Android 7.0 通过FileProvider在应用间文件共享

应用开发中遇到调用Intent打开文件地方无法出现选择。以为是个别用户手机上没有此类软件。后查看发现这些用户手机系统都是android7.0,查看7.0对于Intent的使用发现The increased level of file access security offered by a content URI makes FileProvider a key part of Android's security infrastructure.

android7.0之后,安全级别升级了。为了保护源文件,所以限制了其访问权限。使用第三方应用打开文件的时候会通过FileProvider ,生成 content URI允许您使用临时访问权限来授予读取和写入访问权限。关于FileProvider的介绍和使用。

我需要使用的功能是打开 文件

1.配置文件中定义FileProvider

FileProvider是v4包中一个继承ContentProvider的子类,位置是android.support.v4.content,他可以通过File创建一个content://类型的Uri而不是file://类型的Uri.所以我们在使用的使用首先需要在清单文件中注册一个provider

<provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="njxx.npc.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
</provider>

这里是直接使用的v4包中的FileProvider,我们也可以直接继承FileProvider类,适当重写重载函数,但不建议如此做。下面来介绍上面的几个设置:

  • name:provider的类名,若使用默认的v4的FileProvider可使用”android.support.v4.content.FileProvider”,也可以设置为自定义的继承FileProvider的provider类;
  • authorities:一个签名认证,可以自定义,但在获取uri的时候需要保持一致; 
    grantUriPermissions:使用FileProvider的使用需要我们给流出的URI赋予临时访问权限(READ和WRITE),该设置是允许我们行使该项权力;
  • meta-data:meta-data配置的是我们可以访问的文件的路径配置信息,需要使用xml文件进行配置,FileProvider会通过解析xml文件获取配置项,其中name名字不可改变为:android.support.FILE_PROVIDER_PATHS,resource为配置路径信息的配置项目。

2.创建file_paths文件

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="npc_files"
        path="/njxx/npc/download" />
    <external-path
        name="npc_apk"
        path="/njxx/npc/updated" />
</paths>

3.配置file_paths

路径配置 

     <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />

provider 配置信息 

<provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="njxx.npc.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
</provider>

 打开文件操作

    public void openFile(File file, Context context) {
        if (Build.VERSION.SDK_INT >= 23) {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            String type = getMIMEType(file);
            Uri uri = FileProvider.getUriForFile(context, "njxx.npc.fileprovider", file);
            intent.setDataAndType(uri, type);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            try {
                context.startActivity(intent);
            } catch (Exception var5) {
                var5.printStackTrace();
                Toast.makeText(context, "没有找到打开此类文件的程序", Toast.LENGTH_SHORT).show();
            }
        } else {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            String type = "application/vnd.android.package-archive";
            intent.setDataAndType(Uri.fromFile(file), type);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
        }
    }

获取文件类型 

    public String getMIMEType(File file) {
        String var1 = "";
        String var2 = file.getName();
        String var3 = var2.substring(var2.lastIndexOf(".") + 1, var2.length()).toLowerCase();
        var1 = MimeTypeMap.getSingleton().getMimeTypeFromExtension(var3);
        return var1;
    }

强制过滤 FileUriExposedException 异常

/**************解决Android 7.0 FileUriExposedException url异常***********************/
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
	StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
	StrictMode.setVmPolicy(builder.build());
}

猜你喜欢

转载自blog.csdn.net/nuonuonuonuonuo/article/details/81976201