1:引言
为了提高私有目录的安全性,防止应用信息的泄漏,从 Android 7.0 开始,应用私有目录的访问权限被做限制。具体表现为,开发人员不能够再简单地通过 file:// URI 访问其他应用的私有目录文件或者让其他应用访问自己的私有目录文件。
同时,也是从 7.0 开始,Android SDK 中的 StrictMode 策略禁止开发人员在应用外部公开 file:// URI。具体表现为,当我们在应用中使用包含 file:// URI 的 Intent 离开自己的应用时,程序会发生故障。
开发中,如果我们在使用 file:// URI 时忽视了这两条规定,将导致用户在 7.0 及更高版本系统的设备中使用到相关功能时,出现 FileUriExposedException 异常,导致应用出现崩溃闪退问题。而这两个过程的替代解决方案便是使用 FileProvider
。
2:FileProvider配置
3:FileProvider获取Uri
/** * 获取FileProvider path * author zx * since 2018/5/4 . * version 1.0 */ Uri contentUri = FileProvider.getUriForFile(Context context, String authority, File file);
4:通过上述生成的Uri,获取文件绝对路径(使用反射)
/** * 获取FileProvider path * author zx * version 1.0 * since 2018/5/4 . */ private static String getFPUriToPath(Context context, Uri uri) { try { List<PackageInfo> packs = context.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, context, 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) { String filePath = ((File) invoke1).getAbsolutePath(); return filePath; } } } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } break; } break; } } } } } } catch (Exception e) { e.printStackTrace(); } return null; }
PS:没考虑到的地方欢迎留下脚印,谢谢哈!