DownloadManager

Official documentation: https://developer.android.com/reference/android/app/DownloadManager

1. A brief introduction to DownloadManager

DownloadManger is provided by android 2.3 (api level 9) to optimize the handling of long download operations. DownloadManager handles Http/Https connections and monitors state changes in connections and system restarts to ensure that each download task is completed successfully . DownloadManager is a good choice in most cases involving downloading, especially in the background to continue downloading, download status callback, breakpoint resume, download environment settings, download file operations, etc., the support is very good.

DownloadManager is a class that the system opens to third-party applications, including two static inner classes DownloadManager.Query and DownloadManager.Request. DownloadManager.Request is used to request a download , and DownloadManager.Query is used to query download information. For specific interface information, please refer to the last api description.

2. Use Download Manager

DownloadManager mainly provides the following interfaces:

  • public long enqueue(Request request) executes the download and returns downloadId, which can be used to query download information later . If the network does not meet the conditions, the Sdcard is being mounted, or the maximum concurrent number is exceeded, it will wait for the download, and if it is normal, it will be downloaded directly.

  • int remove(long… ids) Delete the download, if the download is in progress, cancel the download. Downloads and records are deleted at the same time.

  • Cursor query(Query query) Query download information.

  • getMaxBytesOverMobile(Context context) returns the maximum value of mobile network downloads

  • rename(Context context, long id, String displayName) Rename the name of the downloaded item

  • getRecommendedMaxBytesOverMobile(Context context) Get recommended mobile network download size

  • Others: By looking at the code we can find that there is also a CursorTranslator private static inner class. This class mainly does a layer of proxy for Query. Make a mapping between DownloadProvider and DownloadManager. More than a dozen states in DownloadProvider correspond to five states in DownloadManager, and the reasons for failure and suspension in DownloadProvider are converted to the reasons for DownloadManager.

3. DownloadManager download example

1. Download the required permissions

<uses-permission android:name="android.permission.INTERNET" />;

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>;

2. Call DownloadManager.Request to start downloading

DownloadManager downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);

String apkUrl = "https://qd.myapp.com/myapp/qqteam/AndroidQQ/mobileqq_android.apk";

DownloadManager.Request request = new 

DownloadManager.Request(Uri.parse(apkUrl));

request.setDestinationInExternalPublicDir("dirType", "/mydownload/QQ.apk");

// request.setTitle("TX QQ");

// request.setDescription("This is TX QQ");

// request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);

//request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);

// 
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);

//request.setMimeType("application/cn.trinea.download.file"); 

long downloadId = downloadManager.enqueue(request);

The above code is to add a download url to the system download queue, and the download will start automatically when the conditions are met. Calling enqueue() returns a long id value, which is the unique id of the download item.

Attributes can be set for Request (download item). Except for the required URI of the construction parameter, other conditions are optional, such as the local path of the download, the renaming after the download, the display and non-display of the download notification or the style of the notification. , the network types allowed for download, the MimeType of the downloaded item, etc.

request.setMimeType(“application/cn.trinea.download.file”);

Set the mineType of the downloaded file. Because clicking on a downloaded file in the download management UI and clicking on the notification bar prompt after the download is completed will open the file according to the mimeType, so we can use this attribute. For example, if the mimeType is set to application/cn.trinea.download.file above, we can set the intent-filter of an Activity to application/cn.trinea.download.file at the same time, which is used to open the file in response to the click.

<intent-filter> 

<action android:name="android.intent.action.VIEW" />

<category android:name="android.intent.category.DEFAULT" />

<data android:mimeType="application/cn.trinea.download.file" />
    
</intent-filter>

Add the http header of the network link requesting download, such as User-Agent, gzip compression, etc.:

request.addRequestHeader(String header, String value);

3. Monitoring and query of download progress status

The DownloadManager download tool does not provide a corresponding callback interface to return the real-time download progress status, but through ContentProvider, one of the four major components of Android, we can monitor the progress status change of the current download item.

downloadManager.getUriForDownloadedFile(id);

This method will return a Uri of the download item, such as: content://downloads/my_downloads/125
ContentObserver - Content Observer, which can monitor and observe the changes of the database item pointed to by a specific Uri, and then perform corresponding processing, among which we will monitor Uri.parse(" content://downloads/my_downloads "). Then query the download status and progress, and perform the next operation such as sending the handler to update the UI.

The following method can query the download progress status of the download item according to the id of the download item and return "current downloaded bytes", "total bytes", "current download status":

 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;
}

It can be seen from the above code that we mainly call DownloadManager.Query() to query. DownloadManager.Query is an information query class open to the outside world for download management. It mainly includes the following interfaces:

  • setFilterById(long... ids) filter according to the download id
  • setFilterByStatus(int flags) filter according to download status
  • setOnlyIncludeVisibleInDownloadsUi(boolean value) filters based on whether it is visible in the download ui.
  • orderBy(String column, int direction) sorts according to the column, but currently only supports
  • DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP和
  • DownloadManager.COLUMN_TOTAL_SIZE_BYTES排序。

To observe the content provided by ContentProvider, you need to re-create the onChange(boolean selfChange) method in ContentObserver, and register/deregister Observer in the corresponding life cycle method of activity/fragment:

 class DownloadStatusObserver extends ContentObserver {
        public DownloadStatusObserver() {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            int[] bytesAndStatus = getBytesAndStatus(downloadId);
            int currentSize = bytesAndStatus[0];//当前大小
            int totalSize = bytesAndStatus[1];//总大小
            int status = bytesAndStatus[2];//下载状态

        }

    }

@Override
    protected void onResume() {
        super.onResume();
        getContentResolver().registerContentObserver(CONTENT_URI, true, observer);
}

 @Override
    protected void onDestroy() {
        super.onDestroy();
        getContentResolver().unregisterContentObserver(observer);
    }
  • If there are too many elements on the interface that need to be updated, and the network speed is fast and the onChange is executed continuously, it will have a certain impact on the performance of the page. It is recommended that ScheduledExecutorService be queried regularly, as follows:

      //三秒定时刷新一次
      public static ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
      Runnable command = new Runnable() {
      
              @Override
              public void run() {
                  updateView();
              }
          };
      scheduledExecutorService.scheduleAtFixedRate(command, 0, 3, TimeUnit.SECONDS);
    

4. Download success monitoring

After the download is complete, the download manager will send the DownloadManager.ACTION_DOWNLOAD_COMPLETE broadcast and pass the downloadId as a parameter. By accepting the broadcast we can open and operate on the downloaded content. code show as below:

class CompleteReceiver extends BroadcastReceiver {
 
    @Override
    public void onReceive(Context context, Intent intent) {
        // get complete download id
        long completeDownloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
        // to do here
    }
};
 
private CompleteReceiver       completeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.download_manager_demo);
 
    completeReceiver = new CompleteReceiver();
    /** register download success broadcast **/
    registerReceiver(completeReceiver,
                     new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
 
@Override
protected void onDestroy() {
    super.onDestroy();
    unregisterReceiver(completeReceiver);
}

5. Respond to notification bar clicks

  • Responding to clicks on the notification bar during download

Click the notification bar prompt during downloading, and the system will send the DownloadManager.ACTION_NOTIFICATION_CLICKED broadcast to the downloaded application separately.

intent.getData is content://downloads/all_downloads/29669 , and the last digit is downloadId.

If multiple applications are downloaded at the same time, the intent will contain the key DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS, which represents the downloaded downloadId array.

  • In response to download complete notification bar clicks

After downloading, the following code will be called for processing, from which we can find that the system will call the View action to query according to the mimeType. So you can use the setMimeType function of DownloadManager.Request we introduced.

private void openDownload(Context context, Cursor cursor) {
    String filename = cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl._DATA));
    String mimetype = cursor.getString(cursor.getColumnIndexOrThrow(Downloads.Impl.COLUMN_MIME_TYPE));
    Uri path = Uri.parse(filename);
    // If there is no scheme, then it must be a file
    if (path.getScheme() == null) {
        path = Uri.fromFile(new File(filename));
    }
    Intent activityIntent = new Intent(Intent.ACTION_VIEW);
    mimetype = DownloadDrmHelper.getOriginalMimeType(context, filename, mimetype);
    activityIntent.setDataAndType(path, mimetype);
    activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    try {
        context.startActivity(activityIntent);
    } catch (ActivityNotFoundException ex) {
        Log.d(Constants.TAG, "no activity for " + mimetype, ex);
    }
}

6. Open the system download interface through implicit intent

Intent intent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
startActivity(intent);

4. DownloadManager/Request/Query interface reference

DownloadManager:
 long enqueue(Request request) 

