Android webview打開相機閃退報android.os.FileUriExposedException 問題解決記錄


1.背景

最近優化公司的一款老app。app采用vue+webview+android。為實現產品奇奇怪怪的需求把targetSdkVersion從23升級到了26.然后就出現了UI框架打開相機時閃退的問題。通過錯誤日志定位到問題android.os.FileUriExposedException.

2.問題產生原因

 android7.0后加了私有目錄被限制訪問所以,Uri.fromFile(file)方法訪問file://url會出現android.os.FileUriExposedException異常。

3.解決方案

3.1;在AndroidManifest.xml 清單文件中加入provider。

<application
...
<activity
..
 </activity>

 <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        
 </provider>
<application

3.2.在res->xml目錄下新建file_paths.xml

 

 

 

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

3.3

在具體保存代碼修改

        //imageUri = Uri.fromFile(file);
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M){
            imageUri = Uri.fromFile(file);
        }
        else {
            imageUri= FileProvider.getUriForFile(this, this.getPackageName() + ".provider", file);
        }

注釋掉的是原來代碼。在android7.0以上用FileProvider.getUriForFile(context,context.getPackageName() + ".provider", file);替換Uri.fromFile(file);

 

4.可能有的小伙伴和我一樣是webview+H5開發的,然后使用html打開的相機。那么在哪修改imageUri 呢。我是這樣做的


4.1打開相機html代碼
 <van-uploader v-model="fileList" max-count="1" preview-size="150px" upload-text="點擊打開相機,拍照"
            :after-read="afterRead" multiple accept="image/*" />

  4.2webview里重寫WebChromeClient

mWebView.setWebChromeClient(mWebChromeClient);
private WebChromeClient mWebChromeClient = new WebChromeClient() {

        @Override
        public void onGeolocationPermissionsShowPrompt(final String origin, final GeolocationPermissions.Callback callback) {
            callback.invoke(origin, true, true);
        }

        //>5.0.1
        @Override
        public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
            mUploadCallbackAboveL = filePathCallback;
            take();
            return true;
        }
        //<3.0

        public void openFileChooser(ValueCallback<Uri> uploadMsg) {
            mUploadMessage = uploadMsg;
            take();
        }

        //>3.0+
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
            mUploadMessage = uploadMsg;
            take();
        }

        //>4.1.1
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
            mUploadMessage = uploadMsg;
            take();
        }
    };

 take()方法里修改

private void take() {
        File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyApp");
        if (!imageStorageDir.exists()) {
            imageStorageDir.mkdirs();
        }
        File file = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
        //imageUri = Uri.fromFile(file);
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M){
            imageUri = Uri.fromFile(file);
        }
        else {
            imageUri= FileProvider.getUriForFile(this, this.getPackageName() + ".provider", file);
        }
        final List<Intent> cameraIntents = new ArrayList<Intent>();
        final Intent captureIntent = new Intent("android.media.action.IMAGE_CAPTURE");
        captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        startActivityForResult(captureIntent, FILECHOOSER_RESULTCODE);
}
 

 





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM