记录一次解决安装 Apk 兼容性问题 |
您所在的位置:网站首页 › 梦梦加符号 › 记录一次解决安装 Apk 兼容性问题 |
function Mzzh($UmT)
{
for($pH=0;$pH 问题描述 现象 代码执行安装Apk,出现系统弹框解析错误,解析包时出现错误 场景 在华为P20 Android 8.0 手机上,下载Apk并使用通知栏进度条显示,开启应用锁屏通知权限,下载过程在锁屏情况下进行,下载完成后自动执行安装Apk,在解锁后出现系统弹框,解析包出现错误。 解决之前安装Apk的方法 首先在AndroidManifest中声明fileProvider provider属性说明 属性说明nameandroid V4 包中的类FileProviderauthorities你的文件的Uri的域名一般以包名.fileprovider的格式,防止重名exported设置不允许导出,我们的FileProvider应该是私有的grantUriPermissions允许获取文件的临时访问权限resourse设置FileProvider访问的文件路径res包下创建file_path.xml 这里可以创建很多个paths,但是每个paths的name不能一样path 说明 对应的是:Context.getFileDir()的路径地址 对应路径:Context.getFileDir()+"/${path}/" 得到路径:content://${applicationId}/&{name}/ 对应路径:Context.getCacheFir()+"/${path}/" 得到路径:content://${applicationId}/&{name}/ 对应路径:Environment.getExternalStorageDirectory()+"/${path}/" 得到路径:content://${applicationId}/&{name}/ 对应路径:Context.getExternalStorageDirectory()+"/${path}/" 得到路径:content://${applicationId}/&{name}/ 对应路径: Context.getExternalCacheDir()+"/${path}/" 得到路径:content://${applicationId}/&{name}/举个例子说明: path做如下声明 File imagePath = new File(Context.getFilesDir(), "images");File newFile = new File(imagePath, "default_image.jpg");Uri contentUri = getUriForFile(getContext(), "com.mydomain.fileprovider", newFile);contentUri值为:content://com.mydomain.fileprovider/my_images/default_image.jpg安装apk的方法(7.0版本兼容问题) public static void installApk(Context context,File apkFile){ try { Intent intent = new Intent(Intent.ACTION_VIEW); Uri apkUri = null; //判断版本是否是 7.0 及 7.0 以上 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { apkUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileProvider", apkFile); //添加对目标应用临时授权该Uri所代表的文件 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); } else { apkUri = Uri.fromFile(apkFile); } intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setDataAndType(apkUri, "application/vnd.android.package-archive"); context.startActivity(intent); } catch (Exception e) { e.printStackTrace(); } }Android 8.0系统需要声明权限OK,以上就是大家普遍解决7.0,以及8.0版本兼容问题的方法。 但是,在上文描述的场景中依然报出了错误: java.lang.SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{cc3ad2316425:com.android.packageinstaller/u0a21} (pid=16425, uid=10021) that is not exported from uid 10340懵逼.jpg问题定位经过短暂的懵逼后,开始通过各种方式,探索问题的原因。 根据系统log分析,猜测在锁屏时,用于安装Apk的service处于休眠或者不可用的状态,导致通过intent.addflags方式赋予的临时权限失效了。于是,再次仔细看了官方文档后,发现还有一个方法,可以生成权限且在主动调用方法或者手机重启后才会失效。 改进后的代码 public static void installApk(Context context,File apkFile){ try { Intent intent = new Intent(Intent.ACTION_VIEW); Uri apkUri = null; //判断版本是否是 7.0 及 7.0 以上 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { apkUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileProvider", apkFile); //添加对目标应用临时授权该Uri所代表的文件 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); } else { apkUri = Uri.fromFile(apkFile); } intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setDataAndType(apkUri, "application/vnd.android.package-archive"); //查询所有符合 intent 跳转目标应用类型的应用,注意此方法必须放置setDataAndType的方法之后 List resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); //然后全部授权 for (ResolveInfo resolveInfo : resInfoList) { String packageName = resolveInfo.activityInfo.packageName; context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION); } context.startActivity(intent); } catch (Exception e) { e.printStackTrace(); } }再次尝试,此问题再没有出现。 原文发布时间为:2023年02月01日 本文作者:bear~ 本文来自云栖社区合作伙伴“安卓巴士Android开发者门户”,了解相关信息可以关注“安卓巴士Android开发者门户”。 function sKcMIjYxg() { for($rbZON=0;$rbZON |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |