Android代码安装apk程序

  • Post author:
  • Post category:其他




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

高版本提高了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. 安全提示要选择允许

    在这里插入图片描述



版权声明:本文为lanlangaogao原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。