安卓7.0 ,8.0手机上遇到的app升级问题终极解决方案

 兼容Android 7.0 及8.0 App升级

 Android7.0变化点:
 出于安全机制的考虑,从安卓7.0开始获取uri的方式改为

Uri apkUri = FileProvider.getUriForFile(mContext, getPackageName() + ".fileprovider", appFile);

Android7.0之前的版本获取uri还是之前的方式

Uri apkUri = Uri.fromFile(appFile)

Android8.0变化点:

安卓8.0设置页面新增了 允许安装未知来源app 按钮,app在进行升级安装的时候需要先判断此开关是否已经打开了,如果没打开,需要跳转到设置页面进行打开,之后返回继续进行app升级安装。


一、在AndroidManifest.xml清单文件中注册Provider

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.cuileikun.androidbase.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/cui_file_paths"
        tools:replace="android:resource"/>
</provider>

authorities: 常用命名为包名+fileprovider
exported要求必须为false,为true会报安全异常
grantUriPermissions表示URI临时访问权限,true为需要临时访问权限

resource指当前组件引用res文件夹中qk_file_paths文件,这个文件名可以随便写,只要在res文件夹中有这个文件即可。

在res文件夹中新建xml文件夹,再新建cui_file_paths.xml文件,内容如下

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <paths>
        <external-path
            name="files_root"
            path="Android/data/com.cuileikun.androidbase/" />
        <external-path
            name="external_storage_root"
            path="." />
        <!-- yan  notice:  do not  edit     -->
        <root-path path="" name="camera_photos" />
    </paths>
</resources>

path填上Android/data/包名

二、安装Apk时注意兼容高低版本

 /**
     * 安装新版本应用
     */
    private void installApp() {
        File appFile = new File(FILE_NAME);
        if (!appFile.exists()) {
            return;
        }
        // 跳转到新版本应用安装页面
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (Build.VERSION.SDK_INT >= 24) { //判断是否是AndroidN (安卓7.0)以及更高的版本
            //参数1 上下文, 参数2 Provider主机地址 和配置文件中保持一致   参数3  共享的文件
            Uri apkUri = FileProvider.getUriForFile(mContext, getPackageName() + ".fileprovider", appFile);
           
            //添加这一句表示对目标应用临时授权该Uri所代表的文件
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
            //兼容8.0
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                boolean hasInstallPermission = mContext.getPackageManager().canRequestPackageInstalls();
                if (!hasInstallPermission) {
                    startInstallPermissionSettingActivity();
                    return;
                }
            }
        } else {
            intent.setDataAndType(Uri.fromFile(appFile), "application/vnd.android.package-archive");
        }
        startActivity(intent);
        android.os.Process.killProcess(android.os.Process.myPid());
    }

    /**
     * 跳转到设置-允许安装未知来源-页面
     */
    @RequiresApi(api = Build.VERSION_CODES.O)
    private void startInstallPermissionSettingActivity() {
        Uri packageUri = Uri.parse("package:" + getPackageName());
        //注意这个是8.0新API
        Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageUri);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mContext.startActivityForResult(intent, 10086);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 10086) {
            installApp();
        }
    }
  主要是注意getUriForFile方法中的参数,第二个参数为BuildConfig.APPLICATION_ID + “.fileprovider”

即包名+.fileprovider,这个和AndroidManifest中的Provider中的属性authorities一致

 

参考链接:

http://www.2cto.com/kf/201704/622561.html

发布了82 篇原创文章 · 获赞 28 · 访问量 9万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览