<uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
DownloadManagerdownloadManager=(DownloadManager)getSystemService(DOWNLOAD_SERVICE);//文件下载地址String url="http://v.yingshibao.chuanke.com//001_zongshu.mp4";//创建一个Request对象DownloadManager.Request request=newDownloadManager.Request(Uri.parse(url));//设置下载文件路径request.setDestinationInExternalPublicDir("itbox","zongshu.mp4");//开始下载longdownloadId=downloadManager.enqueue(request);
class DownloadChangeObserver extends ContentObserver {private Handler handler;private long downloadId;public DownloadChangeObserver(Handler handler, long downloadId) {super(handler);this.handler = handler;this.downloadId = downloadId;}@Overridepublic void onChange(boolean selfChange) {updateView(handler, downloadId);}}
mContext.getContentResolver().registerContentObserver(Uri.parse("content://downloads/my_downloads"),true,new DownloadChangeObserver(handler,downloadId));
public void updateView(Handler handler, long downloadId) {// 获取状态和字节int[] bytesAndStatus = getBytesAndStatus(downloadId);//handler.sendMessage(handler.obtainMessage(0, bytesAndStatus[0],bytesAndStatus[1], bytesAndStatus[2]));}public int[] getBytesAndStatus(long downloadId) {int[] bytesAndStatus = new int[] { -1, -1, 0 };DownloadManager.Query query = new DownloadManager.Query().setFilterById(downloadId);Cursor c = null;try {c = downloadManager.query(query);if (c != null && c.moveToFirst()) {// 当前下载的字节bytesAndStatus[0] = c.getInt(c.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));// 总字节数bytesAndStatus[1] = c.getInt(c.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));// 状态bytesAndStatus[2] = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));}} finally {if (c != null) {c.close();}}return bytesAndStatus;}
registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));BroadcastReceiver receiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {Log.v("chadm", "action = " + action);}}};

