您的位置:首页 > 移动开发 > Android开发

关于android7.0的FileProvider获取File路径

2018-01-30 14:51 1151 查看
关于FileProvider的使用,网上随便搜索一下,都有一堆使用的教程说明,但这些说明,都只是告诉我们配置FileProvider,使系统认识这个FileProvider. 但是在我的项目中需要的是获取文件的绝对路径,于是就有了这个文章.

说明

Android 7.0的新特性规定,对于android
7.0应用(仅仅对于android 7.0版本的sdk而言,若是编译版本低于25仍然不会受到影响),android框架使用StrictMode Api禁止我们的应用对外部(跨越应用分享)公开file://,若使用file://格式共享文件则会报FileUriExposedException异常,android
7.0应用间的文件共享需要使用content://类型的URI分享,并且需要为其提供临时的文件访问权限 
(Intent.FLAG_GRANT_READ_URI_PERMISSION和Intent.FLAG_GRANT_WRITE_URI_PERMISSION),对此,官方给我们的建议是使用FileProvider类进行分享.

由于android7.0的处理,

Uri uri = intent.getData();

我们使用这句话获取到的uri是一个content类型的uri,而不是file类型了,这与我们需要的(文件路径)是不一样的,在网上查询无果后,开始自己查看源码FileProvider

值得我们注意的是

public class FileProvider extends ContentProvider

这个FileProvider 继承自我们的ContentProvider,
interface PathStrategy {
Uri getUriForFile(File var1);

File getFileForUri(Uri var1);
}

还有这个接口 这个接口看起来就是用来封装uri和File的,

查看源码发现我们对我们开放的只有获取uri的方法并没有获取file的方法

public static Uri getUriForFile(Context context, String authority, File file) {
FileProvider.PathStrategy strategy = getPathStrategy(context, authority);
return strategy.getUriForFile(file);
}

于是想到了使用反射大法:
  直接贴上代码  当然这代码中我们必须要先拿到一个uri才行

List<PackageInfo> packs = this.getPackageManager().getInstalledPackages(PackageManager.GET_PROVIDERS);
if (packs != null) {

String fileProviderClassName = FileProvider.class.getName();
for (PackageInfo pack : packs) {
ProviderInfo[] providers = pack.providers;
if (providers != null) {
for (ProviderInfo provider : providers) {

if (uri.getAuthority().equals(provider.authority)){
if (provider.name.equalsIgnoreCase(fileProviderClassName)) {
Class<FileProvider> fileProviderClass = FileProvider.class;
try {
Method getPathStrategy = fileProviderClass.getDeclaredMethod("getPathStrategy", Context.class , String.class);
getPathStrategy.setAccessible(true);
Object invoke = getPathStrategy.invoke(null, this, uri.getAuthority());
if (invoke != null) {
String PathStrategyStringClass = FileProvider.class.getName()+"$PathStrategy";
Class<?> PathStrategy = Class.forName(PathStrategyStringClass);
Method getFileForUri = PathStrategy.getDeclaredMethod("getFileForUri", Uri.class);
getFileForUri.setAccessible(true);
Object invoke1 = getFileForUri.invoke(invoke, uri);
if (invoke1 instanceof File) {
filePath = ((File) invoke1).getAbsolutePath();

}
}

} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}

break;
}
Log.e(provider);
break;
}
}

}

}
}


这样我们就能拿到了 File对象进而拿到绝对路径了

有什么没考虑到的地方欢迎指出

文笔不好 哪里看不明白可以评论提问
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  FileProvider android7.0