Android 7.0之後安裝APK,拍照 出現FileUriExposedException,多個provider配置

做項目在主頁檢查更新的時候,檢查到apk需要更新,於是我美滋滋的得到了下載的apk,然後調用一下去安裝apk方法,以爲理所當然的沒啥問題,可是當我下載完了的時候,在調用安裝的代碼時,拋出了一個異常FileUriExposedException,MMP 這是個什麼鬼,欺負我英語不好嗎,於是日常百度,搜嘎,原來由於

在android7.0,修改了對私有存儲的限制,而我的編譯版本爲25,導致在獲取資源的時候,不能通過Uri.fromFile(..)來獲取uri了,但是在寫入數據的時候是可以通過Uri.fromFile(..)來獲取uri的,android 官網給出的解決辦法是通過FileProvider來解決這一問題,我們需要在AndroidManifest.xml 配製provider節點 

原來如此那就好整了,開幹開幹

第一步: 在AndroidManifest.xml文件添加  provider節點配置
<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.fileprovider"
    android:grantUriPermissions="true"
    android:exported="false">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_path" />
</provider>
注意了,這個applacationId 必須要在grade文件裏面配置哦 如果你不配置的話你可以直接寫上你的包名

第二步: 在res文件夾下面新建一個xml文件夾,然後在xml文件夾中新建一個xml 這個xml的名字
必須與你在第一步的配置文件裏面名字一致,如圖



第三步 xml 裏面的內容
<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path path="Android/data/你的包名/" name="files_root" />
    <external-path path="." name="external_storage_root" />
</paths>


注意了 這裏請必須要填上你自己的包名,
ok了,文件都配置好了,就差最後的代碼了,

第四步
/** 安裝一個apk文件 */
public static void install(Context  context, File uriFile) {
    Intent intent = new Intent(Intent.ACTION_VIEW);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        Uri contentUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID+".fileprovider", uriFile);
        intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
    } else {
        intent.setDataAndType(Uri.fromFile(uriFile), "application/vnd.android.package-archive");
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    }
    if (App.getIntence().getPackageManager().queryIntentActivities(intent, 0).size() > 0) {
        App.getIntence().startActivity(intent);
    }
}
這裏要注意的是這句代碼,這裏BuildConfig 是導入的我當前項目的包名,如果你不想這麼做的話,你可以直接寫你自己的包名列如: 包名com.test 來替換

題外:
我們項目中可能會用到其他一些第三方sdk有用到拍照功能或者關於某些獲取資源操作的話,他爲了適配android7.0也添加了這個節點,此時有些人可能就不知道如何下手了,其實很簡單我們只要重寫一個類 繼承自FileProvider,然後就按上述方法在添加一個節點就可以了;例如:
public class MyFileProvider extends FileProvider {
    
}


然後
<provider
    android:name=".util.MyFileProvider"
    android:authorities="${applicationId}.provider"
    android:grantUriPermissions="true"
    android:exported="false">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>


這個file_paths文件 是第三方sdk的 而不是我新建的那個
大功告成~~~


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章