一。downloadmanager類說明:
從Android 2.3開始新增了一個下載管理類,在SDK的文檔中我們尋找android.app.DownloadManager可以看到。下載管理類可以長期處理多個HTTP下載任務,用戶端只需要給出請求的Uri和存放目標檔案的位置即可,下載管理使用了一個AIDL伺服器所以可以放心的在後台執行,同時執行個體化的方法需要使用getSystemService(Context.DOWNLOAD_SERVICE) ,Android123再次提醒使用API Level為9的使用者可以輕鬆的通過新增的這個API實現Android平台上的檔案下載操作。
DownloadManager類提供了以下幾種方法來處理,
Java代碼
- long enqueue(DownloadManager.Request request) //存入隊列一個新的下載項
-
- ParcelFileDescriptor openDownloadedFile(long id) //開啟一個下載後的檔案用於讀取,參數中的long型id是一個provider中的一條記錄。
-
- Cursor query(DownloadManager.Query query) //查詢一個下載,返回一個Cursor
-
- int remove(long... ids) //取消下載同時移除這些條從下載管理中。
我們可以看到提供的方法都比較簡單,給我們操作的最終封裝成為一個provider資料庫的方式進行添加、查詢和移除,但是對於查詢和新增工作的細節,我們要看看DownloadManager.Request類和DownloadManager.Query 類了。
一、DownloadManager.Request類的成員和定義Java代碼
- DownloadManager.Request addRequestHeader(String header, String value) // 添加一個Http請求前序,對於這兩個參數,Android開發網給大家舉個小例子,比如說User-Agent值可以為Android123或 Windows XP等等了,主要是給伺服器提供標識。
- DownloadManager.Request setAllowedNetworkTypes(int flags) //設定允許使用的網路類型,這一步Android 2.3做的很好,目前有兩種定義分別為NETWORK_MOBILE和NETWORK_WIFI我們可以選擇使用移動網路或Wifi方式來下載。
- DownloadManager.Request setAllowedOverRoaming(boolean allowed) //對於下載,考慮到流量費用,這裡是否允許使用漫遊。
- DownloadManager.Request setDescription(CharSequence description) //設定一個描述資訊,主要是最終顯示的notification提示,可以隨便寫個自己區別
- DownloadManager.Request setDestinationInExternalFilesDir(Context context, String dirType, String subPath) //設定目標儲存在外部目錄,一般位置可以用 getExternalFilesDir()方法擷取。
- DownloadManager.Request setDestinationInExternalPublicDir(String dirType, String subPath) //設定外部儲存的公用目錄,一般通過getExternalStoragePublicDirectory()方法擷取。
- DownloadManager.Request setDestinationUri(Uri uri) //設定需要下載目標的Uri,可以是http、ftp等等了。
- DownloadManager.Request setMimeType(String mimeType) //設定mime類型,這裡看伺服器配置,一般國家化的都為utf-8編碼。
- DownloadManager.Request setShowRunningNotification(boolean show) //是否顯示下載進度的提示
- DownloadManager.Request setTitle(CharSequence title) //設定notification的標題
- DownloadManager.Request setVisibleInDownloadsUi(boolean isVisible) //設定下載管理類在處理過程中的介面是否顯示
當然了Google還提供了一個簡單的方法來執行個體化本類,這個構造方法為DownloadManager.Request(Uri uri) ,我們直接填寫一個Uri即可,上面的設定使用預設情況。
二、DownloadManager.Query類
對於當前下載內容的狀態,我們可以使用DownloadManager.Query類來擷取,本類比較簡單,僅僅提供了兩個方法。Java代碼
- DownloadManager.Query setFilterById(long... ids) //根據id來過濾尋找。
- DownloadManager.Query setFilterByStatus(int flags) //根據任務的狀態來尋找。
詳細的狀態在android.app.DownloadManager類中有定義,目前Android 2.3中的定義為:
Java代碼
- int STATUS_FAILED 失敗
- int STATUS_PAUSED 暫停
- int STATUS_PENDING 等待將開始
- int STATUS_RUNNING 正在處理中
- int STATUS_SUCCESSFUL 已經下載成功
最後Android開發網提醒大家要說的是因為DownloadManager類提供的query方法返回一個Cursor對象,這些狀態儲存在這個遊標的COLUMN_STATUS 欄位中。
1. 下載的狀態完成均是以廣播的形式通知大家,目前API Level為9定義了下面三種Intent的actionJava代碼
- ACTION_DOWNLOAD_COMPLETE下載完成的動作。
- ACTION_NOTIFICATION_CLICKED 當使用者單擊notification中下載管理的某項時觸發。
- ACTION_VIEW_DOWNLOADS 查看下載項
2. 對於一個尚未完成的項,在Cursor中我們尋找COLUMN_REASON欄位,可能有以下定義:Java代碼
- int ERROR_CANNOT_RESUME 不能夠繼續,由於一些其他原因。
- int ERROR_DEVICE_NOT_FOUND 外部存放裝置沒有找到,比如SD卡沒有插入。
- int ERROR_FILE_ALREADY_EXISTS 要下載的檔案已經存在了,Android123提示下載管理類是不會覆蓋已經存在的檔案,所以如果需要重新下載,請先刪除以前的檔案。
-
- int ERROR_FILE_ERROR 可能由於SD卡原因導致了檔案錯誤。
- int ERROR_HTTP_DATA_ERROR 在Http傳輸過程中出現了問題。
- int ERROR_INSUFFICIENT_SPACE 由於SD卡空間不足造成的
-
- int ERROR_TOO_MANY_REDIRECTS 這個Http有太多的重新導向,導致無法正常下載
- int ERROR_UNHANDLED_HTTP_CODE 無法擷取http出錯的原因,比如說遠程伺服器沒有響應。
- int ERROR_UNKNOWN 未知的錯誤類型.
3. 有關暫停一些狀態,同樣COLUMN_REASON欄位的值可能是以下定義Java代碼
- int PAUSED_QUEUED_FOR_WIFI 由於移動網路資料問題,等待WiFi串連能用後再重新進入下載隊列。
- int PAUSED_UNKNOWN 未知原因導致了任務下載的暫停.
- int PAUSED_WAITING_FOR_NETWORK 可能由於沒有網路連接而無法下載,等待有可用的網路連接恢複。.
- int PAUSED_WAITING_TO_RETRY 由於重重原因導致下載暫停,等待重試。
有關Android 2.3中新增的下載管理DownloadManager的介紹基本上已經完全講完,如果你對Cursor、Provider這些基礎概念瞭解的話,可以看到這個下載管理類可以幫我們減少很多不必要的代碼編寫
二。用downloadManager 下載:
public void onDownloadStart(String url, String userAgent,
String contentDisposition, String mimetype, long contentLength) {
AppUtils.LogD(mimetype);
// download file
DownloadManager downloadManager = ((DownloadManager) activity
.getSystemService(Activity.DOWNLOAD_SERVICE));
Request request = new Request(Uri.parse(url));
// set request header, 如session等
request.addRequestHeader("Accept",
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
request.addRequestHeader("Accept-Language", "en-us,en;q=0.5");
request.addRequestHeader("Accept-Encoding", "gzip, deflate");
request.addRequestHeader("Accept-Charset",
"ISO-8859-1,utf-8;q=0.7,*;q=0.7");
request.addRequestHeader("Cache-Control", "max-age=0");
String host = "";
try {
host = new URL(url).getHost();
} catch (MalformedURLException e) {
e.printStackTrace();
}
String cookieStr = CookieManager.getInstance().getCookie(host);
if (!AppUtils.isEmpty(cookieStr)) {
request.addRequestHeader("Cookie", cookieStr + "; AcSe=0");
}
// generate filename dynamically
String fileName = contentDisposition.replaceFirst(
"attachment; filename=", "");
request.setDestinationInExternalPublicDir(
Environment.DIRECTORY_DOWNLOADS, fileName);
downloadManager.enqueue(request);
}
三。判斷download finished:
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
long downloadId = intent.getLongExtra(
DownloadManager.EXTRA_DOWNLOAD_ID, 0);
Query query = new Query();
query.setFilterById(enqueue);
Cursor c = dm.query(query);
if (c.moveToFirst()) {
int columnIndex = c
.getColumnIndex(DownloadManager.COLUMN_STATUS);
if (DownloadManager.STATUS_SUCCESSFUL == c
.getInt(columnIndex)) {
ImageView view = (ImageView) findViewById(R.id.imageView1);
String uriString = c
.getString(c
.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
view.setImageURI(Uri.parse(uriString));
}
}
}
}
};
registerReceiver(receiver, new IntentFilter(
DownloadManager.ACTION_DOWNLOAD_COMPLETE));
四。擷取系統download history list:
Intent i = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
startActivity(i);
五。 獲得剛下載的檔案 和 開啟該檔案:
protected String getDownloadedFileName() {
String fileName = "";
DownloadManager downloadManager = (DownloadManager) activity
.getSystemService(Activity.DOWNLOAD_SERVICE);
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL);
Cursor c = downloadManager.query(query);
if (c.moveToFirst()) {
fileName = c.getString(c
.getColumnIndex(DownloadManager.COLUMN_TITLE));
}
return fileName;
}
public void openFileFromSDCard(String fileStr, String mimeType) {
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
File file = new File(fileStr);
intent.setDataAndType(Uri.fromFile(file), mimeType);
activity.startActivity(intent);
}