Android代码安装apk程序

本文详细介绍了在Android应用中如何处理高低版本兼容问题,特别是针对Android7.0及以上版本,通过ContentProvider来实现对SD卡和私有数据文件的访问。主要涉及Java代码、AndroidManifest.xml配置以及paths.xml的设置。此外,还提到了老版本代码的实现方式以及可能出现的问题和解决方案,如权限问题和路径匹配错误。
摘要由CSDN通过智能技术生成

一、高低版本兼容代码及配置

高版本提高了sdcard、 app文件空间的访问权限,高低版本的系统api有一定区别,Android7.0 及以上,开放(暴露)私有数据文件的唯一方式是通过 ContentProvider 来实现(我们的app提供我们的文件给系统安装程序)。

基本步骤
1、在AndroidManifest.xml 中配置 ContentProvider 信息;
2、配置要开放的 paths 信息;
3、Java 代码中通过 FileProvider 封装文件信息。

1.java代码

private void install(String path) {
       File apk = new File(path);
       Intent intent = new Intent(Intent.ACTION_VIEW);
       intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
           intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
           //注意第二个参数,要保持和manifest中android:authorities的值相同
           Uri uri = FileProvider.getUriForFile(context, 
           									context.getPackageName() + ".fileProvider", apk);
           intent.setDataAndType(uri, "application/vnd.android.package-archive");
       } else {
           intent.setDataAndType(Uri.fromFile(apk), "application/vnd.android.package-archive");
       }
       try {
           context.startActivity(intent);
       } catch (Exception e) {
           e.printStackTrace();
       }
   }

特别注意
Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + “.fileProvider”, apk);
第二个参数一定要和provider 的android:authorities="${applicationId}.fileProvider"匹配。
applicationId是包名,context.getPackageName()也是包名,所以
context.getPackageName() + “.fileProvider”${applicationId}.fileProvider 是相同的字符串

2.AndroidManifest.xml 配置ContentProvider

配置安装权限

<!-- 应用安装权限 -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

配置ContentProvider

<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_provider" />
</provider>

provider 属性说明:

  1. android:name 属性填写的是 FileProvider 类的完整名称。这个类可以填写两个值,一个是位于 support(android.support.v4.content.FileProvider) 包下的,另一个是位于 androidx(androidx.core.content.FileProvider) 包下的。这两种都可以填写,本质上没有区别。要根据实际情况来决定用哪个,即要看工程引的是 androidx 支援包还是 support 支援包。

  2. android:authorities 属性就是和普通的 ContentProvider 一样的用于访问文件资源的 uri 标签头。值内容根据实际需要来填写即可。

  3. android:exported android:grantUriPermissions 两个属性的值照着填就好。大致是指允许其它应用单次使用自己的 Provider 资源。

  4. meta-data 标签中的内容需要关注的是 android:resource 属性中的内容。这个属性的值引向一个 xml目录的文件,这份 xml 文件描述要给其他应用访问的文件目录。

3.paths xml 配置

在工程 res 目录下新建一个 xml 没有的话新建)目录,则在目录中创建一个file_provider.xml(名称随意,和 android:resource=“@xml/file_provider” 一致即可),并在xml中添加需要对外提供的目录路径

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="path1"
        path="/data/dir1/" />
    <external-path
        name="path2"
        path="/" />
    <external-files-path
        name="path3"
        path="/data/dir2" />
    <external-cache-path
        name="path4"
        path="/data/dir3" />
    <cache-path
        name="path5"
        path="/data" />
    <files-path
        name="path6"
        path="/ff" />
</paths>

简要说明:
不带external 是程序安装目录下的目录,cache-path 指程序安装目录下的cache目录。
带有external 的是指sdcard 目录下对应包名的专属目录,例如external-cache-path 指sdcard 目录下对应包名的专属cache目录。

例如下图是斗鱼直播的files目录:

<external-files-path
        name="path3"
        path="/" />

对应下图
在这里插入图片描述
如果还有子目录,对应的增加接口,例如files 目录下的douyu, 那么xml如下:

<external-files-path
        name="path3"
        path="/douyu/" />

二、老版本代码

老版本代码相对简单,粗暴且实用,只要知道 apk 的path,并拥有访问权限(sdcard),
再加上安装权限即可。

File apk = new File(apkPath);
Uri uri = Uri.fromFile(apk);
Intent intent = new Intent();
intent.setClassName("com.android.packageinstaller", 
					"com.android.packageinstaller.PackageInstallerActivity");
intent.setData(uri);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

manifest 添加对应的权限

<!--sdcard 读权限-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

三、可能出的问题及处理

  1. java.lang.NullPointerException: Attempt to invoke virtual method ‘android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)’ on a null object reference
    at android.support.v4.content.FileProvider.parsePathStrategy(FileProvider.java:591)
    原因:FileProvider.getUriForFile(context, context.getPackageName() + “.fileProvider”, apk); 第二个参数 “包名.fileProvider” 和 provider.xml 中 android:authorities=“${applicationId}.fileProvider” 的值(具体值:如com.eagle.app.fileProvider)不同,请仔细核对和修改一致。
  2. 权限问题
    一般app需要安装权限,除了在清单文件中列出外,还需要手动确认,注意留意并确认
  3. 下载的安装文件路径与file_provider 中描述的文件不匹配,仔细核对路径与描述。
  4. 安全提示要选择允许
    在这里插入图片描述
  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值