WebView加载H5,点击H5内容,如何能够同时支持拍照或录制视频,然后把结果文件返回给H5?

现在我这样做是可以拍照并且返回给H5了,但是录制视频应该怎么加上去呢?因为加载的H5页面有些是需要拍照,有些是需要录制视频的,下面是H5页面和WebView加载的三个类:
1.自定义WebChromeClient:

public class ZpWebChromeClient extends WebChromeClient {

    private OpenFileChooserCallBack mOpenFileChooserCallBack;

    // For Android < 3.0
    public void openFileChooser(ValueCallback<Uri> uploadMsg) {
        openFileChooser(uploadMsg, "");
    }

    //For Android 3.0 - 4.0
    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
        if (mOpenFileChooserCallBack != null) {
            mOpenFileChooserCallBack.openFileChooserCallBack(uploadMsg, acceptType);
        }
    }

    // For Android 4.0 - 5.0
    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
        openFileChooser(uploadMsg, acceptType);
    }

    // For Android > 5.0
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
        if (mOpenFileChooserCallBack != null) {
            mOpenFileChooserCallBack.showFileChooserCallBack(filePathCallback, fileChooserParams);
        }
        return true;
    }

    public void setOpenFileChooserCallBack(OpenFileChooserCallBack callBack) {
        mOpenFileChooserCallBack = callBack;
    }

    @Override
    public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
        callback.invoke(origin, true, false);   //开启H5定位
        super.onGeolocationPermissionsShowPrompt(origin, callback);
    }

    public interface OpenFileChooserCallBack {

        void openFileChooserCallBack(ValueCallback<Uri> uploadMsg, String acceptType);

        void showFileChooserCallBack(ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams);
    }

}

2.自定义WebView:

public class ZpWebView extends WebView {

    private ZpWebChromeClient webChromeClient;

    public ZpWebView(Context context) {
        super(context);
        initWebView();
    }

    public ZpWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initWebView();
    }

    public ZpWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initWebView();
    }

    private void initWebView() {
        webChromeClient = new ZpWebChromeClient();
        setWebChromeClient(webChromeClient);

        WebSettings webviewSettings = getSettings();
        // 不支持缩放
        webviewSettings.setSupportZoom(false);
        // 自适应屏幕大小
        webviewSettings.setUseWideViewPort(true);
        webviewSettings.setLoadWithOverviewMode(true);
        String cacheDirPath = getContext().getFilesDir().getAbsolutePath() + "cache/";
        webviewSettings.setAppCachePath(cacheDirPath);
        webviewSettings.setAppCacheEnabled(true);

        webviewSettings.setDomStorageEnabled(true);
        webviewSettings.setAllowFileAccess(true);
        webviewSettings.setAppCacheMaxSize(1024 * 1024 * 8);
        webviewSettings.setJavaScriptEnabled(true);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            webviewSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }
    }

    public void setOpenFileChooserCallBack(ZpWebChromeClient.OpenFileChooserCallBack callBack) {
        webChromeClient.setOpenFileChooserCallBack(callBack);
    }

}

3.WebView加载数据页面:

public class WebViewActivity extends BaseActivity {

    @BindView(R.id.wv_zp)
    ZpWebView mWebView;
    //    @BindView(R.id.pb_web_view)
//    ProgressBar progressBar;
    @BindView(R.id.fl_root_web_view)
    FrameLayout mRootView;

    public static final int REQUEST_SELECT_FILE_CODE = 100;
    private static final int REQUEST_FILE_CHOOSER_CODE = 101;
    private static final int REQUEST_FILE_CAMERA_CODE = 102;
    // 默认图片压缩大小(单位:K)
    public static final int IMAGE_COMPRESS_SIZE_DEFAULT = 400;
    // 压缩图片最小高度
    public static final int COMPRESS_MIN_HEIGHT = 900;
    // 压缩图片最小宽度
    public static final int COMPRESS_MIN_WIDTH = 675;

    private ValueCallback<Uri> mUploadMsg;
    private ValueCallback<Uri[]> mUploadMsgs;
    // 相机拍照返回的图片文件
    private File mFileFromCamera;

    public static void open(Context context, String url, String title) {
        Intent intent = new Intent(context, WebViewActivity.class);
        intent.putExtra("url", url);
        intent.putExtra("title", title);
        context.startActivity(intent);
    }

    @Override
    protected int getLayout() {
        return R.layout.activity_web_view;
    }

    @Override
    protected void initView(Bundle savedInstanceState) {
        String title = getIntent().getStringExtra("title");
        mTvTitle.setText(title);
    }

    @Override
    protected void initData() {
        String url = getIntent().getStringExtra("url");
//        String url = "https://cardloan.xiaoying.com/cashloan/index?source=100029070#!/register/1";
//        ZpWebView webView = findViewById(R.id.wv_zp);
//        mWebView.loadUrl("https://zujin.58fangdai.com/common/h5/mobile/idcard?releaseView=1&token=906764d51644ec9f2907260e4694a4a7");//无法拍照
//        webView.loadUrl("https://cardloan.xiaoying.com/cashloan/index?source=100029070#!/register/1");//无法下载APP
//        mWebView.loadUrl("https://www.qianban.com/loan/stream/06QLN1?af=LW25XJJRQBQLC");//无法打电话
        mWebView.loadUrl(url);

        mWebView.setOpenFileChooserCallBack(new ZpWebChromeClient.OpenFileChooserCallBack() {
            @SuppressLint("CheckResult")
            @Override
            public void openFileChooserCallBack(ValueCallback<Uri> uploadMsg, String acceptType) {
                mUploadMsg = uploadMsg;
                new RxPermissions(WebViewActivity.this).
                        request(Manifest.permission.CAMERA)
                        .compose(RxUtil.lifeCycle(WebViewActivity.this))
                        .subscribe(aBooleans -> {
                            if (aBooleans) {
//                                Log.d(TAG, "1602  initData: 已获取到定位权限");
                                takeCameraPhoto();
                            } else {
                                ToastUtils.showShort(R.string.please_open_permission);
                            }
                        });
//                new RxPermissions(WebViewActivity.this).
//                        request(Manifest.permission.CAMERA)
//                        .compose(RxUtil.lifeCycle(WebViewActivity.this))
//                        .subscribe(aBooleans -> {
//                            if (aBooleans) {
////                                Log.d(TAG, "1602  initData: 已获取到定位权限");
//                                new RxPermissions(WebViewActivity.this).
//                                        request(Manifest.permission.READ_EXTERNAL_STORAGE) //动态写数据权限
//                                        .compose(RxUtil.lifeCycle(WebViewActivity.this))
//                                        .subscribe(ab -> {
//                                            if (ab) {
//                                                new RxPermissions(WebViewActivity.this).
//                                                        request(Manifest.permission.RECORD_AUDIO) //动态写数据权限
//                                                        .compose(RxUtil.lifeCycle(WebViewActivity.this))
//                                                        .subscribe(cd -> {
//                                                            if (cd) {
//                                                                takeCameraPhoto();
//                                                            } else {
//                                                                ToastUtils.showShort(R.string.please_open_permission);
//                                                            }
//                                                        });
//                                            } else {
//                                                ToastUtils.showShort(R.string.please_open_permission);
//                                            }
//                                        });
//                            } else {
//                                ToastUtils.showShort(R.string.please_open_permission);
//                            }
//                        });
            }

            @SuppressLint("CheckResult")
            @Override
            public void showFileChooserCallBack(ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
                if (mUploadMsgs != null) {
                    mUploadMsgs.onReceiveValue(null);
                }
                mUploadMsgs = filePathCallback;
                new RxPermissions(WebViewActivity.this).
                        request(Manifest.permission.CAMERA)
                        .compose(RxUtil.lifeCycle(WebViewActivity.this))
                        .subscribe(aBooleans -> {
                            if (aBooleans) {
//                                Log.d(TAG, "1602  initData: 已获取到定位权限");
                                takeCameraPhoto();
                            } else {
                                ToastUtils.showShort(R.string.please_open_permission);
                            }
                        });
//                new RxPermissions(WebViewActivity.this).
//                        request(Manifest.permission.CAMERA)
//                        .compose(RxUtil.lifeCycle(WebViewActivity.this))
//                        .subscribe(aBooleans -> {
//                            if (aBooleans) {
////                                Log.d(TAG, "1602  initData: 已获取到定位权限");
//                                new RxPermissions(WebViewActivity.this).
//                                        request(Manifest.permission.READ_EXTERNAL_STORAGE) //动态写数据权限
//                                        .compose(RxUtil.lifeCycle(WebViewActivity.this))
//                                        .subscribe(ab -> {
//                                            if (ab) {
//                                                new RxPermissions(WebViewActivity.this).
//                                                        request(Manifest.permission.RECORD_AUDIO) //动态写数据权限
//                                                        .compose(RxUtil.lifeCycle(WebViewActivity.this))
//                                                        .subscribe(cd -> {
//                                                            if (cd) {
//                                                                takeCameraPhoto();
//                                                            } else {
//                                                                ToastUtils.showShort(R.string.please_open_permission);
//                                                            }
//                                                        });
//                                            } else {
//                                                ToastUtils.showShort(R.string.please_open_permission);
//                                            }
//                                        });
//                            } else {
//                                ToastUtils.showShort(R.string.please_open_permission);
//                            }
//                        });
            }
        });
        mWebView.setDownloadListener(new DownloadListener() {
            @Override
            public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
                //todo:解决点击无法下载的问题(跳到手机浏览器下载)
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.addCategory(Intent.CATEGORY_BROWSABLE);
                intent.setData(Uri.parse(url));
                startActivity(intent);
            }
        });

