最近做SDK開發(fā),有個簡單的下載功能,為了方便及不增加第三方庫,遂采用了系統(tǒng)的DownloadManager來處理下載任務。
官網(wǎng)的說明:
The download manager is a system service that handles long-running HTTP downloads. Clients may request that a URI be downloaded to a particular destination file. The download manager will conduct the download in the background, taking care of HTTP interactions and retrying downloads after failures or across connectivity changes and system reboots.
Apps that request downloads through this API should register a broadcast receiver for ACTION_NOTIFICATION_CLICKED to appropriately handle when the user clicks on a running download in a notification or from the downloads UI.
Note that the application must have the Manifest.permission.INTERNET permission to use this class.
Instances of this class must be obtained using Context.getSystemService(Class) with the argument DownloadManager.class or Context.getSystemService(String) with the argument Context.DOWNLOAD_SERVICE.
下載狀態(tài):
DownloadManager.STATUS_PAUSED:下載暫停
DownloadManager.STATUS_PENDING:下載延遲
DownloadManager.STATUS_RUNNING:正在下載
DownloadManager.STATUS_SUCCESSFUL:下載完成
DownloadManager.STATUS_FAILED:下載失敗
文件信息:
DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR:已下載文件大小
DownloadManager.COLUMN_TOTAL_SIZE_BYTES:文件總大小
廣播:
DownloadManager.ACTION_NOTIFICATION_CLICKED:下載通知點擊事件廣播
最后代碼如下
public class DownloadHelper {
private static final String TAG = "DownloadHelper";
private boolean debug = false;
private Context context;
/**
* 系統(tǒng)下載管理器
*/
private DownloadManager mDownloadManager;
/**
* 下載ID
*/
private long mDownloadId;
/**
* 文件名
*/
private String fileName;
/**
* 文件下載地址
*/
private String downloadUrl;
private boolean downloading;
/**
* 通知欄點擊事件,點擊進入下載詳情
*/
private BroadcastReceiver mDownloadDetailsReceiver;
private final Runnable mQueryProgressRunnable = new Runnable() {
@Override
public void run() {
queryProgress();
if (downloading) {
mHandler.postDelayed(mQueryProgressRunnable, 1000);
}
}
};
private final Handler mHandler = new Handler(Looper.getMainLooper());
private DownloadListener downloadListener;
public interface DownloadListener {
void onStart();
void onProgress(long soFarSize, long totalSize);
void onFinish(String fileFullPath, long totalSize);
void onFailed();
}
public void setDownloadListener(DownloadListener listener) {
this.downloadListener = listener;
}
private DownloadHelper(Context context, String fileName, String downloadUrl) {
this.context = context;
this.fileName = fileName;
this.downloadUrl = downloadUrl;
}
public static DownloadHelper getInstance(Context context, String fileName, String downloadUrl) {
DownloadHelper helper = new DownloadHelper(context, fileName, downloadUrl);
helper.registerReceiver();
return helper;
}
/**
* 注冊廣播
*/
private void registerReceiver() {
mDownloadDetailsReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DownloadManager.ACTION_NOTIFICATION_CLICKED.equals(action)) {
showDownloadList();
}
}
};
context.registerReceiver(mDownloadDetailsReceiver, new IntentFilter(DownloadManager.ACTION_NOTIFICATION_CLICKED));
}
/**
* 顯示下載列表
*/
public void showDownloadList() {
Intent downloadIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
if (downloadIntent.resolveActivity(context.getPackageManager()) != null) {
context.startActivity(downloadIntent);
}
}
/**
* 開始下載
*/
public void startDownload(String mimeType) {
if (downloadListener != null) downloadListener.onStart();
mDownloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downloadUrl));
request..setAllowedOverMetered(true)
.setAllowedOverRoaming(true)
.setTitle("Downloading " + fileName) // 通知欄標題
.setMimeType(mimeType)
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
// .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)
.setDestinationInExternalFilesDir(ContextUtils.getContext(), Environment.DIRECTORY_DOWNLOADS, fileName)
.allowScanningByMediaScanner();
try {
mDownloadId = mDownloadManager.enqueue(request); // 加入下載隊列
if (mDownloadId != 0) {
startQueryProgress();
}
} catch (IllegalArgumentException e) {
if (downloadListener != null) downloadListener.onFailed();
// "更新失敗", "請在設置中開啟下載管理"
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + "com.android.providers.downloads"));
if (intent.resolveActivity(context.getPackageManager()) != null) {
context.startActivity(intent);
}
}
}
/**
* 查詢下載進度
*/
private void queryProgress() {
// 通過ID向下載管理查詢下載情況,返回一個cursor
Cursor c = mDownloadManager.query(new DownloadManager.Query().setFilterById(mDownloadId));
if (c != null && c.moveToFirst()) {
int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
logDebug("下載狀態(tài):" + status);
switch (status) {
case DownloadManager.STATUS_PAUSED: //下載暫停, 由系統(tǒng)觸發(fā)
case DownloadManager.STATUS_PENDING: //下載延遲, 由系統(tǒng)觸發(fā)
break;
case DownloadManager.STATUS_RUNNING: //正在下載, 由系統(tǒng)觸發(fā)
long soFarSize = c.getLong(c.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
long totalSize = c.getLong(c.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
if (totalSize > 0) {
logDebug(String.format("total:%s soFar:%s ", totalSize, soFarSize) + soFarSize * 1.0f / totalSize);
if (downloadListener != null) {
downloadListener.onProgress(soFarSize, totalSize);
}
}
break;
case DownloadManager.STATUS_SUCCESSFUL: //下載完成, 由系統(tǒng)觸發(fā)
stopQueryProgress();
File downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
totalSize = c.getLong(c.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
if (downloadListener != null) {
String fullName = downloadDir.getPath() + File.separator + fileName;
logDebug(fullName);
downloadListener.onFinish(fullName, totalSize);
}
break;
case DownloadManager.STATUS_FAILED: //下載失敗, 由系統(tǒng)觸發(fā)
if (downloadListener != null) downloadListener.onFailed();
break;
}
} else {
stopQueryProgress();
if (downloadListener != null) downloadListener.onFailed();
}
closeCursor(c);
}
private void closeCursor(Cursor cursor) {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
private void logDebug(String msg) {
if (debug) {
Log.e(TAG, msg);
}
}
/**
* 移除下載并刪除下載文件
*/
public void removeDownload() {
mDownloadManager.remove(mDownloadId);
stopQueryProgress();
}
/**
* 開始查詢下載進度
*/
private void startQueryProgress() {
downloading = true;
mHandler.post(mQueryProgressRunnable);
}
/**
* 停止查詢下載進度
*/
private void stopQueryProgress() {
downloading = false;
mHandler.removeCallbacks(mQueryProgressRunnable);
}
public boolean isDownloading() {
return downloading;
}
public void onDestroy() {
try {
stopQueryProgress(); //停止查詢下載進度
context.unregisterReceiver(mDownloadDetailsReceiver);
} catch (Exception ex) {
//java.lang.IllegalArgumentException: Receiver not registered:
}
}
}