给你一个眼神,自己体会

白日依山尽,黄河入海流。 欲穷千里目,更上一层楼。

Android 6.0 / 7.0 / 8.0 的APK安装

Android 6.0 / 7.0 / 8.0 的APK安装

最近适配安卓8.0后,发现游戏内自己强更整包安装会crash,于是就开始适配个版本的应用内APK安装。我发现一个问题就是,安卓6.0必须要存储权限才能安装,就是APK一定要下载到外部存储空间,才能调起安装器,其他版本都不需要,不知道是不是我哪里还没配置好。

Android 1.x~6.x APK安装
关于 android 7.0 之前的 apk安装,需要注意设置 Intent.FLAG_ACTIVITY_NEW_TASK 就好

Intent intent = new Intent(Intent.ACTION_VIEW);
Uri apkUri = Uri.fromFile(file);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
startActivity(intent);

Android 7.x APK安装
在 Android 7.0 引入了“私有目录被限制访问”,“StrictMode API 政策”。 Android 7.0 行为变更

” StrictMode API 政策” 是指禁止向你的应用外公开 file:// URI。使用上述方法安装APK时会出现 FileUriExposedException 异常。这个时候就需要使用FileProvider来解决这个问题:


步骤一 (FileProvider的申请),在Manifest.xml中定义一个FileProvider,代码如下:

<provider
    android:name="android.support.v4.content.FileProvider" // 指向v4包里的FileProvider类
    android:authorities="你的包名.FileProvider" // 对应你的content uri的基础域名,生成的uri将以content://你的包名.FileProvider作为开头
    android:exported="false" // 设置不允许导出,我们的FileProvider应该是私有的
    android:grantUriPermissions="true"> // 设置允许获取访问文件的临时权限
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/apk_provider_paths" /> // 用于设置FileProvider的文件访问路径
</provider>


 注意 android:authorities=”你的包名.FileProvider” 中 “你的包名”为你当前项目包名


步骤二 (创建 .xml),在res目录新建xml文件夹

xml文件下的 .xml文件名与步骤一中 android:resource=”@xml/apk_provider_paths”  引用的名称一致


步骤三 (配置FileProvider文件共享的路径),在 apk_provider_paths.xml文件中配置:



在标签中我们必须配置至少一个或多个path子元素, path子元素则用来定义content uri所对应的路径目录。 

这里说明一下, 例如将 APK 下载到了  Environment.getExternalStorageDirectory() + “/aaa/bbb” 目录下,则配置如下



如果你的 APK不是在 sdcard目录下,那么 apk_provider_paths.xml中的 paths 需要进行重新配置。具体可参考点击查看或者Android7.0

根据文档提示,我们使用FileProvider进行处理,同时利用xml对FileProvider进行配置 ,可参考如下

Java根路径产生方式 对应xml根节点名称
Context.getFilesDir() files-path
getCacheDir() cache-path
Environment.getExternalStorageDirectory()
external-path

Context#getExternalFilesDir(String) Context.getExternalFilesDir(null)
external-files-path
Context.getExternalCacheDir() external-cache-path
具体升级代码

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Uri apkUri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    // 授予文件操作的临时权限,根据需求设定,一般安装只需要READ权限
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);    
    intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    // 获取配置的FileProvider的 Content Uri的值
    apkUri = FileProvider.getUriForFile(mContext
        , "你的包名.FileProvider"
        , file);
} else {
    apkUri = Uri.fromFile(file);
}
intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
startActivity(intent);

Android 8.x APK安装
在Android 8.0 Oreo 中,Google 移除掉了容易被滥用的“允许位置来源”应用的开关,在安装 GooglePlay Store 之外的第三方来源的 Android 应用的时候,竟然没有了“允许未知来源”的检查框,如果你还是想要安装某个被自己所信任的开发者的 app,则需要授予“安装未知应用”的许可。

静态权限设置:

在Manifest.xml配置文件中添加以下权限,这个不是危险权限,可以不用动态申请。

<uses-permission android:name=”android.permission.REQUEST_INSTALL_PACKAGES”/>


zhou, guoshan