解決Android7.0調用相機拋出的FileUriExposedException異常

在Android7.0版本及7.0以上的手機上按照傳統的寫法會拋出一個FileUriExposedException異常,這是因為7.0的版本改了一些東西,在獲取相機或相冊的圖片中的Uri時,即file://URI開頭的Uri離開了相機或相冊應用,就會觸發7.0文件uri權限 FileUriExposedException。在網上也查閱了一些資料,谷歌推薦的解決方式是使用FileProvider。

第一步:配置provider

在AndroidManifest.xml中的application標簽中添加以下代碼:
注意:不管你是在主項目下調用相機還是在library中調用相機,都可以在主項目下配置即可,只要包名一致就不會異常。。

        <provider
            android:name="android.support.v4.content.FileProvider" //固定值
            android:authorities="包名.fileprovider"http://包名.fileprovider,包名寫自己的
            android:exported="false"http://必須為flase
            android:grantUriPermissions="true">//必須為true
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"http://固定值
                android:resource="@xml/file_paths"/>//在res目錄下定義的file_paths.xml文件,名字可以自定義
        </provider>

第二步:配置file_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="camera_photos" path="."  /> //.代表任意目錄
    <external-path name="cache" path="Android/data/包名/cache" />  //這里包名寫成你自己的
    <external-path name="images" path="Pictures/" />
    <external-path name="dcim" path="DCIM/" />
</paths>

第三步:判斷Android版本,分別調用

private File mTmpFile;
//開始調用相機
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getActivity().getPackageManager()) != null) {
    try {
        mTmpFile = FileUtils.createTmpFile(getActivity());
    } catch (IOException e) {
        e.printStackTrace();
    }
    if (mTmpFile != null && mTmpFile.exists()) {
        //適配Android7.0版本調用相機 API24
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            Log.i("TAG", "Android7.0以及7.0版本以上的手機");
            Uri uriForFile = FileProvider.getUriForFile(getActivity()
                    , "包名.fileprovider", mTmpFile);//這里包名寫自己的
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uriForFile);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        } else {
            Log.i("TAG", "Android7.0以下版本的手機");
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTmpFile));
        }
        startActivityForResult(intent, REQUEST_CAMERA);
    } else {
        Toast.makeText(getActivity(), "圖片錯誤", Toast.LENGTH_SHORT).show();
    }
} else {
    Toast.makeText(getActivity(), "沒有系統相機", Toast.LENGTH_SHORT).show();
}

OK,這樣在7.0以上和以下的手機上調用都不會崩潰報異常了,在這里做個總結,希望幫助更多的碼農避免踩坑?。。?/p>

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容