欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android7.0 安装文件URI适配

程序员文章站 2024-03-19 15:58:04
...

问题:Android7.0环境中,使用下载好的安装文件安装时,出现“文件解析错误的页面”。

分析:

1)APK下载的过程没有问题,下载的文件能够手动安装;

2)调用系统安装APK文件,Android 6.0及以下的设备能够正常安装;

7.0系统安装错误。

发现是因为安装过程中出错。

//检测通过直接安装
					Intent newIntent = new Intent();
					newIntent.setAction(android.content.Intent.ACTION_VIEW);
					newIntent.setDataAndType(AppUtils.getUriFromFile(file), "application/vnd.android.package-archive");
					newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
					context.startActivity(newIntent);

其中从文件读取Uri的方法:

/**
     * 从文件获取Uri
     *
     * @param file : 文件
     */
    public static Uri getUriFromFile(File file) {
        Uri uri = null;
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
            //API23+ fix file uri: replace file:// uri with content:// uri:
            uri = FileProvider.getUriForFile(App.getInstance(),
					App.getInstance().getPackageName() + ".fileProvider",
                    file);
        } else {
            //API 23 can use file uri
            uri = Uri.fromFile(file);
        }
        return uri;
    }

AndroidManifest.xml中配置FileProvider:

        <!-- Android N 文件URI适配 -->
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.shouse.keeper.fileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"/>
        </provider>

android:authorities="${applicationId}.fileProvider"。需要和程序中的Provider名对应。

对应的文件共享路径设置:value/xml/provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!--内置SD卡 Environment.getExternalStorageDirectory() .表示共享所有的目录,也可以指定共享的目录-->
    <external-path
        name="external-path"
        path="." />
    <!--内置SD卡 Context.getExternalCacheDir() .表示共享所有的目录,也可以指定共享的目录-->
    <external-cache-path
        name="external-cache-path"
        path="." />
    <!--内置SD卡 Context.getExternalFilesDir(null) .表示共享所有的目录,也可以指定共享的目录-->
    <external-files-path
        name="external-files-path"
        path="." />
    <!--data目录下 Context.getFilesDir() .表示共享所有的目录,也可以指定共享的目录-->
    <files-path
        name="files_path"
        path="." />
    <!--data缓存目录 Context.getCacheDir() .表示共享所有的目录,也可以指定共享的目录-->
    <cache-path
        name="cache-path"
        path="." />
    <!--这个标签Android官方文档中是没有提及,Android设备的根目录,该目录下包含着手机内部存储器,外置SD卡等所有文件的目录-->
    <root-path
        name="name"
        path="." />
</paths>

3)分析发现文件的Uri转换没有问题,问题发生是因为安装语句问题。

在7.0以上需要设置Uri访问授权。

/**
     * 安装APK
     *
     * @param context : 上下文
     * @param file    : 文件
     */
    public static boolean installApkFile(Context context, File file) {
        if (null == file || !file.exists()) {
            return false;
        }
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
            //API23+ 需要增加授权属性
            Intent install = new Intent(Intent.ACTION_VIEW);
            install.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//添加这一句表示对目标应用临时授权该Uri所代表的文件
            install.setDataAndType(getUriFromFile(file), "application/vnd.android.package-archive");
            context.startActivity(install);
        } else {
            //API 23 direct install
            Intent newIntent = new Intent();
            newIntent.setAction(android.content.Intent.ACTION_VIEW);
            newIntent.setDataAndType(getUriFromFile(file), "application/vnd.android.package-archive");
            newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(newIntent);
        }
        return true;
    }

因为没有添加红色部分的语句,导致目标文件访问出错,总是提示文件解析错误。

3)文件通过FileProvider映射关系是怎么的呢?

File:   /storage/emulated/0/yangfang/download/file/housekeeper_2.3.0_signed.apk

Uri:    content://com.shouse.keeper.fileProvider/external_files/yangfang/download/file/housekeeper_2.3.0_signed.apk

外存储ExtranalPath:  /storage/emulated/0 -->  provider的根目录。












相关标签: 文件访问