天天看點

WebView 選擇相冊圖檔踩坑

最近在為公司的幾個H5項目做app打包,然後就踩到這個坑了。

項目中有 h5調用相冊選擇圖檔,然後上傳這個功能,測試說上傳不了圖檔。然後搜了不少資料,折騰了一下午,終于搞好了,特此記錄下。

原生WebView 的選擇圖檔功能需要我們自己實作,代碼如下:

wv_main.setWebChromeClient(new WebChromeClient() {
            // Andorid 4.1----4.4
            public void openFileChooser(ValueCallback<uri> uploadFile, String acceptType, String capture) {
 
                mFilePathCallback = uploadFile;
                handle(uploadFile);
            }
 
            // for 5.0+
            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback<uri[]> filePathCallback, FileChooserParams fileChooserParams) {
                if (mFilePathCallbackArray != null) {
                    mFilePathCallbackArray.onReceiveValue(null);
                }
                mFilePathCallbackArray = filePathCallback;
                handleup(filePathCallback);
                return true;
            }
 
 
        });
    }
 
    private void handle(ValueCallback<uri> uploadFile) {
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("image/*");
        startActivityForResult(intent, PICK_REQUEST);
    }
 
    private void handleup(ValueCallback<uri[]> uploadFile) {
 
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("image/*");
        startActivityForResult(intent, PICK_REQUEST);
    }
           

然後在Activity的onActivityResult 方法裡處理回調,代碼如下:

@Override
   protected void onActivityResult(int requestCode, int resultCode, Intent data) {
       super.onActivityResult(requestCode, resultCode, data);
 
       if (requestCode == PICK_REQUEST) {
           if (null != data) {
               Uri uri = data.getData();
               handleCallback(uri);
           } else {
               // 取消了照片選取的時候調用
               handleCallback(null);
           }
       } else {
           // 取消了照片選取的時候調用
           handleCallback(null);
       }
 
 
   }
           
/**
     * 處理WebView的回調
     *
     * @param uri
     */
    private void handleCallback(Uri uri) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if (mFilePathCallbackArray != null) {
                if (uri != null) {
                    mFilePathCallbackArray.onReceiveValue(new Uri[]{uri});
                } else {
                    mFilePathCallbackArray.onReceiveValue(null);
                }
                mFilePathCallbackArray = null;
            }
        } else {
            if (mFilePathCallback != null) {
                if (uri != null) {
                    String url = getFilePathFromContentUri(uri, getContentResolver());
                    Uri u = Uri.fromFile(new File(url));
 
                    mFilePathCallback.onReceiveValue(u);
                } else {
                    mFilePathCallback.onReceiveValue(null);
                }
                mFilePathCallback = null;
            }
        }
    }
           

坑1:記得一定要釋放,不然點取消之後,就再調不起來了(一下午主要就填這個坑了)

4.1-4.4
 mFilePathCallback.onReceiveValue(null);
5.0
mFilePathCallbackArray.onReceiveValue(null);
           

坑2:4.4以下,傳回的Uri 是content: 開頭的,h5端識别不了,需要轉成絕對路徑

public static String getFilePathFromContentUri(Uri selectedVideoUri,
                                                   ContentResolver contentResolver) {
        String filePath;
        String[] filePathColumn = {MediaStore.MediaColumns.DATA};
 
        Cursor cursor = contentResolver.query(selectedVideoUri, filePathColumn, null, null, null);
//      也可用下面的方法拿到cursor
//      Cursor cursor = this.context.managedQuery(selectedVideoUri, filePathColumn, null, null, null);
 
        cursor.moveToFirst();
 
        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        filePath = cursor.getString(columnIndex);
        cursor.close();
        return filePath;
    }