Android N 中共享文件
Android N 系统,Android 框架执行的 StrictMode,API 禁止向您的应用外公开 file://URI。
如果一项包含文件 URI 的 Intent 离开您的应用,应用会停止运行,并出现 FileUriExposedException异常。
android.os.FileUriExposedException: file:///storage/emulated/0/Download/appName-2.3.0.apk exposed beyond app through Intent.getData()
若要在应用间共享文件,您应发送一项 content://URI,并授予 URI 临时访问权限。
进行此授权的最简单方式是使用 FileProvider类。
如何共享文件
1、在AndroidManifest.xml中标签下添加如下代码
注意:
authorities:权限名称,可自己定义()
grantUriPermissions:必须是true,表示授予 URI 临时访问权限 ( readPermission, writePermission, and permission attributes)
exported:true: The provider is available to other applications. false: The provider is not available to other applications.
resource:自定义的xml文件(下面会介绍)
2、在res目录下新建一个xml文件夹,并且新建一个file_paths的xml文件(如下图)
3、打开file_paths.xml文件添加如下内容
path:需要临时授权访问的路径(.代表所有路径)
name:给这个访问路径起个名字
代表的根目录: getCacheDir()
4、修改代码适配Android N
Intent intent = new Intent(Intent.ACTION_VIEW);
//判断是否是AndroidN以及更高的版本
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
/* 这句要记得写:这是申请权限,之前因为没有添加这个,打开裁剪页面时,一直提示“无法修改低于50*50像素的图片”,开始还以为是图片的问题呢,结果发现是因为没有添加FLAG_GRANT_READ_URI_PERMISSION。 如果关联了源码,点开FileProvider的getUriForFile()看看,注释就写着需要添加权限。 */
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
/*getUriForFile(Context context, String authority, File file):此处的authority需要和manifest里面保持一致。以前我们直接 Uri.fromFile(apkFile)构建出一个Uri,现在我们使用FileProvider.getUriForFile(); */
Uri contentUri = FileProvider.getUriForFile(context, 自定义的权限名, apkFile);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
startActivity(intent);
下面FileProvider的getUriForFile()方法的注释:
/**
* Return a content URI for a given {@link File}. Specific temporary
* permissions for the content URI can be set with
* {@link Context#grantUriPermission(String, Uri, int)}, or added
* to an {@link Intent} by calling {@link Intent#setData(Uri) setData()} and then
* {@link Intent#setFlags(int) setFlags()}; in both cases, the applicable flags are
* {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} and
* {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION}. A FileProvider can only return a
* content
{@link Uri} for file paths defined in their
* meta-data element. See the Class Overview for more information.
*
* @param context A {@link Context} for the current component.
* @param authority The authority of a {@link FileProvider} defined in a
* {@code } element in your app's manifest.
* @param file A {@link File} pointing to the filename for which you want a
* content
{@link Uri}.
* @return A content URI for the file.
* @throws IllegalArgumentException When the given {@link File} is outside
* the paths supported by the provider.
*/
public static Uri getUriForFile(Context context, String authority, File file) {
final PathStrategy strategy = getPathStrategy(context, authority);
return strategy.getUriForFile(file);
}