这个共享权限是准对第三方应用,你的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卡