关于android7.0的FileProvider获取File路径
关于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对象进而拿到绝对路径了
有什么没考虑到的地方欢迎指出
文笔不好 哪里看不明白可以评论提问
下一篇: 解决启用Csrf后出现400错误
推荐阅读
-
php dirname(__FILE__) 获取当前文件的绝对路径
-
android实现Uri获取真实路径转换成File的方法
-
关于Python获取脚本所在目录路径的方法
-
关于File(path).listFiles()在android7.0及以上版本运行返回null的问题【实测有效】
-
Spring Boot内嵌tomcat关于getServletContext().getRealPath获取得到临时路径的问题
-
Spring Boot内嵌tomcat关于getServletContext().getRealPath获取得到临时路径的问题
-
关于获取input type='file'的大小疑点
-
fairytailmaintheme php dirname__FILE__ 获取当前文件的绝对路径
-
通过__FILE__灵活获取文件路径的方法
-
php dirname(__FILE__) 获取当前文件的绝对路径