欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > Android(java)高版本 DownloadManager 封装工具类,支持 APK 断点续传与自动安装

Android(java)高版本 DownloadManager 封装工具类,支持 APK 断点续传与自动安装

2025/3/16 18:59:00 来源:https://blog.csdn.net/tangweiguo03051987/article/details/146265400  浏览:    关键词:Android(java)高版本 DownloadManager 封装工具类,支持 APK 断点续传与自动安装

主要有以下优点

  1. 兼容高版本 Android:适配 Android 10 及以上版本的存储权限和安装权限。
  2. 断点续传:支持从断点继续下载。
  3. 下载进度监听:实时获取下载进度并回调。
  4. 错误处理:处理下载失败、网络异常等情况。
  5. 自动安装 APK:下载完成后自动安装 APK 文件。
  6. 通知栏进度:显示下载进度和状态。

优化后的 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() {@Overridepublic 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 获取文件的 UriUri apkUri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", apkFile);// 创建安装 IntentIntent 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;}@Overridepublic 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() {@Overridepublic void onProgress(int progress) {Log.d(TAG, "下载进度: " + progress + "%");}@Overridepublic void onError(String message) {Log.e(TAG, "下载失败: " + message);}@Overridepublic void onDownloadComplete() {Log.d(TAG, "下载完成");}
});

优化点说明

  1. 兼容高版本 Android

    • 使用 FileProvider 提供文件的 Uri,适配 Android 7.0 及以上版本。
    • 适配 Android 8.0 及以上版本的未知来源应用安装权限。
  2. 断点续传

    • 通过 setAllowedOverMeteredsetAllowedOverRoaming 支持断点续传。
  3. 下载进度监听

    • 使用 ContentObserver 监听下载进度,并通过回调实时更新 UI。
  4. 错误处理

    • DownloadObserver 中检查下载状态,如果下载失败,通过 onError 回调通知调用方。
  5. 自动安装 APK

    • 下载完成后自动安装 APK 文件,适配高版本 Android 的权限要求。

总结

该工具类封装了 DownloadManager 的核心功能,并针对高版本 Android 进行了优化,支持断点续传、下载进度监听和自动安装 APK 文件。适用于需要文件下载和 APK 升级功能的 Android 应用。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词