Android7.0共享文件权限

这个共享权限是准对第三方应用,你的App对外无法暴露file://类型的URI了。
解决方法:
1、需要在当前module的AndroidManifest.xml文件,添加provider标签

<manifest>
  <application>
    <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/path_file" /> 
     </provider> 
  </application>
</manifest>

2、在res目录下新建xml文件夹,并在当前文件夹新建一个xml文件,比如:path_file.xml

这里写图片描述

图中的意思就是名称可以随便起,文件内部是这样的,比如我用来读取图片的

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <paths>
     <external-path path="." name="files_path" />
  </paths>
</resources> 

这句话的意思就是说,我可以可以访问Environment.getExternalStorageDirectory()目录下的所有文件,没错,那个点就是指定所有(关于指定所有,有不同的说法,我觉得这个最靠谱),那么下面来说说不指定所有,以及其他路径。

我指定一个路径

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <paths>
     <external-path path="images/" name="files_path" />
  </paths>
</resources> 

以上表明的路径为:Environment.getExternalStorageDirectory()+/images/,在我的模拟器路径就是:/storage/emulated/0/images/

在程序中使用

private void camera()
{
    //调用系统拍照In
    Intent photoIn = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    //设置拍照后的保存路径
    String path = Environment.getExternalStorageDirectory().getPath()+"/images/image.jpg";
    File file = new File(path);
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
    {
        photoIn.putExtra(MediaStore.EXTRA_OUTPUT, file);
    } else
    {
        //7.0以后版本处理(需配置共享文件)
        Uri contentUri = FileProvider.getUriForFile(this
                    , BuildConfig.APPLICATION_ID + ".FileProvider"
                    , file);
        //对图片剪裁
        photoIn.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
    }
    startActivityForResult(photoIn, 100);
}

特别强调:

BuildConfig.APPLICATION_ID + ".FileProvider" == ${applicationId}.FileProvider == 包名.FileProvider,比如com.example.test.testapplication.FileProvider

此时:

 contentUri = content://com.example.test.testapplication.FileProvider/files_path/image.jpg

files_path,就是配置里面的name=”files_path”,那么path=”images/”呢
我们修改一下路径:String path = Environment.getExternalStorageDirectory().getPath()+”/abcd/image.jpg”;,这个路径没在共享里面配置,再次运行程序,问题来了

Caused by: java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/abcd/image.jpg

那么我再修改一下配置文件

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path path="images/" name="files_path" />
    <external-path path="abcd/" name="files_path" />
</paths>

恩,可以运行了
注意此时: 1、name 都是 files_path。
2、String path = Environment.getExternalStorageDirectory().getPath()+”/abcd/image.jpg”;

现在我再修改一下

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path path="abcd/" name="files_path" />
    <external-path path="images/" name="files_path" /> 
</paths>

就是调换了一下位置,其他的都不变,再次运行,又奔溃了

Caused by: java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/abcd/image.jpg

可以看出,有相同name的时候,只有最后一个生效,也就是path=”images/”的生效了,不信改一下name看看

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path path="abcd/" name="abcd_path" />
    <external-path path="images/" name="files_path" /> 
</paths>

name不一样了,以一张图来证明

这里写图片描述

到这里应该都知道怎么回事了,不知道?那就再看一遍

下面分享一下其他共享路径:

<external-path/>代表的根目录: Environment.getExternalStorageDirectory()
<files-path/>代表的根目录: Context.getFilesDir()
<cache-path/>代表的根目录: getCacheDir()
<external-files-path/>代表的根目录: Context.getExternalFilesDir(String) 
<external-cache-path />代表的根目录: Context.getExternalCacheDir()
<root-path />设备的根目录,用于访问外置SD卡

猜你喜欢

转载自blog.csdn.net/a598068693/article/details/77247417