Android(java)高版本 DownloadManager 封装工具类,支持 APK 断点续传与自动安装
主要有以下优点
- 兼容高版本 Android:适配 Android 10 及以上版本的存储权限和安装权限。
- 断点续传:支持从断点继续下载。
- 下载进度监听:实时获取下载进度并回调。
- 错误处理:处理下载失败、网络异常等情况。
- 自动安装 APK:下载完成后自动安装 APK 文件。
- 通知栏进度:显示下载进度和状态。
优化后的 DownloadManager 工具类
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import androidx.core.content.FileProvider;
import java.io.File;
public class DownloadUtils {
private static final String TAG = "DownloadUtils";
private static DownloadUtils instance;
private DownloadManager downloadManager;
private long downloadId;
private Context context;
private DownloadProgressListener progressListener;
private DownloadObserver downloadObserver;
private DownloadUtils(Context context) {
this.context = context.getApplicationContext();
downloadManager = (DownloadManager) this.context.getSystemService(Context.DOWNLOAD_SERVICE);
}
public static synchronized DownloadUtils getInstance(Context context) {
if (instance == null) {
instance = new DownloadUtils(context);
}
return instance;
}
/**
* 下载文件
*
* @param url 文件下载地址
* @param fileName 保存的文件名
* @param listener 下载进度监听器
*/
public void downloadFile(String url, String fileName, DownloadProgressListener listener) {
this.progressListener = listener;
// 创建下载请求
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setTitle("文件下载");
request.setDescription("正在下载文件...");
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
// 设置下载路径
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// Android 10 及以上版本,使用应用专属目录
request.setDestinationInExternalFilesDir(context, Environment.DIRECTORY_DOWNLOADS, fileName);
} else {
// Android 10 以下版本,使用公共下载目录
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
}
// 支持断点续传
request.setAllowedOverMetered(true); // 允许使用移动网络
request.setAllowedOverRoaming(true); // 允许漫游时下载
// 开始下载
downloadId = downloadManager.enqueue(request);
// 注册下载完成监听
context.registerReceiver(downloadCompleteReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
// 注册下载进度监听
if (progressListener != null) {
downloadObserver = new DownloadObserver(new Handler(Looper.getMainLooper()), downloadId);
context.getContentResolver().registerContentObserver(
Uri.parse("content://downloads/my_downloads"), true, downloadObserver);
}
}
/**
* 下载完成的广播接收器
*/
private final BroadcastReceiver downloadCompleteReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
if (id == downloadId) {
if (progressListener != null) {
progressListener.onDownloadComplete();
}
installApk(context);
}
}
};
/**
* 安装 APK 文件
*/
private void installApk(Context context) {
File apkFile;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// Android 10 及以上版本,使用应用专属目录
apkFile = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "app-update.apk");
} else {
// Android 10 以下版本,使用公共下载目录
apkFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), "app-update.apk");
}
if (!apkFile.exists()) {
Log.e(TAG, "APK 文件不存在");
return;
}
// 使用 FileProvider 获取文件的 Uri
Uri apkUri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", apkFile);
// 创建安装 Intent
Intent installIntent = new Intent(Intent.ACTION_VIEW);
installIntent.setDataAndType(apkUri, "application/vnd.android.package-archive");
installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 适配 Android 7.0 及以上版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
installIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
// 适配 Android 8.0 及以上版本,允许安装未知来源的应用
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!context.getPackageManager().canRequestPackageInstalls()) {
// 跳转到设置页面,允许安装未知来源应用
Intent intent = new Intent(android.provider.Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,
Uri.parse("package:" + context.getPackageName()));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
return;
}
}
context.startActivity(installIntent);
// 注销广播接收器和内容观察者
context.unregisterReceiver(downloadCompleteReceiver);
if (downloadObserver != null) {
context.getContentResolver().unregisterContentObserver(downloadObserver);
}
}
/**
* 下载进度观察者
*/
private class DownloadObserver extends ContentObserver {
private final long downloadId;
public DownloadObserver(Handler handler, long downloadId) {
super(handler);
this.downloadId = downloadId;
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
queryDownloadProgress();
}
private void queryDownloadProgress() {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(downloadId);
try (Cursor cursor = downloadManager.query(query)) {
if (cursor != null && cursor.moveToFirst()) {
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
int bytesDownloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
int bytesTotal = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
if (status == DownloadManager.STATUS_RUNNING && bytesTotal > 0) {
int progress = (int) ((bytesDownloaded * 100L) / bytesTotal);
if (progressListener != null) {
progressListener.onProgress(progress);
}
} else if (status == DownloadManager.STATUS_FAILED) {
if (progressListener != null) {
progressListener.onError("下载失败");
}
}
}
}
}
}
/**
* 下载进度监听器
*/
public interface DownloadProgressListener {
void onProgress(int progress); // 下载进度(0-100)
void onError(String message); // 下载失败
void onDownloadComplete(); // 下载完成
}
}
使用示例
// 初始化工具类
DownloadUtils downloadUtils = DownloadUtils.getInstance(context);
// 开始下载
downloadUtils.downloadFile("https://example.com/app-update.apk", "app-update.apk", new DownloadUtils.DownloadProgressListener() {
@Override
public void onProgress(int progress) {
Log.d(TAG, "下载进度: " + progress + "%");
}
@Override
public void onError(String message) {
Log.e(TAG, "下载失败: " + message);
}
@Override
public void onDownloadComplete() {
Log.d(TAG, "下载完成");
}
});
优化点说明
-
兼容高版本 Android:
- 使用
FileProvider
提供文件的 Uri,适配 Android 7.0 及以上版本。 - 适配 Android 8.0 及以上版本的未知来源应用安装权限。
- 使用
-
断点续传:
- 通过
setAllowedOverMetered
和setAllowedOverRoaming
支持断点续传。
- 通过
-
下载进度监听:
- 使用
ContentObserver
监听下载进度,并通过回调实时更新 UI。
- 使用
-
错误处理:
- 在
DownloadObserver
中检查下载状态,如果下载失败,通过onError
回调通知调用方。
- 在
-
自动安装 APK:
- 下载完成后自动安装 APK 文件,适配高版本 Android 的权限要求。
总结
该工具类封装了 DownloadManager
的核心功能,并针对高版本 Android 进行了优化,支持断点续传、下载进度监听和自动安装 APK 文件。适用于需要文件下载和 APK 升级功能的 Android 应用。