Android 經典筆記之五:DownloadManager下載管理器介紹
DownloadManager下載管理器介紹
目錄介紹:
- 0.簡單介紹
- 1.所需權限
- 2.獲取對象,開始下載
- 3.取消下載
- 4.Request類的介紹
- 4.5.指定下載的類型
- 4.6.定製Notification樣式
- 4.7.設置下載文件類型
- 4.8.添加請求下載的網絡鏈接的http頭,比如User-Agent,gzip壓縮等
- 5.Query 類
- 6.不足之處
- 7.代碼案例【簡易】
0.簡單介紹
- 關於DownloadManager簡單介紹 DownloadManager是android2.3以後,係統下載的方法,是處理長期運行的HTTP下載的係統服務。客戶端可以請求的URI被下載到一個特定的目標文件。客戶端將會在後台與http交互進行下載,或者在下載失敗,或者連接改變,重新啟動係統後重新下載。還可以進入係統的下載管理界麵查看進度。DownloadManger有兩個內部類,Request 和Query。Request類可設置下載的一些屬性。Query類可查詢當前下載的進度,下載地址,文件存放目錄等數據。
1.所需權限
<uses-permission android:name="android.permission.INTERNET" />;
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>;
注意,訪問本地控件【sd卡,手機內存卡】需要檢測是否添加權限
/**檢測存儲權限*/
private final int REQUEST_EXTERNAL_STORAGE = 1;
private String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
public void verifyStoragePermissions(Activity activity) {
// Check if we have write permission
int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
}
}
2.獲取對象,開始下載
- 獲取對象,開始下載
DownloadManager downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE); DownloadManager.Request request = new DownloadManager.Request(Uri.parse(apkUrl)); long id = downloadManager.enqueue(request); //每下載的一個文件對應一個id,通過此id可以查詢數據。
3.取消下載
downloadManager.remove(REFERENCE_1, REFERENCE_2, REFERENCE_3);
該方法返回成功取消的下載的個數,如果一個下載被取消了,所有相關聯的文件,部分下載的文件和完全下載的文件都會被刪除.
4.Request類的介紹
/**
* 方法1:
* 目錄: Android -> data -> com.app -> files -> Download -> dxtj.apk
* 這個文件是你的應用所專用的,軟件卸載後,下載的文件將隨著卸載全部被刪除
*/
request.setDestinationInExternalFilesDir( this , Environment.DIRECTORY_DOWNLOADS , "dxtj.apk" );
/**
* 方法2:
* 下載的文件存放地址 SD卡 download文件夾,dxtj.apk
* 軟件卸載後,下載的文件會保留
*/
//在SD卡上創建一個文件夾
request.setDestinationInExternalPublicDir( "/epmyg/" , "dxtj.apk" ) ;
/**
* 方法3:
* 如果下載的文件希望被其他的應用共享
* 特別是那些你下載下來希望被Media Scanner掃描到的文件(比如音樂文件)
*/
request.setDestinationInExternalPublicDir( Environment.DIRECTORY_MUSIC, "告白氣球.mp3" );
/**
* 方法4【投資界和新芽目前用這個】
* 文件將存放在外部存儲的確實download文件內,如果無此文件夾,創建之,如果有,下麵將返回false。
* 係統有個下載文件夾,比如小米手機係統下載文件夾 SD卡--> Download文件夾
*/
//創建目錄
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).mkdir() ;
//設置文件存放路徑
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS , "dxtj.apk" ) ;
-
4.1 指定下載的類型
//指定在WIFI狀態下,執行下載操作。 request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI); //指定在MOBILE狀態下,執行下載操作 request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE); //是否允許漫遊狀態下,執行下載操作 request.setAllowedOverRoaming(boolean); //是否允許“計量式的網絡連接”執行下載操作 request.setAllowedOverMetered(boolean); //默認是允許的。
-
4.2 定製Notification樣式
//設置Notification的標題和描述 request.setTitle("標題"); request.setDescription("描述"); //設置Notification的顯示,和隱藏。 request.setNotificationVisibility(visibility); VISIBILTY_HIDDEN: Notification:將不會顯示,如果設置該屬性的話,必須要添加權限 android.permission.DOWNLOAD_WITHOUT_NOTIFICATION. VISIBILITY_VISIBLE: Notification顯示,但是隻是在下載任務執行的過程中顯示,下載完成自動消失。(默認值) VISIBILITY_VISIBLE_NOTIFY_COMPLETED : Notification顯示,下載進行時,和完成之後都會顯示。 VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION :隻有當任務完成時,Notification才會顯示。 對Notification的設定方法相對較少。
-
4.3 設置下載文件類型
request.setMimeType("application/vnd.android.package-archive"); 這是安卓.apk文件的類型。有些機型必須設置此方法,才能在下載完成後,點擊通知欄的Notification時,才能正確的打開安裝界麵。不然會彈出一個Toast(can not open file).其他文件類型的MimeType
-
4.4 添加請求下載的網絡鏈接的http頭,比如User-Agent,gzip壓縮等
request.addRequestHeader(String header, String value);
5.Query 類
- 我們的需求,可能不隻是在Notification 中顯示進度就好了,也許,在app中也需要獲取實時下載進度。所以Query類就是提供查詢的一些方法。
- 但API中就隻有兩個方法,原來,他把數據保存在數據庫中去了。我們需要獲得一個Cursor 結果集,通過結果集獲得我們想要的數據。
DownloadManager.Query query = new DownloadManager.Query(); Cursor cursor = downloadManager.query(query.setFilterById(id)); if (cursor != null && cursor.moveToFirst()) { //下載的文件到本地的目錄 String address = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)); //已經下載的字節數 int bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)); //總需下載的字節數 int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)); //Notification 標題 String title =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TITLE)); //描述 String description =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_DESCRIPTION)); //下載對應id long id =cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_ID)); //下載文件名稱 String filename =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME)); //下載文件的URL鏈接 String url =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_URI)); }
6.不足之處
- 1、我發現,在下載的時候,發送Notification時 是沒有聲音的。也沒有設置聲音的方法。不過這影響不大。主要的功能實現就好。
- 2、因為這是係統的類,每個係統的Notification界麵是不一樣的。這就是每個rom廠家的自定義了。小米和魅族的就大不一樣。魅族Notification上有一個下載暫停的按鈕,而小米沒有。所以導致Notification是不能統一的。其實,暫停的話用戶可以點擊notification,進入到下載管理界麵,就有暫停按鈕了。
7.代碼案例【簡易】
/**
* 開始下載
* @param context
*/
private static void startDownload(Context context) {
int status = getDownloadStatus(context);
if (status != DOWNLOAD_STATUS_NEED_LOAD) {
// 不用下載則無需下列操作
return;
}
DialogUtils.showToast(context, "開始下載安裝包...");
// parse url
Uri mUri = Uri.parse(path);
// create request
DownloadManager.Request r = new DownloadManager.Request(mUri);
// set request property
String apkName = getDownloadApkName(context);
// set 下載路徑
r.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, apkName);
// set Notification
r.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
// create manager
DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
// key code, set mine type
r.setMimeType("application/vnd.android.package-archive");
// add to queue
dm.enqueue(r);
}
/**獲得Apk的名稱*/
@NonNull
private static String getDownloadApkName(Context context) {
return context.getString(R.string.app_name) + "_" + version + ".apk";
}
/**
* 判斷當前版本文件下載狀態
* @param context
* @return
*/
private static int getDownloadStatus(Context context) {
DownloadManager.Query query = new DownloadManager.Query();
DownloadManager dm = (DownloadManager) context.getSystemService(Activity.DOWNLOAD_SERVICE);
Cursor c = dm.query(query);
if (!c.moveToFirst()) {
// 無下載內容
return DOWNLOAD_STATUS_NEED_LOAD;
}
do {
int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
String title = c.getString(c.getColumnIndex(DownloadManager.COLUMN_TITLE));
String apkName = getDownloadApkName(context);
if (title.equals(apkName)) {
// 如果下載列表中文件是當前版本應用,則繼續判斷下載狀態
if (status == DownloadManager.STATUS_SUCCESSFUL) {
// 如果已經下載,返回狀態,同時直接提示安裝
String uri = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
promptInstall(context, Uri.parse(uri));
return DOWNLOAD_STATUS_LOADED;
} else if (status == DownloadManager.STATUS_RUNNING
|| status == DownloadManager.STATUS_PAUSED
|| status == DownloadManager.STATUS_PENDING) {
return DOWNLOAD_STATUS_RUNNING;
} else {
// 失敗也視為可以再次下載
return DOWNLOAD_STATUS_NEED_LOAD;
}
}
} while (c.moveToNext());
return DOWNLOAD_STATUS_NEED_LOAD;
}
/**
* 根據下載隊列id獲取下載Uri
* @param enqueueId
* @return null-獲取不到
*/
public static Uri getDownloadUriById(Context context, long enqueueId) {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(enqueueId);
DownloadManager dm = (DownloadManager) context.getSystemService(Activity.DOWNLOAD_SERVICE);
Cursor c = dm.query(query);
if (c.moveToFirst()) {
int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
String uri = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
return Uri.parse(uri);
}
}
return null;
}
/**
* 安裝文件
* @param context 上下文
* @param data uri地址
*/
public static void promptInstall(Context context, Uri data) {
Intent promptInstall = new Intent(Intent.ACTION_VIEW).setDataAndType(data, "application/vnd.android.package-archive");
// FLAG_ACTIVITY_NEW_TASK 可以保證安裝成功時可以正常打開 app
promptInstall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(promptInstall);
}
其他
- 知乎:https://www.zhihu.com/people/yang-chong-69-24/pins/posts
- 領英:https://www.linkedin.com/in/chong-yang-049216146/
- 簡書:https://www.jianshu.com/u/b7b2c6ed9284
- csdn:https://my.csdn.net/m0_37700275
- 網易博客:https://yangchong211.blog.163.com/
- 新浪博客:https://blog.sina.com.cn/786041010yc
- github:https://github.com/yangchong211
- 喜馬拉雅聽書:https://www.ximalaya.com/zhubo/71989305/
- 脈脈:yc930211
- 360圖書館:https://www.360doc.com/myfiles.aspx
- 開源中國:https://my.oschina.net/zbj1618/blog
- 泡在網上的日子:https://www.jcodecraeer.com/member/content_list.php?channelid=1
- 郵箱:yangchong211@163.com
最後更新:2017-09-20 10:02:55