Android中系統(tǒng)下載管理DownLoadManager
一、DownloadManager簡(jiǎn)單介紹
DownloadManager是系統(tǒng)開(kāi)放給第三方應(yīng)用使用的類,包含兩個(gè)靜態(tài)內(nèi)部類DownloadManager.Query和DownloadManager.Request。DownloadManager.Request用來(lái)請(qǐng)求一個(gè)下載,DownloadManager.Query用來(lái)查詢下載信息,這兩個(gè)類的具體功能會(huì)在后面穿插介紹。DownloadManager的源碼可見(jiàn)DownloadManager@Grepcode。
DownloadManager主要提供了下面幾個(gè)接口:
public long enqueue(Request request)執(zhí)行下載,返回downloadId,downloadId可用于后面查詢下載信息。若網(wǎng)絡(luò)不滿足條件、Sdcard掛載中、超過(guò)最大并發(fā)數(shù)等異常會(huì)等待下載,正常則直接下載。
public int remove(long… ids)刪除下載,若下載中取消下載。會(huì)同時(shí)刪除下載文件和記錄。
public Cursor query(Query query)查詢下載信息。
public static Long getRecommendedMaxBytesOverMobile(Context context通過(guò)移動(dòng)網(wǎng)絡(luò)下載的最大字節(jié)數(shù)
public String getMimeTypeForDownloadedFile(long id)得到下載的mimeType,如何設(shè)置后面會(huì)進(jìn)行介紹
其它:通過(guò)查看代碼我們可以發(fā)現(xiàn)還有個(gè)CursorTranslator私有靜態(tài)內(nèi)部類。這個(gè)類主要對(duì)Query做了一層代理。將 DownloadProvider和DownloadManager之間做個(gè)映射。將DownloadProvider中的十幾種狀態(tài)對(duì)應(yīng)到了 DownloadManager中的五種狀態(tài),DownloadProvider中的失敗、暫停原因轉(zhuǎn)換為了DownloadManager的原因。
二、下載管理示例
下面具體介紹利用DownloadManager進(jìn)行下載。
1、AndroidManifest中添加權(quán)限
Java
1 2 |
<uses-permissionandroid:name="android.permission.INTERNET"/> <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/> |
網(wǎng)絡(luò)訪問(wèn)權(quán)限是必須的,下載地址為sdcard的話需要添加sdcard寫(xiě)權(quán)限。
2、調(diào)用DownloadManager.Request開(kāi)始下載
Java
1 2 3 4 5 6 7 8 9 10 11 |
DownloadManagerdownloadManager=(DownloadManager)getSystemService(DOWNLOAD_SERVICE); StringapkUrl="http://img.meilishuo.net/css/images/AndroidShare/Meilishuo_3.6.1_10006.apk"; DownloadManager.Requestrequest=newDownloadManager.Request(Uri.parse(apkUrl)); request.setDestinationInExternalPublicDir("Trinea","MeiLiShuo.apk"); // request.setTitle("MeiLiShuo"); // request.setDescription("MeiLiShuo desc"); // request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); // request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI); // request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN); // request.setMimeType("application/com.trinea.download.file"); longdownloadId=downloadManager.enqueue(request); |
上面調(diào)用downloadManager的enqueue接口進(jìn)行下載,返回唯一的downloadId。
DownloadManager.Request除了構(gòu)造函數(shù)的Uri必須外,其他設(shè)置都為可選設(shè)置。下面逐個(gè)介紹下:
request.setDestinationInExternalPublicDir(“Trinea”, “MeiLiShuo.apk”);表示設(shè)置下載地址為sd卡的Trinea文件夾,文件名為MeiLiShuo.apk。
setDestinationInExternalPublicDir源碼
從源碼中我們可以看出下載完整目錄為Environment.getExternalStoragePublicDirectory(dirType)。 不過(guò)file是通過(guò)file.mkdir()創(chuàng)建的,這樣如果上級(jí)目錄不存在就會(huì)新建文件夾異常。所以下載前我們最好自己調(diào)用File的mkdirs方法 遞歸創(chuàng)建子目錄,如下:
Java
1 2 |
Filefolder=newFile(folderName); return(folder.exists()&&folder.isDirectory())?true:folder.mkdirs(); |
否則,會(huì)報(bào)異常
1 2 |
java.lang.IllegalStateException:Unabletocreatedirectory:/storage/sdcard0/Trinea/aa atandroid.app.DownloadManager$Request.setDestinationInExternalPublicDir(DownloadManager.java) |
其他設(shè)置下載路徑接口為 setDestinationUri,setDestinationInExternalFilesDir,setDestinationToSystemCache。 其中setDestinationToSystemCache僅限系統(tǒng)app使用。
request.allowScanningByMediaScanner();表示允許MediaScanner掃描到這個(gè)文件,默認(rèn)不允許。
request.setTitle(“MeiLiShuo”);設(shè)置下載中通知欄提示的標(biāo)題
request.setDescription(“MeiLiShuo desc”);設(shè)置下載中通知欄提示的介紹
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
表示下載進(jìn)行中和下載完成的通知欄是否顯示。默認(rèn)只顯示下載中通知。VISIBILITY_VISIBLE_NOTIFY_COMPLETED表示下載完 成后顯示通知欄提示。VISIBILITY_HIDDEN表示不顯示任何通知欄提示,這個(gè)需要在AndroidMainfest中添加權(quán)限 android.permission.DOWNLOAD_WITHOUT_NOTIFICATION.
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
表示下載允許的網(wǎng)絡(luò)類型,默認(rèn)在任何網(wǎng)絡(luò)下都允許下載。有NETWORK_MOBILE、NETWORK_WIFI、NETWORK_BLUETOOTH三種及其組合可供選擇。如果只允許wifi下載,而當(dāng)前網(wǎng)絡(luò)為3g,則下載會(huì)等待。
request.setAllowedOverRoaming(boolean allow)移動(dòng)網(wǎng)絡(luò)情況下是否允許漫游。
request.setMimeType(“application/com.trinea.download.file”);
設(shè)置下載文件的mineType。因?yàn)橄螺d管理Ui中點(diǎn)擊某個(gè)已下載完成文件及下載完成點(diǎn)擊通知欄提示都會(huì)根據(jù)mimeType去打開(kāi)文件,所以我們可以 利用這個(gè)屬性。比如上面設(shè)置了mimeType為application/com.trinea.download.file,我們可以同時(shí)設(shè)置某個(gè) Activity的intent-filter為application/com.trinea.download.file,用于響應(yīng)點(diǎn)擊的打開(kāi)文件。
Java
1 2 3 4 5 6 7 |
<intent-filter> <actionandroid:name="android.intent.action.VIEW"/>
<categoryandroid:name="android.intent.category.DEFAULT"/>
<dataandroid:mimeType="application/com.trinea.download.file"/> </intent-filter> |
request.addRequestHeader(String header, String value)
添加請(qǐng)求下載的網(wǎng)絡(luò)鏈接的http頭,比如User-Agent,gzip壓縮等
3 下載進(jìn)度狀態(tài)監(jiān)聽(tīng)及查詢
下載進(jìn)度狀態(tài)監(jiān)聽(tīng)代碼
其中我們會(huì)監(jiān)聽(tīng)Uri.parse(“content://downloads/my_downloads”)。然后查詢下載狀態(tài)和進(jìn)度,發(fā)送handler進(jìn)行更新,handler中處理就是設(shè)置進(jìn)度條和狀態(tài)等。
其中DownloadManagerPro.getBytesAndStatus的主要代碼如下,可直接引入TrineaAndroidCommon@Github(歡迎star和fork^_^)或TrineaAndroidCommon@GoogleCode作為你項(xiàng)目的library(如何拉取代碼及添加公共庫(kù)):
下載進(jìn)度狀態(tài)查詢代碼
從上面代碼可以看出我們主要調(diào)用DownloadManager.Query()進(jìn)行查詢。DownloadManager.Query為下載管理對(duì)外開(kāi)放的信息查詢類,主要包括以下接口:
setFilterById(long… ids)根據(jù)下載id進(jìn)行過(guò)濾
setFilterByStatus(int flags)根據(jù)下載狀態(tài)進(jìn)行過(guò)濾
setOnlyIncludeVisibleInDownloadsUi(boolean value)根據(jù)是否在download ui中可見(jiàn)進(jìn)行過(guò)濾。
orderBy(String column, int direction)根據(jù)列進(jìn)行排序,不過(guò)目前僅支持DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP和 DownloadManager.COLUMN_TOTAL_SIZE_BYTES排序。
4 下載成功監(jiān)聽(tīng)
下載完成后,下載管理會(huì)發(fā)出DownloadManager.ACTION_DOWNLOAD_COMPLETE這個(gè)廣播,并傳遞downloadId作為參數(shù)。通過(guò)接受廣播我們可以打開(kāi)對(duì)下載完成的內(nèi)容進(jìn)行操作。代碼如下:
下載成功監(jiān)聽(tīng)
5、響應(yīng)通知欄點(diǎn)擊
(1) 響應(yīng)下載中通知欄點(diǎn)擊
點(diǎn)擊下載中通知欄提示,系統(tǒng)會(huì)對(duì)下載的應(yīng)用單獨(dú)發(fā)送Action為 DownloadManager.ACTION_NOTIFICATION_CLICKED廣播。intent.getData為 content://downloads/all_downloads/29669,最后一位為downloadId。
如果同時(shí)下載多個(gè)應(yīng)用,intent會(huì)包含DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS這個(gè)key,表示下載的的downloadId數(shù)組。這里設(shè)計(jì)到下載管理通知欄的顯示機(jī)制,會(huì)在下一篇具體介紹。
(2) 響應(yīng)下載完成通知欄點(diǎn)擊
下載完后會(huì)調(diào)用下面代碼進(jìn)行處理,從中我們可以發(fā)現(xiàn)系統(tǒng)會(huì)調(diào)用View action根據(jù)mimeType去查詢。所以可以利用我們?cè)诮榻B的DownloadManager.Request的setMimeType函數(shù)。
openDownload源碼
如果界面上過(guò)多元素需要更新,且網(wǎng)速較快不斷的執(zhí)行onChange會(huì)對(duì)頁(yè)面性能有一定影響。推薦ScheduledExecutorService定期查詢,如下:
Java
1 2 3 4 5 6 7 8 9 |
publicstaticScheduledExecutorServicescheduledExecutorService=Executors.newScheduledThreadPool(3); Runnablecommand=newRunnable(){
@Override publicvoidrun(){ updateView(); } }; scheduledExecutorService.scheduleAtFixedRate(command,0,3,TimeUnit.SECONDS); |
表示3秒定時(shí)刷新
推薦文章
2024-11-28
2024-06-25
2024-01-04
2023-11-06
2023-10-30
2023-10-13
2023-10-10
穩(wěn)定
產(chǎn)品高可用性高并發(fā)貼心
項(xiàng)目群及時(shí)溝通專業(yè)
產(chǎn)品經(jīng)理1v1支持快速
MVP模式小步快跑承諾
我們選擇聲譽(yù)堅(jiān)持
10年專注高端品質(zhì)開(kāi)發(fā)聯(lián)系我們
友情鏈接: