WebView里调用相机/文件选取照片并上传

本文参考:Android——UI篇:WebView里调用相机/文件选取照片并上传 - 简书

第一步:重写WebChromeClient中的openFileChooser/onShowFileChooser方法

第二步:在openFileChooser/onShowFileChooser中处理逻辑

public class WebActivity extends AppCompatActivity {
    private ValueCallback mUploadCallbackAboveL;
    private ValueCallback mUploadCallbackBelow;
    private Uri imageUri;
    private final int REQUEST_CODE_IMG = 10011;
    private final int REQUEST_CODE_VIDEO = 10022;
    private final String TAG = "WebActivity";
    //省略无关代码
    .....

    @SuppressLint("SetJavaScriptEnabled")
    @Override
    protected void initView(Bundle savedInstanceState) {
        WebSettings mSettings = mWebView.getSettings();
        //省略无关代码
        .....
       //重写WebChromeClient 中的openFileChooser/onShowFileChooser方法
        WebChromeClient chromeClient = new WebChromeClient() {
            @Override
            public void onPermissionRequest(PermissionRequest request) {
                request.grant(request.getResources());
                request.getOrigin();
            }

            @Override
            public void onReceivedTitle(WebView view, String title) {
                if (mTvTitle != null && !TextUtils.isEmpty(title)) {
                    mTvTitle.setText(title);
                }
            }

            /**
             * 16(Android 4.1.2) <= API <= 20(Android 4.4W.2)回调此方法
             */
            public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) {
                // 这里我们就不区分input的参数了,直接用拍照
                mUploadCallbackBelow = uploadMsg;
                openCamera("");
            }

            /**
             * API >= 21(Android 5.0.1)回调此方法
             */
            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback valueCallback, FileChooserParams fileChooserParams) {
                // (1)该方法回调时说明版本API >= 21,此时将结果赋值给 mUploadCallbackAboveL,使之 != null
                mUploadCallbackAboveL = valueCallback;
                String[] acceptTypes = fileChooserParams.getAcceptTypes();
                if (acceptTypes.length > 0) {
                    openCamera(acceptTypes[0]);
                    LoggerUtils.e(TAG, "类型:" + acceptTypes[0]);
                }
                return true;
            }
        };
        mWebView.setWebChromeClient(chromeClient);
    }
    //省略无关代码
    .....
   
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE_VIDEO) {
            if (null != mUploadCallbackBelow) {
                Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
                mUploadCallbackBelow.onReceiveValue(result);
                mUploadCallbackBelow = null;
            } else if (null != mUploadCallbackAboveL) {
                Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
                if (result != null) {
                    mUploadCallbackAboveL.onReceiveValue(new Uri[]{result});
                } else {
                    mUploadCallbackAboveL.onReceiveValue(null);
                }
                mUploadCallbackAboveL = null;
            }
        } else if (requestCode == REQUEST_CODE_IMG) {
            // 经过上边(1)、(2)两个赋值操作,此处即可根据其值是否为空来决定采用哪种处理方法
            if (mUploadCallbackBelow != null) {
                chooseBelow(resultCode, data);
            } else if (mUploadCallbackAboveL != null) {
                chooseAbove(resultCode, data);
            } else {
                ToastUtils.showShort("发生错误");
            }
        }
    }

    /**
     * 调用相机/相册选择器弹窗
     */
    private void openCamera(String accept) {
        if (accept.contains("video")) {
            Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
            intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);//设置视频录制的质量,0为低质量,1为高质量。
            //intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 6);//限制时长 单位秒
            //intent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, 1024L * 1024 * 10);//指定视频最大允许的尺寸,单位为byte
            //开启摄像机
            startActivityForResult(intent, REQUEST_CODE_VIDEO);
        } else {
            // 指定拍照存储位置的方式调起相机
            String filePath = Environment.getExternalStorageDirectory() + File.separator
                    + Environment.DIRECTORY_PICTURES + File.separator;
            String fileName = "IMG_" + DateFormat.format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".jpg";
            imageUri = Uri.fromFile(new File(filePath + fileName));

//        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
//        startActivityForResult(intent, REQUEST_CODE_IMG);


            // 选择图片(不包括相机拍照),则不用成功后发刷新图库的广播
//        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
//        i.addCategory(Intent.CATEGORY_OPENABLE);
//        i.setType("image/*");
//        startActivityForResult(Intent.createChooser(i, "Image Chooser"), REQUEST_CODE_IMG);

            Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);

            Intent photo = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

            Intent chooserIntent = Intent.createChooser(photo, "Image Chooser");
            chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});

            startActivityForResult(chooserIntent, REQUEST_CODE_IMG);
        }
    }

    /**
     * Android API < 21(Android 5.0)版本的回调处理
     *
     * @param resultCode 选取文件或拍照的返回码
     * @param data       选取文件或拍照的返回结果
     */
    private void chooseBelow(int resultCode, Intent data) {
        LoggerUtils.d(TAG, "返回调用方法--chooseBelow");
        if (RESULT_OK == resultCode) {
            updatePhotos();
            if (data != null) {
                // 这里是针对文件路径处理
                Uri uri = data.getData();
                if (uri != null) {
                    LoggerUtils.d(TAG, "系统返回URI:" + uri.toString());
                    mUploadCallbackBelow.onReceiveValue(uri);
                } else {
                    mUploadCallbackBelow.onReceiveValue(null);
                }
            } else {
                // 以指定图像存储路径的方式调起相机,成功后返回data为空
                LoggerUtils.d(TAG, "自定义结果:" + imageUri.toString());
                mUploadCallbackBelow.onReceiveValue(imageUri);
            }
        } else {
            mUploadCallbackBelow.onReceiveValue(null);
        }
        mUploadCallbackBelow = null;
    }

    /**
     * Android API >= 21(Android 5.0) 版本的回调处理
     *
     * @param resultCode 选取文件或拍照的返回码
     * @param data       选取文件或拍照的返回结果
     */
    private void chooseAbove(int resultCode, Intent data) {
        LoggerUtils.d(TAG, "返回调用方法--chooseAbove");
        if (RESULT_OK == resultCode) {
            updatePhotos();
            if (data != null) {
                // 这里是针对从文件中选图片的处理
                Uri[] results;
                Uri uriData = data.getData();
                if (uriData != null) {
                    results = new Uri[]{uriData};
                    for (Uri uri : results) {
                        LoggerUtils.d(TAG, "系统返回URI:" + uri.toString());
                    }
                    mUploadCallbackAboveL.onReceiveValue(results);
                } else {
                    mUploadCallbackAboveL.onReceiveValue(null);
                }
            } else {
                LoggerUtils.d(TAG, "自定义结果:" + imageUri.toString());
                mUploadCallbackAboveL.onReceiveValue(new Uri[]{imageUri});
            }
        } else {
            mUploadCallbackAboveL.onReceiveValue(null);
        }
        mUploadCallbackAboveL = null;
    }

    private void updatePhotos() {
        // 该广播即使多发(即选取照片成功时也发送)也没有关系,只是唤醒系统刷新媒体文件
        Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        intent.setData(imageUri);
        sendBroadcast(intent);
    }

}

你可能感兴趣的:(webview,android,java)