        mWebView.setWebViewClient(new WebViewClient() {

            @RequiresApi(api = Build.VERSION_CODES.M)
            @Override
            public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
                super.onReceivedError(view, request, error);
                int errorCode = error.getErrorCode();
                //todo:公司产品地址无网络只走这里的回调
                if (errorCode == -2) {
//                    progressBar.setVisibility(View.GONE);
                    mWebView.setVisibility(View.GONE);
                    View errorView = View.inflate(WebViewActivity.this, R.layout.error_view, null);
                    mRootView.addView(errorView);
                }
            }

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                //1.解决无法调用拨打电话问题,还要重写下面这个重载函数
                if (url.startsWith("mailto:")) {
                    //Handle mail Urls
                    startActivity(new Intent(Intent.ACTION_SENDTO, Uri.parse(url)));
                } else if (url.startsWith("tel:")) {
                    //Handle telephony Urls
                    startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(url)));
                } else {
                    view.loadUrl(url);
                }
                return true;
            }

            @TargetApi(Build.VERSION_CODES.N)
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                final Uri uri = request.getUrl();
                if (uri.toString().startsWith("mailto:")) {
                    //Handle mail Urls
                    startActivity(new Intent(Intent.ACTION_SENDTO, uri));
                } else if (uri.toString().startsWith("tel:")) {
                    //Handle telephony Urls
                    startActivity(new Intent(Intent.ACTION_DIAL, uri));
                } else if (uri.toString().startsWith("sms:")) {
                    //Handle Web Urls
                    startActivity(new Intent(Intent.ACTION_SENDTO, uri));
                } else {
                    view.loadUrl(uri.toString());
                }
                return true;
            }

        });
    }

    @Override
    protected void initEvent() {
        mIvBack.setOnClickListener(v -> finish());
    }

    public void takeCameraPhoto() {
        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) {
            ToastUtils.showShort("设备无摄像头");
            return;
        }
        String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath();
        mFileFromCamera = new File(filePath, System.currentTimeMillis() + ".jpg");
//        mFileFromCamera = new File(filePath, System.currentTimeMillis() + ".mp4");
//        Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        Uri imgUrl;
        if (getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.M) {
            String authority = "com.jr.xiaojingfinancial.provider";
            imgUrl = FileProvider.getUriForFile(WebViewActivity.this, authority, mFileFromCamera);
        } else {
            imgUrl = Uri.fromFile(mFileFromCamera);
        }
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imgUrl);
        startActivityForResult(intent, REQUEST_FILE_CAMERA_CODE);//这行报错
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case REQUEST_SELECT_FILE_CODE:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    if (mUploadMsgs == null) {
                        return;
                    }
                    mUploadMsgs.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
                    mUploadMsgs = null;
                }
                break;
            case REQUEST_FILE_CHOOSER_CODE:
                if (mUploadMsg == null) {
                    return;
                }
                Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
                mUploadMsg.onReceiveValue(result);
                mUploadMsg = null;
                break;
            case REQUEST_FILE_CAMERA_CODE:
                takePictureFromCamera();
                break;
        }
    }

    /**
     * 处理相机返回的图片
     */
//    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void takePictureFromCamera() {
        if (mFileFromCamera != null && mFileFromCamera.exists()) {
            String filePath = mFileFromCamera.getAbsolutePath();
            // 压缩图片到指定大小
            File imgFile = ZpImageUtils.compressImage(this, filePath, COMPRESS_MIN_WIDTH, COMPRESS_MIN_HEIGHT, IMAGE_COMPRESS_SIZE_DEFAULT);
            Uri localUri = Uri.fromFile(imgFile);
            Intent localIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, localUri);
            this.sendBroadcast(localIntent);
            Uri result = Uri.fromFile(imgFile);
            if (mUploadMsg != null) {
                mUploadMsg.onReceiveValue(Uri.parse(filePath));
                mUploadMsg = null;
            }
            if (mUploadMsgs != null) {
                mUploadMsgs.onReceiveValue(new Uri[]{result});
                mUploadMsgs = null;
            }
        }
    }

    /**
     * 监听物理返回键
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
            mWebView.goBack();// 返回前一个HTML页面
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public void onDestroy() {
        //释放资源,防止内存泄露
        if (mWebView != null) {
            ViewParent parent = mWebView.getParent();
            if (parent != null) {
                ((ViewGroup) parent).removeView(mWebView);
            }
            mWebView.stopLoading(); // 退出时调用此方法,移除绑定的服务,否则某些特定系统会报错
            mWebView.getSettings().setJavaScriptEnabled(false);
            mWebView.clearHistory();
            mWebView.clearView();
            mWebView.removeAllViews();
            mWebView.destroy();
        }
        super.onDestroy();
    }

}
阅读 2.5k
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题