Queue a new download that will automatically start the download when the downloadmanager is ready to execute the download/connection is available, returning the unique id for that download

int remove(long... ids)

Remove one or more downloads, returning the number of changes

Cursor query(Query query) 

Execute a query Qurey class is described below

openDownloadedFile(long id)

Open a file (the file must be downloaded)

getUriForDownloadedFile(long id) 

Returns a Uri of the downloaded item, eg: content://downloads/my_downloads/103

getMimeTypeForDownloadedFile(long id)

Returns a downloaded item mimetype

restartDownload(long... ids)      

Re-completed download items (download successful, download failed) start downloading;

getMaxBytesOverMobile(Context context)

Returns the maximum value of mobile network downloads

rename(Context context, long id, String displayName) 

Rename downloaded item's name

getRecommendedMaxBytesOverMobile(Context context)

Get the recommended download size for mobile networks

addCompletedDownload(String title, String description,boolean isMediaScannerScannable, String mimeType, String path, long length,boolean showNotification)

Add a file to the system's download file database, and the download entry of the file can be displayed in the system download app;
according to the instructions on the api, this method is useful for making a file scannable by MediaScanner, call this method, which can make the specified file scannable by MediaScanner by setting the param isMediaScannerScannable to true. It is very useful in the application of album gallery


Request
setDestinationUri(Uri uri) :

Customize the download local path and pass in a Uri type;

setDestinationInExternalFilesDir(Context context, String dirType,String subPath)  :

Customize the download local path, which is the Android/data/package-name/ parent directory of the built-in sd card. The contents of this directory will be deleted and emptied with the uninstallation of the application. dirType: The type of the file (Environment.DIRECTORY_DOWNLOADS, Environment. DIRECTORY_DCIM,...);
subPath: The subdirectory path under the parent directory (/apk/myPath/myapk.apk)

setDestinationInExternalPublicDir(String dirType, String subPath) :

Same as above, download to the subPath subdirectory under the common parent directory shared on the sd card

allowScanningByMediaScanner() :

It can be understood from the literal meaning that the download item is allowed to be scanned by MediaScanner (scanning work of multimedia files). (Recognized by MediaScanner: http://blog.csdn.net/hellofeiya/article/details/8255898 )

addRequestHeader(String header, String value) :

Add an HTTP request header to the end of the HTTP header list

setTitle(CharSequence title)/setDescription(CharSequence description) 

Set the display style of the download notification in the notification bar

setMimeType(String mimeType)

Set the MIME content type of this download. This will override the content type declared in the server's response.
Setting the MimeType will override the declared content type returned by the server

setShowRunningNotification(boolean show)(已过时)

Set whether to display the status of the download item in the form of a notification when the download starts, the default display

setNotificationVisibility(int visibility)替代上面方法

visibility取值:
{@link #VISIBILITY_HIDDEN}, {@link #VISIBILITY_VISIBLE}, {@link #VISIBILITY_VISIBLE_NOTIFY_COMPLETED}.

setAllowedNetworkTypes(int flags)

Set the allowed network environment when downloading, all network environments are allowed by default

setAllowedOverRoaming(boolean allow)

Set whether this download may proceed over a metered network connection. By default, metered networks are allowed
.

setRequiresCharging(boolean requiresCharging)

Set whether it must be downloaded while charging, the default is no

setRequiresDeviceIdle(boolean requiresDeviceIdle)

Set whether the mobile phone must be in an idle state to download, the default is no

setVisibleInDownloadsUi(boolean isVisible)

Set whether the download item is displayed by default in the system's download app. Open the system's own download app to view the download item.


Query
setFilterById(long... ids)

Filter the download items in the downloadmanager according to the id and return the cursor

setFilterByStatus(int flags) 

Filter the download items in the downloadmanager according to the status and return the cursor

setOnlyIncludeVisibleInDownloadsUi(boolean value)

If it is set to true, the download items that are only displayed on the download interface will be filtered. Otherwise, the ones that are not displayed will also be filtered.

orderBy(String column, int direction)

Sort the data carried by the returned Cursor according to column and direction. The value of
column is COLUMN_LAST_MODIFIED_TIMESTAMP
COLUMN_TOTAL_SIZE_BYTES The
value of direction is ORDER_ASCENDING
ORDER_DESCENDING



Reprinted: https://www.jianshu.com/p/7ad92b3d9069

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325566876&siteId=291194637