
本文共 3559 字,大约阅读时间需要 11 分钟。
Android 8.0 适配:未知来源应用权限的解决方案
在之前的文章中,我们详细讲解了如何处理 Android 6.0 及以上版本的 APK 更新适配问题,并提供了相应的工具类实现方案。本文将延续上一篇的讲解,介绍如何在 Android 8.0 及以上版本中处理未知来源应用权限问题,确保 APK 更新成功完成。
适配 Android 8.0:未知来源应用权限的解决方案
在 Android 8.0(Oreo)版本及以上,未知来源应用的安装权限问题引起了很多开发者的困扰。相比于之前的版本,Android 8.0 等级严格地限制了未知来源应用的安装权限。具体表现为:在8.0 机型上直接更新 APK 将直接消失安装界面。
未知来源应用权限的开关
Android 8.0 的变更主要体现在以下几个方面:
适配步骤
为应对 Android 8.0 的变化,我们需要做以下配置:
清单文件声明权限:需要在 Android 清单文件中加入以下权限:
这些权限将自动引导用户进入权限设置页面进行授权。
动态权限申请:使用Android 8.0 的 API 提供的 canRequestPackageInstalls()
方法检查未知来源应用的权限状态:
boolean hasInstallPermission = getPackageManager().canRequestPackageInstalls();
如果权限未开启,应用将请求用户进入设置页面进行权限授权:
Uri selfPackageUri = Uri.parse("package:" + getPackageName());Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, selfPackageUri);startActivityForResult(intent, 100);
权限处理逻辑
在 Android 8.0 及以上版本中,权限的询问和回调设计得更为智能。例如在 APK 下载完成后,通过 InstallFinishedReceiver
接收下载完成的通知,并通过 content://downloads/my_downloads
URI 无缝连接已缓存的文件路径。
Android 8.0 共同适配工具类实现
为了适配不同版本的 Android 系统,我们提供了一个通用的 AppDownloadManager
工具类。该工具类能够兼容 Android 6.0(API 23)、7.0(API 24)、以及 8.0(API 26)版本。
工具类实现细节
1. 工具类初始化
在主活动中初始化 AppDownloadManager
,并将 下载 progress listener 注入到更新对话框中:
mDownloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);...mUpdateDialog = new AppUpdateDialog(this);... mUpdateListener = new OnUpdateListener() { @Override void update(int currentByte, int totalByte) { updateDialog.setProgress(currentByte, totalByte); if (currentByte == totalByte && totalByte > 0) { updateDialog.dismiss(); } }};
2. APK 下载流程
// 下载前需清理已下载的 APKFile existingApk = new File(getExternalFilesDir(DIRECTORY_DOWNLOADS), "app_name.apk");if (existingApk != null && existingApk.exists()) { existingApk.delete();}DownloadManager.Request request = new DownloadManager.Request(Uri.parse(apkUrl));request.setTitle("app_name");request.setDescription("版本号:v1.0.0");request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);...mReqId = mDownloadManager.enqueue(request);
3. 下载进度更新
通过 DownloadChangeObserver
和 DownloadReceiver
实现即时进度更新:
class DownloadChangeObserver extends ContentObserver { @Override void onChange(boolean selfChange) { super.onChange(selfChange); updateView(); }}
4. 安装授权逻辑
在 Android 8.0 及以上版本,安装未知来源的 APK 需要用户手动开启权限:
public void installAPK(Context context, Intent intent) { long completeDownloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { boolean hasInstallPermission = canRequestPackageInstalls(); if (!hasInstallPermission) { // 弹窗提示用户开启权限 // 并跳转至设置页面 startInstallPermissionActivity(context); } else { // 安装 APK install(context, completeDownloadId); } } else { // 6.0及以下版本直接安装 install(context, completeDownloadId); }}
使用说明
1. 显示更新提示框
在应用启动后检查是否有新版本,并显示通知:
if (hasUpdate) { showUpdateDialog(appUpdateInfo);}
2. 生命周期管理
确保在 Activity.onResume() 和 Activity.onPause() 中调用相关方法:
@Overridepublic void onResume() { super.onResume(); if (mDownloadManager != null) { mDownloadManager.resume(); }}@Overridepublic void onPause() { super.onPause(); if (mDownloadManager != null) { mDownloadManager.onPause(); }}
通过以上方案,可以轻松实现 Android 8.0 及更高版本的应用版本更新能力,同时兼容多个版本的适配需求。