public long enqueue(Request request) {ContentValues values = request.toContentValues(mPackageName);Uri downloadUri = mResolver.insert(Downloads.Impl.CONTENT_URI, values);long id = Long.parseLong(downloadUri.getLastPathSegment());return id;}
/*** Inserts a row in the database*/@Overridepublic Uri insert(final Uri uri, final ContentValues values) {//检查权限,如果没有相应权限,则remove相关数据,插入一条空记录checkInsertPermissions(values);SQLiteDatabase db = mOpenHelper.getWritableDatabase();// note we disallow inserting into ALL_DOWNLOADSint match = sURIMatcher.match(uri);//判断Uri,只支持对MY_DOWNLOADS的插入操作if (match != MY_DOWNLOADS) {Log.d(Constants.TAG, "calling insert on an unknown/invalid URI: " + uri);throw new IllegalArgumentException("Unknown/Invalid URI " + uri);}// copy some of the input values as itContentValues filteredValues = new ContentValues();copyString(Downloads.Impl.COLUMN_URI, values, filteredValues);copyString(Downloads.Impl.COLUMN_APP_DATA, values, filteredValues);copyBoolean(Downloads.Impl.COLUMN_NO_INTEGRITY, values, filteredValues);copyString(Downloads.Impl.COLUMN_FILE_NAME_HINT, values, filteredValues);copyString(Downloads.Impl.COLUMN_MIME_TYPE, values, filteredValues);copyBoolean(Downloads.Impl.COLUMN_IS_PUBLIC_API, values, filteredValues);boolean isPublicApi =values.getAsBoolean(Downloads.Impl.COLUMN_IS_PUBLIC_API) == Boolean.TRUE;// validate the destination columnInteger dest = values.getAsInteger(Downloads.Impl.COLUMN_DESTINATION);if (dest != null) {if (getContext().checkCallingPermission(Downloads.Impl.PERMISSION_ACCESS_ADVANCED)!= PackageManager.PERMISSION_GRANTED&& (dest == Downloads.Impl.DESTINATION_CACHE_PARTITION|| dest == Downloads.Impl.DESTINATION_CACHE_PARTITION_NOROAMING|| dest == Downloads.Impl.DESTINATION_SYSTEMCACHE_PARTITION)) {throw new SecurityException("setting destination to : " + dest +" not allowed, unless PERMISSION_ACCESS_ADVANCED is granted");}// for public API behavior, if an app has CACHE_NON_PURGEABLE permission, automatically// switch to non-purgeable downloadboolean hasNonPurgeablePermission =getContext().checkCallingPermission(Downloads.Impl.PERMISSION_CACHE_NON_PURGEABLE)== PackageManager.PERMISSION_GRANTED;if (isPublicApi && dest == Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE&& hasNonPurgeablePermission) {dest = Downloads.Impl.DESTINATION_CACHE_PARTITION;}if (dest == Downloads.Impl.DESTINATION_FILE_URI) {getContext().enforcePermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE,Binder.getCallingPid(), Binder.getCallingUid(),"need WRITE_EXTERNAL_STORAGE permission to use DESTINATION_FILE_URI");checkFileUriDestination(values);} else if (dest == Downloads.Impl.DESTINATION_SYSTEMCACHE_PARTITION) {getContext().enforcePermission(android.Manifest.permission.ACCESS_CACHE_FILESYSTEM,Binder.getCallingPid(), Binder.getCallingUid(),"need ACCESS_CACHE_FILESYSTEM permission to use system cache");}filteredValues.put(Downloads.Impl.COLUMN_DESTINATION, dest);}// validate the visibility columnInteger vis = values.getAsInteger(Downloads.Impl.COLUMN_VISIBILITY);if (vis == null) {if (dest == Downloads.Impl.DESTINATION_EXTERNAL) {filteredValues.put(Downloads.Impl.COLUMN_VISIBILITY,Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);} else {filteredValues.put(Downloads.Impl.COLUMN_VISIBILITY,Downloads.Impl.VISIBILITY_HIDDEN);}} else {filteredValues.put(Downloads.Impl.COLUMN_VISIBILITY, vis);}// copy the control column as iscopyInteger(Downloads.Impl.COLUMN_CONTROL, values, filteredValues);/** requests coming from* DownloadManager.addCompletedDownload(String, String, String,* boolean, String, String, long) need special treatment*/if (values.getAsInteger(Downloads.Impl.COLUMN_DESTINATION) ==Downloads.Impl.DESTINATION_NON_DOWNLOADMANAGER_DOWNLOAD) {// these requests always are marked as ‘completed‘filteredValues.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_SUCCESS);filteredValues.put(Downloads.Impl.COLUMN_TOTAL_BYTES,values.getAsLong(Downloads.Impl.COLUMN_TOTAL_BYTES));filteredValues.put(Downloads.Impl.COLUMN_CURRENT_BYTES, 0);copyInteger(Downloads.Impl.COLUMN_MEDIA_SCANNED, values, filteredValues);copyString(Downloads.Impl._DATA, values, filteredValues);copyBoolean(Downloads.Impl.COLUMN_ALLOW_WRITE, values, filteredValues);} else {filteredValues.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_PENDING);filteredValues.put(Downloads.Impl.COLUMN_TOTAL_BYTES, -1);filteredValues.put(Downloads.Impl.COLUMN_CURRENT_BYTES, 0);}// set lastupdate to current timelong lastMod = mSystemFacade.currentTimeMillis();filteredValues.put(Downloads.Impl.COLUMN_LAST_MODIFICATION, lastMod);// use packagename of the caller to set the notification columnsString pckg = values.getAsString(Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE);String clazz = values.getAsString(Downloads.Impl.COLUMN_NOTIFICATION_CLASS);if (pckg != null && (clazz != null || isPublicApi)) {int uid = Binder.getCallingUid();try {if (uid == 0 || mSystemFacade.userOwnsPackage(uid, pckg)) {filteredValues.put(Downloads.Impl.COLUMN_NOTIFICATION_PACKAGE, pckg);if (clazz != null) {filteredValues.put(Downloads.Impl.COLUMN_NOTIFICATION_CLASS, clazz);}}} catch (PackageManager.NameNotFoundException ex) {/* ignored for now */}}// copy some more columns as iscopyString(Downloads.Impl.COLUMN_NOTIFICATION_EXTRAS, values, filteredValues);copyString(Downloads.Impl.COLUMN_COOKIE_DATA, values, filteredValues);copyString(Downloads.Impl.COLUMN_USER_AGENT, values, filteredValues);copyString(Downloads.Impl.COLUMN_REFERER, values, filteredValues);// UID, PID columnsif (getContext().checkCallingPermission(Downloads.Impl.PERMISSION_ACCESS_ADVANCED)== PackageManager.PERMISSION_GRANTED) {copyInteger(Downloads.Impl.COLUMN_OTHER_UID, values, filteredValues);}filteredValues.put(Constants.UID, Binder.getCallingUid());if (Binder.getCallingUid() == 0) {copyInteger(Constants.UID, values, filteredValues);}// copy some more columns as iscopyStringWithDefault(Downloads.Impl.COLUMN_TITLE, values, filteredValues, "");copyStringWithDefault(Downloads.Impl.COLUMN_DESCRIPTION, values, filteredValues, "");// is_visible_in_downloads_ui columnif (values.containsKey(Downloads.Impl.COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI)) {copyBoolean(Downloads.Impl.COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI, values, filteredValues);} else {// by default, make external downloads visible in the UIboolean isExternal = (dest == null || dest == Downloads.Impl.DESTINATION_EXTERNAL);filteredValues.put(Downloads.Impl.COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI, isExternal);}// public api requests and networktypes/roaming columnsif (isPublicApi) {copyInteger(Downloads.Impl.COLUMN_ALLOWED_NETWORK_TYPES, values, filteredValues);copyBoolean(Downloads.Impl.COLUMN_ALLOW_ROAMING, values, filteredValues);copyBoolean(Downloads.Impl.COLUMN_ALLOW_METERED, values, filteredValues);}if (Constants.LOGVV) {Log.v(Constants.TAG, "initiating download with UID "+ filteredValues.getAsInteger(Constants.UID));if (filteredValues.containsKey(Downloads.Impl.COLUMN_OTHER_UID)) {Log.v(Constants.TAG, "other UID " +filteredValues.getAsInteger(Downloads.Impl.COLUMN_OTHER_UID));}}//将数据插入到DB里面long rowID = db.insert(DB_TABLE, null, filteredValues);if (rowID == -1) {Log.d(Constants.TAG, "couldn‘t insert into downloads database");return null;}//将请求头数据插入到DB里面insertRequestHeaders(db, rowID, values);//通知有内容改变notifyContentChanged(uri, match);// Always start service to handle notifications and/or scanningfinal Context context = getContext();//启动DownloadService开始下载context.startService(new Intent(context, DownloadService.class));return ContentUris.withAppendedId(Downloads.Impl.CONTENT_URI, rowID);}
@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {int returnValue = super.onStartCommand(intent, flags, startId);if (Constants.LOGVV) {Log.v(Constants.TAG, "Service onStart");}mLastStartId = startId;enqueueUpdate();return returnValue;}
private void enqueueUpdate() {mUpdateHandler.removeMessages(MSG_UPDATE);mUpdateHandler.obtainMessage(MSG_UPDATE, mLastStartId, -1).sendToTarget();}
private Handler.Callback mUpdateCallback = new Handler.Callback() {@Overridepublic boolean handleMessage(Message msg) {Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);final int startId = msg.arg1;if (DEBUG_LIFECYCLE) Log.v(TAG, "Updating for startId " + startId);// Since database is current source of truth, our "active" status// depends on database state. We always get one final update pass// once the real actions have finished and persisted their state.// TODO: switch to asking real tasks to derive active state// TODO: handle media scanner timeoutsfinal boolean isActive;synchronized (mDownloads) {isActive = updateLocked();}if (msg.what == MSG_FINAL_UPDATE) {// Dump thread stacks belonging to poolfor (Map.Entry<Thread, StackTraceElement[]> entry :Thread.getAllStackTraces().entrySet()) {if (entry.getKey().getName().startsWith("pool")) {Log.d(TAG, entry.getKey() + ": " + Arrays.toString(entry.getValue()));}}// Dump speed and update detailsmNotifier.dumpSpeeds();Log.wtf(TAG, "Final update pass triggered, isActive=" + isActive+ "; someone didn‘t update correctly.");}if (isActive) {// Still doing useful work, keep service alive. These active// tasks will trigger another update pass when they‘re finished.// Enqueue delayed update pass to catch finished operations that// didn‘t trigger an update pass; these are bugs.enqueueFinalUpdate();} else {// No active tasks, and any pending update messages can be// ignored, since any updates important enough to initiate tasks// will always be delivered with a new startId.if (stopSelfResult(startId)) {if (DEBUG_LIFECYCLE) Log.v(TAG, "Nothing left; stopped");getContentResolver().unregisterContentObserver(mObserver);mScanner.shutdown();mUpdateThread.quit();}}return true;}};
private boolean updateLocked() {final long now = mSystemFacade.currentTimeMillis();boolean isActive = false;long nextActionMillis = Long.MAX_VALUE;final Set<Long> staleIds = Sets.newHashSet(mDownloads.keySet());final ContentResolver resolver = getContentResolver();final Cursor cursor = resolver.query(Downloads.Impl.ALL_DOWNLOADS_CONTENT_URI,null, null, null, null);try {//更新DB里面所有下载记录final DownloadInfo.Reader reader = new DownloadInfo.Reader(resolver, cursor);final int idColumn = cursor.getColumnIndexOrThrow(Downloads.Impl._ID);while (cursor.moveToNext()) {final long id = cursor.getLong(idColumn);staleIds.remove(id);DownloadInfo info = mDownloads.get(id);//如果下载信息保存在mDownloads里面,则直接更新,由于我们是新添加的一个任务,info为空,走insertDownloadLocked这一步if (info != null) {updateDownload(reader, info, now);} else {//创建一个新的DownloadInfo,然后添加到mDownloads里面去info = insertDownloadLocked(reader, now);}if (info.mDeleted) {// Delete download if requested, but only after cleaning upif (!TextUtils.isEmpty(info.mMediaProviderUri)) {resolver.delete(Uri.parse(info.mMediaProviderUri), null, null);}deleteFileIfExists(info.mFileName);resolver.delete(info.getAllDownloadsUri(), null, null);} else {// Kick off download task if ready 准备开始下载final boolean activeDownload = info.startDownloadIfReady(mExecutor);// Kick off media scan if completedfinal boolean activeScan = info.startScanIfReady(mScanner);if (DEBUG_LIFECYCLE && (activeDownload || activeScan)) {Log.v(TAG, "Download " + info.mId + ": activeDownload=" + activeDownload+ ", activeScan=" + activeScan);}isActive |= activeDownload;isActive |= activeScan;}// Keep track of nearest next actionnextActionMillis = Math.min(info.nextActionMillis(now), nextActionMillis);}} finally {cursor.close();}// Clean up stale downloads that disappearedfor (Long id : staleIds) {deleteDownloadLocked(id);}// Update notifications visible to usermNotifier.updateWith(mDownloads.values());// Set alarm when next action is in future. It‘s okay if the service// continues to run in meantime, since it will kick off an update pass.if (nextActionMillis > 0 && nextActionMillis < Long.MAX_VALUE) {if (Constants.LOGV) {Log.v(TAG, "scheduling start in " + nextActionMillis + "ms");}final Intent intent = new Intent(Constants.ACTION_RETRY);intent.setClass(this, DownloadReceiver.class);mAlarmManager.set(AlarmManager.RTC_WAKEUP, now + nextActionMillis,PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_ONE_SHOT));}return isActive;}
public boolean startDownloadIfReady(ExecutorService executor) {synchronized (this) {//判断是否可以下载,由于mControl为0,返回truefinal boolean isReady = isReadyToDownload();//判断是否有任务正在进行,对象是新创建的,mSubmittedTask 为空final boolean isActive = mSubmittedTask != null && !mSubmittedTask.isDone();if (isReady && !isActive) {//如果当前状态不是正在下载,将当前状态更新为正在下载if (mStatus != Impl.STATUS_RUNNING) {mStatus = Impl.STATUS_RUNNING;ContentValues values = new ContentValues();values.put(Impl.COLUMN_STATUS, mStatus);mContext.getContentResolver().update(getAllDownloadsUri(), values, null, null);}//开始下载任务mTask = new DownloadThread(mContext, mSystemFacade, this, mStorageManager, mNotifier);mSubmittedTask = executor.submit(mTask);}return isReady;}}
@Overridepublic void run() {Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);try {runInternal();} finally {mNotifier.notifyDownloadSpeed(mInfo.mId, 0);}}private void runInternal() {// Skip when download already marked as finished; this download was// probably started again while racing with UpdateThread.if (DownloadInfo.queryDownloadStatus(mContext.getContentResolver(), mInfo.mId)== Downloads.Impl.STATUS_SUCCESS) {Log.d(TAG, "Download " + mInfo.mId + " already finished; skipping");return;}State state = new State(mInfo);PowerManager.WakeLock wakeLock = null;int finalStatus = Downloads.Impl.STATUS_UNKNOWN_ERROR;int numFailed = mInfo.mNumFailed;String errorMsg = null;final NetworkPolicyManager netPolicy = NetworkPolicyManager.from(mContext);final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);try {wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, Constants.TAG);wakeLock.setWorkSource(new WorkSource(mInfo.mUid));wakeLock.acquire();// while performing download, register for rules updatesnetPolicy.registerListener(mPolicyListener);Log.i(Constants.TAG, "Download " + mInfo.mId + " starting");// Remember which network this download started on; used to// determine if errors were due to network changes.final NetworkInfo info = mSystemFacade.getActiveNetworkInfo(mInfo.mUid);if (info != null) {state.mNetworkType = info.getType();}// Network traffic on this thread should be counted against the// requesting UID, and is tagged with well-known value.TrafficStats.setThreadStatsTag(TrafficStats.TAG_SYSTEM_DOWNLOAD);TrafficStats.setThreadStatsUid(mInfo.mUid);try {// TODO: migrate URL sanity checking into client side of APIstate.mUrl = new URL(state.mRequestUri);} catch (MalformedURLException e) {throw new StopRequestException(STATUS_BAD_REQUEST, e);}//执行下载executeDownload(state);finalizeDestinationFile(state);finalStatus = Downloads.Impl.STATUS_SUCCESS;} catch (StopRequestException error) {// remove the cause before printing, in case it contains PIIerrorMsg = error.getMessage();String msg = "Aborting request for download " + mInfo.mId + ": " + errorMsg;Log.w(Constants.TAG, msg);if (Constants.LOGV) {Log.w(Constants.TAG, msg, error);}finalStatus = error.getFinalStatus();// Nobody below our level should request retries, since we handle// failure counts at this level.if (finalStatus == STATUS_WAITING_TO_RETRY) {throw new IllegalStateException("Execution should always throw final error codes");}// Some errors should be retryable, unless we fail too many times.if (isStatusRetryable(finalStatus)) {if (state.mGotData) {numFailed = 1;} else {numFailed += 1;}if (numFailed < Constants.MAX_RETRIES) {final NetworkInfo info = mSystemFacade.getActiveNetworkInfo(mInfo.mUid);if (info != null && info.getType() == state.mNetworkType&& info.isConnected()) {// Underlying network is still intact, use normal backofffinalStatus = STATUS_WAITING_TO_RETRY;} else {// Network changed, retry on any next availablefinalStatus = STATUS_WAITING_FOR_NETWORK;}}}// fall through to finally block} catch (Throwable ex) {errorMsg = ex.getMessage();String msg = "Exception for id " + mInfo.mId + ": " + errorMsg;Log.w(Constants.TAG, msg, ex);finalStatus = Downloads.Impl.STATUS_UNKNOWN_ERROR;// falls through to the code that reports an error} finally {if (finalStatus == STATUS_SUCCESS) {TrafficStats.incrementOperationCount(1);}TrafficStats.clearThreadStatsTag();TrafficStats.clearThreadStatsUid();cleanupDestination(state, finalStatus);notifyDownloadCompleted(state, finalStatus, errorMsg, numFailed);Log.i(Constants.TAG, "Download " + mInfo.mId + " finished with status "+ Downloads.Impl.statusToString(finalStatus));netPolicy.unregisterListener(mPolicyListener);if (wakeLock != null) {wakeLock.release();wakeLock = null;}}mStorageManager.incrementNumDownloadsSoFar();}
/*** Fully execute a single download request. Setup and send the request,* handle the response, and transfer the data to the destination file.*/private void executeDownload(State state) throws StopRequestException {state.resetBeforeExecute();//设置下载文件相关信息,文件是否存在、是否从0开始下载还是接着下载setupDestinationFile(state);// skip when already finished; remove after fixing race in 5217390if (state.mCurrentBytes == state.mTotalBytes) {Log.i(Constants.TAG, "Skipping initiating request for download " +mInfo.mId + "; already completed");return;}while (state.mRedirectionCount++ < Constants.MAX_REDIRECTS) {// Open connection and follow any redirects until we have a useful// response with body.HttpURLConnection conn = null;try {checkConnectivity();conn = (HttpURLConnection) state.mUrl.openConnection();conn.setInstanceFollowRedirects(false);conn.setConnectTimeout(DEFAULT_TIMEOUT);conn.setReadTimeout(DEFAULT_TIMEOUT);addRequestHeaders(state, conn);final int responseCode = conn.getResponseCode();switch (responseCode) {case HTTP_OK:if (state.mContinuingDownload) {throw new StopRequestException(STATUS_CANNOT_RESUME, "Expected partial, but received OK");}processResponseHeaders(state, conn);transferData(state, conn);return;case HTTP_PARTIAL:if (!state.mContinuingDownload) {throw new StopRequestException(STATUS_CANNOT_RESUME, "Expected OK, but received partial");}transferData(state, conn);return;case HTTP_MOVED_PERM:case HTTP_MOVED_TEMP:case HTTP_SEE_OTHER:case HTTP_TEMP_REDIRECT:final String location = conn.getHeaderField("Location");state.mUrl = new URL(state.mUrl, location);if (responseCode == HTTP_MOVED_PERM) {// Push updated URL back to databasestate.mRequestUri = state.mUrl.toString();}continue;case HTTP_REQUESTED_RANGE_NOT_SATISFIABLE:throw new StopRequestException(STATUS_CANNOT_RESUME, "Requested range not satisfiable");case HTTP_UNAVAILABLE:parseRetryAfterHeaders(state, conn);throw new StopRequestException(HTTP_UNAVAILABLE, conn.getResponseMessage());case HTTP_INTERNAL_ERROR:throw new StopRequestException(HTTP_INTERNAL_ERROR, conn.getResponseMessage());default:StopRequestException.throwUnhandledHttpError(responseCode, conn.getResponseMessage());}} catch (IOException e) {// Trouble with low-level socketsthrow new StopRequestException(STATUS_HTTP_DATA_ERROR, e);} finally {if (conn != null) conn.disconnect();}}throw new StopRequestException(STATUS_TOO_MANY_REDIRECTS, "Too many redirects");}
private void addRequestHeaders(State state, HttpURLConnection conn) {for (Pair<String, String> header : mInfo.getHeaders()) {conn.addRequestProperty(header.first, header.second);}// Only splice in user agent when not already definedif (conn.getRequestProperty("User-Agent") == null) {conn.addRequestProperty("User-Agent", userAgent());}// Defeat transparent gzip compression, since it doesn‘t allow us to// easily resume partial downloads.conn.setRequestProperty("Accept-Encoding", "identity");if (state.mContinuingDownload) {if (state.mHeaderETag != null) {conn.addRequestProperty("If-Match", state.mHeaderETag);}conn.addRequestProperty("Range", "bytes=" + state.mCurrentBytes + "-");}}
public void onReceive(final Context context, final Intent intent) {if (mSystemFacade == null) {mSystemFacade = new RealSystemFacade(context);}String action = intent.getAction();if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {if (Constants.LOGVV) {Log.v(Constants.TAG, "Received broadcast intent for " +Intent.ACTION_BOOT_COMPLETED);}startService(context);} else if (action.equals(Intent.ACTION_MEDIA_MOUNTED)) {if (Constants.LOGVV) {Log.v(Constants.TAG, "Received broadcast intent for " +Intent.ACTION_MEDIA_MOUNTED);}startService(context);} else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {final ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);final NetworkInfo info = connManager.getActiveNetworkInfo();if (info != null && info.isConnected()) {startService(context);}} else if (action.equals(Constants.ACTION_RETRY)) {startService(context);} else if (action.equals(Constants.ACTION_OPEN)|| action.equals(Constants.ACTION_LIST)|| action.equals(Constants.ACTION_HIDE)) {final PendingResult result = goAsync();if (result == null) {// TODO: remove this once test is refactoredhandleNotificationBroadcast(context, intent);} else {sAsyncHandler.post(new Runnable() {@Overridepublic void run() {handleNotificationBroadcast(context, intent);result.finish();}});}}}
Android 下载模块分析(DownloadManager和DownloadProvider)
原文:http://www.cnblogs.com/adm1989/p/4631129.html