http://www.oschina.net/code/explore/android-2.2-froyo/com/android/mms/util/DownloadManager.java
/** |
002 |
* Copyright (C) 2008 Esmertec AG. |
003 |
* Copyright (C) 2008 The Android Open Source Project |
004 |
* |
005 |
* Licensed under the Apache License, Version 2.0 (the "License"); |
006 |
* you may not use this file except in compliance with the License. |
007 |
* You may obtain a copy of the License at |
008 |
* |
009 |
* http://www.apache.org/licenses/LICENSE-2.0 |
010 |
* |
011 |
* Unless required by applicable law or agreed to in writing, software |
012 |
* distributed under the License is distributed on an "AS IS" BASIS, |
013 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
014 |
* See the License for the specific language governing permissions and |
015 |
* limitations under the License. |
016 |
*/ |
017 |
|
018 |
package com.android.mms.util; |
019 |
|
020 |
import com.android.mms.R; |
021 |
import com.android.mms.data.Contact; |
022 |
import com.android.mms.ui.MessagingPreferenceActivity; |
023 |
import com.google.android.mms.MmsException; |
024 |
import com.google.android.mms.pdu.EncodedStringValue; |
025 |
import com.google.android.mms.pdu.NotificationInd; |
026 |
import com.google.android.mms.pdu.PduPersister; |
027 |
import android.database.sqlite.SqliteWrapper; |
028 |
import com.android.internal.telephony.TelephonyIntents; |
029 |
import com.android.internal.telephony.TelephonyProperties; |
030 |
|
031 |
import android.content.BroadcastReceiver; |
032 |
import android.content.ContentValues; |
033 |
import android.content.Context; |
034 |
import android.content.Intent; |
035 |
import android.content.IntentFilter; |
036 |
import android.content.SharedPreferences; |
037 |
import android.content.SharedPreferences.OnSharedPreferenceChangeListener; |
038 |
import android.database.Cursor; |
039 |
import android.net.Uri; |
040 |
import android.os.Handler; |
041 |
import android.preference.PreferenceManager; |
042 |
import android.provider.Telephony.Mms; |
043 |
import android.telephony.ServiceState; |
044 |
import android.util.Config; |
045 |
import android.util.Log; |
046 |
import android.widget.Toast; |
047 |
|
048 |
import android.os.SystemProperties; |
049 |
|
050 |
public class DownloadManager { |
051 |
private static final String TAG = "DownloadManager" ; |
052 |
private static final boolean DEBUG = false ; |
053 |
private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV; |
054 |
|
055 |
private static final int DEFERRED_MASK = 0x04 ; |
056 |
|
057 |
public static final int STATE_UNSTARTED = 0x80 ; |
058 |
public static final int STATE_DOWNLOADING = 0x81 ; |
059 |
public static final int STATE_TRANSIENT_FAILURE = 0x82 ; |
060 |
public static final int STATE_PERMANENT_FAILURE = 0x87 ; |
061 |
|
062 |
private final Context mContext; |
063 |
private final Handler mHandler; |
064 |
private final SharedPreferences mPreferences; |
065 |
private boolean mAutoDownload; |
066 |
|
067 |
private final OnSharedPreferenceChangeListener mPreferencesChangeListener = |
068 |
new OnSharedPreferenceChangeListener() { |
069 |
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { |
070 |
if (MessagingPreferenceActivity.AUTO_RETRIEVAL.equals(key) |
071 |
|| MessagingPreferenceActivity.RETRIEVAL_DURING_ROAMING.equals(key)) { |
072 |
if (LOCAL_LOGV) { |
073 |
Log.v(TAG, "Preferences updated." ); |
074 |
} |
075 |
|
076 |
synchronized (sInstance) { |
077 |
mAutoDownload = getAutoDownloadState(prefs); |
078 |
if (LOCAL_LOGV) { |
079 |
Log.v(TAG, "mAutoDownload ------> " + mAutoDownload); |
080 |
} |
081 |
} |
082 |
} |
083 |
} |
084 |
}; |
085 |
|
086 |
private final BroadcastReceiver mRoamingStateListener = |
087 |
new BroadcastReceiver() { |
088 |
@Override |
089 |
public void onReceive(Context context, Intent intent) { |
090 |
if (TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(intent.getAction())) { |
091 |
if (LOCAL_LOGV) { |
092 |
Log.v(TAG, "Service state changed: " + intent.getExtras()); |
093 |
} |
094 |
|
095 |
ServiceState state = ServiceState.newFromBundle(intent.getExtras()); |
096 |
boolean isRoaming = state.getRoaming(); |
097 |
if (LOCAL_LOGV) { |
098 |
Log.v(TAG, "roaming ------> " + isRoaming); |
099 |
} |
100 |
synchronized (sInstance) { |
101 |
mAutoDownload = getAutoDownloadState(mPreferences, isRoaming); |
102 |
if (LOCAL_LOGV) { |
103 |
Log.v(TAG, "mAutoDownload ------> " + mAutoDownload); |
104 |
} |
105 |
} |
106 |
} |
107 |
} |
108 |
}; |
109 |
|
110 |
private static DownloadManager sInstance; |
111 |
|
112 |
private DownloadManager(Context context) { |
113 |
mContext = context; |
114 |
mHandler = new Handler(); |
115 |
mPreferences = PreferenceManager.getDefaultSharedPreferences(context); |
116 |
mPreferences.registerOnSharedPreferenceChangeListener(mPreferencesChangeListener); |
117 |
|
118 |
context.registerReceiver( |
119 |
mRoamingStateListener, |
120 |
new IntentFilter(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)); |
121 |
|
122 |
mAutoDownload = getAutoDownloadState(mPreferences); |
123 |
if (LOCAL_LOGV) { |
124 |
Log.v(TAG, "mAutoDownload ------> " + mAutoDownload); |
125 |
} |
126 |
} |
127 |
|
128 |
public boolean isAuto() { |
129 |
return mAutoDownload; |
130 |
} |
131 |
|
132 |
public static void init(Context context) { |
133 |
if (LOCAL_LOGV) { |
134 |
Log.v(TAG, "DownloadManager.init()" ); |
135 |
} |
136 |
|
137 |
if (sInstance != null ) { |
138 |
Log.w(TAG, "Already initialized." ); |
139 |
} |
140 |
sInstance = new DownloadManager(context); |
141 |
} |
142 |
|
143 |
public static DownloadManager getInstance() { |
144 |
if (sInstance == null ) { |
145 |
throw new IllegalStateException( "Uninitialized." ); |
146 |
} |
147 |
return sInstance; |
148 |
} |
149 |
|
150 |
static boolean getAutoDownloadState(SharedPreferences prefs) { |
151 |
return getAutoDownloadState(prefs, isRoaming()); |
152 |
} |
153 |
|
154 |
static boolean getAutoDownloadState(SharedPreferences prefs, boolean roaming) { |
155 |
boolean autoDownload = prefs.getBoolean( |
156 |
MessagingPreferenceActivity.AUTO_RETRIEVAL, true ); |
157 |
|
158 |
if (LOCAL_LOGV) { |
159 |
Log.v(TAG, "auto download without roaming -> " + autoDownload); |
160 |
} |
161 |
|
162 |
if (autoDownload) { |
163 |
boolean alwaysAuto = prefs.getBoolean( |
164 |
MessagingPreferenceActivity.RETRIEVAL_DURING_ROAMING, false ); |
165 |
|
166 |
if (LOCAL_LOGV) { |
167 |
Log.v(TAG, "auto download during roaming -> " + alwaysAuto); |
168 |
} |
169 |
|
170 |
if (!roaming || alwaysAuto) { |
171 |
return true ; |
172 |
} |
173 |
} |
174 |
return false ; |
175 |
} |
176 |
|
177 |
static boolean isRoaming() { |
178 |
// TODO: fix and put in Telephony layer |
179 |
String roaming = SystemProperties.get( |
180 |
TelephonyProperties.PROPERTY_OPERATOR_ISROAMING, null ); |
181 |
if (LOCAL_LOGV) { |
182 |
Log.v(TAG, "roaming ------> " + roaming); |
183 |
} |
184 |
return "true" .equals(roaming); |
185 |
} |
186 |
|
187 |
public void markState( final Uri uri, int state) { |
188 |
// Notify user if the message has expired. |
189 |
try { |
190 |
NotificationInd nInd = (NotificationInd) PduPersister.getPduPersister(mContext) |
191 |
.load(uri); |
192 |
if ((nInd.getExpiry() < System.currentTimeMillis()/1000L) |
193 |
&& (state == STATE_DOWNLOADING)) { |
194 |
mHandler.post( new Runnable() { |
195 |
public void run() { |
196 |
Toast.makeText(mContext, R.string.dl_expired_notification, |
197 |
Toast.LENGTH_LONG).show(); |
198 |
} |
199 |
}); |
200 |
SqliteWrapper.delete(mContext, mContext.getContentResolver(), uri, null , null ); |
201 |
return ; |
202 |
} |
203 |
} catch (MmsException e) { |
204 |
Log.e(TAG, e.getMessage(), e); |
205 |
return ; |
206 |
} |
207 |
|
208 |
// Notify user if downloading permanently failed. |
209 |
if (state == STATE_PERMANENT_FAILURE) { |
210 |
mHandler.post( new Runnable() { |
211 |
public void run() { |
212 |
try { |
213 |
Toast.makeText(mContext, getMessage(uri), |
214 |
Toast.LENGTH_LONG).show(); |
215 |
} catch (MmsException e) { |
216 |
Log.e(TAG, e.getMessage(), e); |
217 |
} |
218 |
} |
219 |
}); |
220 |
} else if (!mAutoDownload) { |
221 |
state |= DEFERRED_MASK; |
222 |
} |
223 |
|
224 |
// Use the STATUS field to store the state of downloading process |
225 |
// because it's useless for M-Notification.ind. |
226 |
ContentValues values = new ContentValues( 1 ); |
227 |
values.put(Mms.STATUS, state); |
228 |
SqliteWrapper.update(mContext, mContext.getContentResolver(), |
229 |
uri, values, null , null ); |
230 |
} |
231 |
|
232 |
public void showErrorCodeToast( int errorStr) { |
233 |
final int errStr = errorStr; |
234 |
mHandler.post( new Runnable() { |
235 |
public void run() { |
236 |
try { |
237 |
Toast.makeText(mContext, errStr, Toast.LENGTH_LONG).show(); |
238 |
} catch (Exception e) { |
239 |
Log.e(TAG, "Caught an exception in showErrorCodeToast" ); |
240 |
} |
241 |
} |
242 |
}); |
243 |
} |
244 |
|
245 |
private String getMessage(Uri uri) throws MmsException { |
246 |
NotificationInd ind = (NotificationInd) PduPersister |
247 |
.getPduPersister(mContext).load(uri); |
248 |
|
249 |
EncodedStringValue v = ind.getSubject(); |
250 |
String subject = (v != null ) ? v.getString() |
251 |
: mContext.getString(R.string.no_subject); |
252 |
|
253 |
v = ind.getFrom(); |
254 |
String from = (v != null ) |
255 |
? Contact.get(v.getString(), false ).getName() |
256 |
: mContext.getString(R.string.unknown_sender); |
257 |
|
258 |
return mContext.getString(R.string.dl_failure_notification, subject, from); |
259 |
} |
260 |
|
261 |
public int getState(Uri uri) { |
262 |
Cursor cursor = SqliteWrapper.query(mContext, mContext.getContentResolver(), |
263 |
uri, new String[] {Mms.STATUS}, null , null , null ); |
264 |
|
265 |
if (cursor != null ) { |
266 |
try { |
267 |
if (cursor.moveToFirst()) { |
268 |
return cursor.getInt( 0 ) &~ DEFERRED_MASK; |
269 |
} |
270 |
} finally { |
271 |
cursor.close(); |
272 |
} |
273 |
} |
274 |
return STATE_UNSTARTED; |
275 |
} |
276 |
} |
/** |
002 |
* Copyright (C) 2008 Esmertec AG. |
003 |
* Copyright (C) 2008 The Android Open Source Project |
004 |
* |
005 |
* Licensed under the Apache License, Version 2.0 (the "License"); |
006 |
* you may not use this file except in compliance with the License. |
007 |
* You may obtain a copy of the License at |
008 |
* |
009 |
* http://www.apache.org/licenses/LICENSE-2.0 |
010 |
* |
011 |
* Unless required by applicable law or agreed to in writing, software |
012 |
* distributed under the License is distributed on an "AS IS" BASIS, |
013 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
014 |
* See the License for the specific language governing permissions and |
015 |
* limitations under the License. |
016 |
*/ |
017 |
|
018 |
package com.android.mms.util; |
019 |
|
020 |
import com.android.mms.R; |
021 |
import com.android.mms.data.Contact; |
022 |
import com.android.mms.ui.MessagingPreferenceActivity; |
023 |
import com.google.android.mms.MmsException; |
024 |
import com.google.android.mms.pdu.EncodedStringValue; |
025 |
import com.google.android.mms.pdu.NotificationInd; |
026 |
import com.google.android.mms.pdu.PduPersister; |
027 |
import android.database.sqlite.SqliteWrapper; |
028 |
import com.android.internal.telephony.TelephonyIntents; |
029 |
import com.android.internal.telephony.TelephonyProperties; |
030 |
|
031 |
import android.content.BroadcastReceiver; |
032 |
import android.content.ContentValues; |
033 |
import android.content.Context; |
034 |
import android.content.Intent; |
035 |
import android.content.IntentFilter; |
036 |
import android.content.SharedPreferences; |
037 |
import android.content.SharedPreferences.OnSharedPreferenceChangeListener; |
038 |
import android.database.Cursor; |
039 |
import android.net.Uri; |
040 |
import android.os.Handler; |
041 |
import android.preference.PreferenceManager; |
042 |
import android.provider.Telephony.Mms; |
043 |
import android.telephony.ServiceState; |
044 |
import android.util.Config; |
045 |
import android.util.Log; |
046 |
import android.widget.Toast; |
047 |
|
048 |
import android.os.SystemProperties; |
049 |
|
050 |
public class DownloadManager { |
051 |
private static final String TAG = "DownloadManager" ; |
052 |
private static final boolean DEBUG = false ; |
053 |
private static final boolean LOCAL_LOGV = DEBUG ? Config.LOGD : Config.LOGV; |
054 |
|
055 |
private static final int DEFERRED_MASK = 0x04 ; |
056 |
|
057 |
public static final int STATE_UNSTARTED = 0x80 ; |
058 |
public static final int STATE_DOWNLOADING = 0x81 ; |
059 |
public static final int STATE_TRANSIENT_FAILURE = 0x82 ; |
060 |
public static final int STATE_PERMANENT_FAILURE = 0x87 ; |
061 |
|
062 |
private final Context mContext; |
063 |
private final Handler mHandler; |
064 |
private final SharedPreferences mPreferences; |
065 |
private boolean mAutoDownload; |
066 |
|
067 |
private final OnSharedPreferenceChangeListener mPreferencesChangeListener = |
068 |
new OnSharedPreferenceChangeListener() { |
069 |
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { |
070 |
if (MessagingPreferenceActivity.AUTO_RETRIEVAL.equals(key) |
071 |
|| MessagingPreferenceActivity.RETRIEVAL_DURING_ROAMING.equals(key)) { |
072 |
if (LOCAL_LOGV) { |
073 |
Log.v(TAG, "Preferences updated." ); |
074 |
} |
075 |
|
076 |
synchronized (sInstance) { |
077 |
mAutoDownload = getAutoDownloadState(prefs); |
078 |
if (LOCAL_LOGV) { |
079 |
Log.v(TAG, "mAutoDownload ------> " + mAutoDownload); |
080 |
} |
081 |
} |
082 |
} |
083 |
} |
084 |
}; |
085 |
|
086 |
private final BroadcastReceiver mRoamingStateListener = |
087 |
new BroadcastReceiver() { |
088 |
@Override |
089 |
public void onReceive(Context context, Intent intent) { |
090 |
if (TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(intent.getAction())) { |
091 |
if (LOCAL_LOGV) { |
092 |
Log.v(TAG, "Service state changed: " + intent.getExtras()); |
093 |
} |
094 |
|
095 |
ServiceState state = ServiceState.newFromBundle(intent.getExtras()); |
096 |
boolean isRoaming = state.getRoaming(); |
097 |
if (LOCAL_LOGV) { |
098 |
Log.v(TAG, "roaming ------> " + isRoaming); |
099 |
} |
100 |
synchronized (sInstance) { |
101 |
mAutoDownload = getAutoDownloadState(mPreferences, isRoaming); |
102 |
if (LOCAL_LOGV) { |
103 |
Log.v(TAG, "mAutoDownload ------> " + mAutoDownload); |
104 |
} |
105 |
} |
106 |
} |
107 |
} |
108 |
}; |
109 |
|
110 |
private static DownloadManager sInstance; |
111 |
|
112 |
private DownloadManager(Context context) { |
113 |
mContext = context; |
114 |
mHandler = new Handler(); |
115 |
mPreferences = PreferenceManager.getDefaultSharedPreferences(context); |
116 |
mPreferences.registerOnSharedPreferenceChangeListener(mPreferencesChangeListener); |
117 |
|
118 |
context.registerReceiver( |
119 |
mRoamingStateListener, |
120 |
new IntentFilter(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)); |
121 |
|
122 |
mAutoDownload = getAutoDownloadState(mPreferences); |
123 |
if (LOCAL_LOGV) { |
124 |
Log.v(TAG, "mAutoDownload ------> " + mAutoDownload); |
125 |
} |
126 |
} |
127 |
|
128 |
public boolean isAuto() { |
129 |
return mAutoDownload; |
130 |
} |
131 |
|
132 |
public static void init(Context context) { |
133 |
if (LOCAL_LOGV) { |
134 |
Log.v(TAG, "DownloadManager.init()" ); |
135 |
} |
136 |
|
137 |
if (sInstance != null ) { |
138 |
Log.w(TAG, "Already initialized." ); |
139 |
} |
140 |
sInstance = new DownloadManager(context); |
141 |
} |
142 |
|
143 |
public static DownloadManager getInstance() { |
144 |
if (sInstance == null ) { |
145 |
throw new IllegalStateException( "Uninitialized." ); |
146 |
} |
147 |
return sInstance; |
148 |
} |
149 |
|
150 |
static boolean getAutoDownloadState(SharedPreferences prefs) { |
151 |
return getAutoDownloadState(prefs, isRoaming()); |
152 |
} |
153 |
|
154 |
static boolean getAutoDownloadState(SharedPreferences prefs, boolean roaming) { |
155 |
boolean autoDownload = prefs.getBoolean( |
156 |
MessagingPreferenceActivity.AUTO_RETRIEVAL, true ); |
157 |
|
158 |
if (LOCAL_LOGV) { |
159 |
Log.v(TAG, "auto download without roaming -> " + autoDownload); |
160 |
} |
161 |
|
162 |
if (autoDownload) { |
163 |
boolean alwaysAuto = prefs.getBoolean( |
164 |
MessagingPreferenceActivity.RETRIEVAL_DURING_ROAMING, false ); |
165 |
|
166 |
if (LOCAL_LOGV) { |
167 |
Log.v(TAG, "auto download during roaming -> " + alwaysAuto); |
168 |
} |
169 |
|
170 |
if (!roaming || alwaysAuto) { |
171 |
return true ; |
172 |
} |
173 |
} |
174 |
return false ; |
175 |
} |
176 |
|
177 |
static boolean isRoaming() { |
178 |
// TODO: fix and put in Telephony layer |
179 |
String roaming = SystemProperties.get( |
180 |
TelephonyProperties.PROPERTY_OPERATOR_ISROAMING, null ); |
181 |
if (LOCAL_LOGV) { |
182 |
Log.v(TAG, "roaming ------> " + roaming); |
183 |
} |
184 |
return "true" .equals(roaming); |
185 |
} |
186 |
|
187 |
public void markState( final Uri uri, int state) { |
188 |
// Notify user if the message has expired. |
189 |
try { |
190 |
NotificationInd nInd = (NotificationInd) PduPersister.getPduPersister(mContext) |
191 |
.load(uri); |
192 |
if ((nInd.getExpiry() < System.currentTimeMillis()/1000L) |
193 |
&& (state == STATE_DOWNLOADING)) { |
194 |
mHandler.post( new Runnable() { |
195 |
public void run() { |
196 |
Toast.makeText(mContext, R.string.dl_expired_notification, |
197 |
Toast.LENGTH_LONG).show(); |
198 |
} |
199 |
}); |
200 |
SqliteWrapper.delete(mContext, mContext.getContentResolver(), uri, null , null ); |
201 |
return ; |
202 |
} |
203 |
} catch (MmsException e) { |
204 |
Log.e(TAG, e.getMessage(), e); |
205 |
return ; |
206 |
} |
207 |
|
208 |
// Notify user if downloading permanently failed. |
209 |
if (state == STATE_PERMANENT_FAILURE) { |
210 |
mHandler.post( new Runnable() { |
211 |
public void run() { |
212 |
try { |
213 |
Toast.makeText(mContext, getMessage(uri), |
214 |
Toast.LENGTH_LONG).show(); |
215 |
} catch (MmsException e) { |
216 |
Log.e(TAG, e.getMessage(), e); |
217 |
} |
218 |
} |
219 |
}); |
220 |
} else if (!mAutoDownload) { |
221 |
state |= DEFERRED_MASK; |
222 |
} |
223 |
|
224 |
// Use the STATUS field to store the state of downloading process |
225 |
// because it's useless for M-Notification.ind. |
226 |
ContentValues values = new ContentValues( 1 ); |
227 |
values.put(Mms.STATUS, state); |
228 |
SqliteWrapper.update(mContext, mContext.getContentResolver(), |
229 |
uri, values, null , null ); |
230 |
} |
231 |
|
232 |
public void showErrorCodeToast( int errorStr) { |
233 |
final int errStr = errorStr; |
234 |
mHandler.post( new Runnable() { |
235 |
public void run() { |
236 |
try { |
237 |
Toast.makeText(mContext, errStr, Toast.LENGTH_LONG).show(); |
238 |
} catch (Exception e) { |
239 |
Log.e(TAG, "Caught an exception in showErrorCodeToast" ); |
240 |
} |
241 |
} |
242 |
}); |
243 |
} |
244 |
|
245 |
private String getMessage(Uri uri) throws MmsException { |
246 |
NotificationInd ind = (NotificationInd) PduPersister |
247 |
.getPduPersister(mContext).load(uri); |
248 |
|
249 |
EncodedStringValue v = ind.getSubject(); |
250 |
String subject = (v != null ) ? v.getString() |
251 |
: mContext.getString(R.string.no_subject); |
252 |
|
253 |
v = ind.getFrom(); |
254 |
String from = (v != null ) |
255 |
? Contact.get(v.getString(), false ).getName() |
256 |
: mContext.getString(R.string.unknown_sender); |
257 |
|
258 |
return mContext.getString(R.string.dl_failure_notification, subject, from); |
259 |
} |
260 |
|
261 |
public int getState(Uri uri) { |
262 |
Cursor cursor = SqliteWrapper.query(mContext, mContext.getContentResolver(), |
263 |
uri, new String[] {Mms.STATUS}, null , null , null ); |
264 |
|
265 |
if (cursor != null ) { |
266 |
try { |
267 |
if (cursor.moveToFirst()) { |
268 |
return cursor.getInt( 0 ) &~ DEFERRED_MASK; |
269 |
} |
270 |
} finally { |
271 |
cursor.close(); |
272 |
} |
273 |
} |
274 |
return STATE_UNSTARTED; |
275 |
} |
276 |
} |