安卓项目实战之:APP版本更新适配 Android 8.0
发布日期:2021-05-10 14:01:16 浏览次数:14 分类:精选文章

本文共 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 通过 Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES 替换了之前的未知来源应用安装权限开关,权限的开启或关闭将由用户主动选择。
  • 默认状态:如果应用未在设置中明确声明会访问未知来源,那么一次性下载可能会自动触发权限询问。
  • 适配步骤

    为应对 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. 下载进度更新

    通过 DownloadChangeObserverDownloadReceiver 实现即时进度更新:

    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 及更高版本的应用版本更新能力,同时兼容多个版本的适配需求。

    上一篇:安卓项目实战之:字体设置相关以及库Calligraphy的使用
    下一篇:安卓项目实战之:基于StackBlur封装的好用的高斯模糊组件

    发表评论

    最新留言

    感谢大佬
    [***.8.128.20]2025年05月08日 18时35分05秒