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; }
沒考慮到的地方歡迎留下腳印,謝謝!