android8.0以上权限变更,若apk内下载安装包后安装,首先需要确认是否有安装未知来源应用程序的权限。
首先,需要在清单文件内加入以下权限:
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
其次,是代码的相关逻辑判断,废话不多说,看代码:
if (Build.VERSION.SDK_INT >= 24) {//判读版本是否在7.0以上
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//判断是否是8.0或以上
boolean haveInstallPermission = mContext.getPackageManager().canRequestPackageInstalls();
if (!haveInstallPermission) {
Uri packageURI = Uri.parse("package:" + mContext.getPackageName());
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, packageURI);
activity.startActivityForResult(intent, 10001);
}else{
Uri apkUri = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID + ".fileprovider", new File(apkpath));
Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
install.setDataAndType(apkUri, "application/vnd.android.package-archive");
mContext.startActivity(install);
}
} else {
Uri apkUri = FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".fileprovider", new File(apkPath));
Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
install.setDataAndType(apkUri, "application/vnd.android.package-archive");
activity.startActivity(install);
}
} else {
Intent install = new Intent(Intent.ACTION_VIEW);
install.setDataAndType(Uri.fromFile(new File(apkPath)), "application/vnd.android.package-archive");
install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
activity.startActivity(install);
}
具体逻辑是:1.若为7.0以下,正常安装
2.若为7.0,8.0以下,使用FileProvider拿到路径,进行安装
3.若为8.0以上,首先需要通过canRequestPackageInstalls()方法判断,是否有允许未知来源应用安装的权限,
如果有的话,同2进行安装,
如果没有的话,通过intent的addFlag,唤起未知来源权限的操作界面,需要手动打开,然后需要在activity的
onActivityResult中进行返回判断,代码如下:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 10001) {
if (resultCode == RESULT_OK) {
Uri apkUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileprovider", new File(ReaderApplication.getInstace().filePath));//在AndroidManifest中的android:authorities值
Intent install = new Intent(Intent.ACTION_VIEW);
install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
install.setDataAndType(apkUri, "application/vnd.android.package-archive");
this.startActivity(install);
} else {
ToastUtils.showLong(this, "未打开'安装未知来源'开关,无法安装,请打开后重试");
}
}
}
除此之外,需要在清单文件定义fileprovider,如下:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<!-- 元数据 -->
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
其中的file_paths需要在xml文件中定义:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<external-path path="" name="download"/>
</paths>
</resources>
还有最后一个比较核心的问题,若需要判断8.0以上的权限问题,项目的targetSdkversion必须为26或者26以上,如果为26以下的话,canRequestPackageInstalls()方法返回的值会一直为false,我就是在这里卡了比较久,因为公司项目比较多,其他版本改了,这个版本没改,给忘记了,所以,大家要注意。
ok,问题记录完成