DownloadManger是android提供的一个系统服务,用于处理App安装包下载任务,通常在应用商店下载应用时,就会用到此服务。我们自己开发的应用,通常都需要实现App在线更新功能,在此我们就可以使用这个系统服务,而不用再自己处理大文件下载等复杂情况。
通过DownloadManager可以获取到当前的下载进度、下载状态(成功、失败、暂停)等。
DownloadManager实例可通过如下方式获得:
DownlaodMnager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
建立一个下载任务,下载文件默认保存在系统内部存储中,为避免某些情况下下载失败,在此可选择保存到外部存储中(需要系统外部存储权限),设置存储位置时,若选用 setDestinationInExternalPublicDir 方法,生成的是文件夹,若直接生成APK文件,可用如下方式:
public long startDownLoad(String url, String apkName) {
DownlaodMnager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.allowScanningByMediaScanner();//设置文件可由MediaScanner扫描
request.setAllowedOverMetered(true);//是否允许流量下载
request.setDescription(“App更新”);//下载描述
request.setMimeType(“application/vnd.android.package-archive”);
File file = new File(Environment.getExternalStorageDirectory() + File.separator +
Environment.DIRECTORY_DOWNLOADS + File.separator + apkName);//文件保存位置
request.setDestinationUri(Uri.fromFile(file));//下载文件外部存储URI
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);//通知栏可见性
long id = manager.enqueue(request);
return id;
}
注意:每建立一个下载任务后,都会返回一个不同的Id,即使前面已经建立了下载任务,所以在此要注意不要重复下载;获取下载进度,要使用建立下载任务时返回的Id,若要在进度条中动态显示进度,可使用 TimeTask或 Handler每1s/次 或更短时间查询进度:
public int queryProcess(long id) {
int percent = 0;
DownlaodMnager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Query query = new DownloadManager.Query();
Cursor cursor = manager.query(query.setFilterById(id));//只查看指定Id的下载任务
if (cursor != null && cursor.moveToFirst()) {
int total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));//App总大小
int progress = cursor.getInt(
cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));//已下载大小
if (total > 0)
percent = (progress * 100) / total;//计算百分比
}
if (cursor != null)
cursor.close();
return percent;
}获取下载状态,在获取下载进度的同时可以获取状态,并在界面显示-失败、暂停等:
public String queryStatus(long id) {
DownlaodMnager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Query query = new DownloadManager.Query();
Cursor cursor = manager.query(query.setFilterById(id));
if (cursor != null && cursor.moveToFirst()) {
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));//状态:成功、暂停、失败
switch (status) {
case DownloadManager.STATUS_FAILED:
stat = “下载失败”;
break;
…//其他状态可在源码中查看
}
}
if (cursor != null)
cursor.close();
return stat;
}取消下载任务:
public void cancelDownLoad(long id) {
if (manager != null && id != 0)
manager.remove(id);
}当下载成功后,需要跳转到系统的App安装界面,通过注册系统广播 android.intent.action.DOWNLOAD_COMPLETE,当监听到该广播时就可以直接去安装应用。
若将APK文件存储在系统的外部存储中,则安装文件时必须要取得系统读取外部存储权限,否则显示安装包读取失败。DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Uri uri = manager.getUriForDownloadedFile(id);
//
public static void installApp(Context context, Uri uri) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//适配 7.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setDataAndType(uri, “application/vnd.android.package-archive”);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//适配 8.0 相关
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!context.getPackageManager().canRequestPackageInstalls()) {
}
}
} else {
intent.setDataAndType(uri, “application/vnd.android.package-archive”);
}
context.startActivity(intent);
}