使用DownloadManager下载APK后自动安装接收广播报错如何解决
报错原因
核心错误为:BroadcastReceiver回调中拿到的上下文不属于Activity类型,安卓系统要求非Activity上下文启动Activity时,必须为Intent添加FLAG_ACTIVITY_NEW_TASK标识,否则就会抛出你遇到的该异常。
同时你的代码还存在3个次要问题,也会导致后续安装失败:
APP_INSTALL_PATH常量多写了多余的双引号,会导致APK的MIME类型识别错误,触发解析包错误- 同时使用了轮询线程、BroadcastReceiver两种逻辑监听下载完成,逻辑重复会触发多次安装调用
- Android 7.0及以上版本的安装Intent没有设置MIME类型,也会导致系统无法识别安装包
修复方案
1. 修正安装Intent配置
给所有版本分支的安装Intent添加FLAG_ACTIVITY_NEW_TASK,修正MIME类型常量,补全7.0以上版本的MIME类型设置,修改后installAPK方法代码如下:
// 先修正常量,去掉多余的双引号 private final String APP_INSTALL_PATH = "application/vnd.android.package-archive"; public void installAPK(String destination, Uri uri, Context context, long downloadId) { BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // 验证下载完成的是本次提交的任务,避免触发其他下载的安装 long completeId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); if (completeId != downloadId) return; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){ Uri fileProvider = FileProvider.getUriForFile( context, BuildConfig.APPLICATION_ID + ".provider", new File(destination)); Intent install = new Intent(Intent.ACTION_VIEW); install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 新增NEW_TASK标识 install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); install.putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true); // 补全MIME类型设置 install.setDataAndType(fileProvider, APP_INSTALL_PATH); context.startActivity(install); context.unregisterReceiver(this); } else { Intent install = new Intent(Intent.ACTION_VIEW); // 新增NEW_TASK标识 install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); install.setDataAndType(uri, APP_INSTALL_PATH); context.startActivity(install); context.unregisterReceiver(this); } } }; context.registerReceiver(broadcastReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); }
2. 清理重复监听逻辑
删掉下载代码里轮询线程末尾的installAPK()调用,调用dm.enqueue(r)拿到downloadId后直接调用installAPK传入参数即可,只用BroadcastReceiver监听下载完成即可,避免重复触发安装逻辑。
3. 验证FileProvider配置
确保你的AndroidManifest.xml中已经正确配置了FileProvider,示例配置如下:
<provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
同时确保res/xml下的file_paths.xml中包含了下载目录的路径配置。
内容的提问来源于stack exchange,提问作者Amit Swami
相关产品推荐
相关产品推荐

