Android WebView 拍照和选择图片

转载地址:https://www.jianshu.com/p/13f4b8f70947

Android WebView 嵌套网页中有js调取拍照和选择图片上传的功能,这个需要在我们的代码中去实现方法

首先基础WebView设置

   WebSettings settings = mWebView.getSettings();
        settings.setJavaScriptEnabled(true);    //设置webview支持javascript
//        settings.setJavaScriptCanOpenWindowsAutomatically(true);
        settings.setLoadsImagesAutomatically(true);    //支持自动加载图片
        settings.setUseWideViewPort(true);    //设置webview推荐使用的窗口,使html界面自适应屏幕
        settings.setLoadWithOverviewMode(true);
        settings.setSaveFormData(true);    //设置webview保存表单数据
        settings.setSavePassword(true);    //设置webview保存密码

        int mDensity = DensityUtils.getDensityDpi(context);
        if (mDensity == 120) {
            settings.setDefaultZoom(WebSettings.ZoomDensity.CLOSE);
        } else if (mDensity == 160) {
            settings.setDefaultZoom(WebSettings.ZoomDensity.MEDIUM);
        } else if (mDensity == 240) {
            settings.setDefaultZoom(WebSettings.ZoomDensity.FAR);
        }
//        settings.setDefaultZoom(WebSettings.ZoomDensity.MEDIUM);    //设置中等像素密度,medium=160dpi
        settings.setSupportZoom(true);    //支持缩放
        settings.setSupportMultipleWindows(true);
        settings.setAppCacheEnabled(true); //设置APP可以缓存
        settings.setDatabaseEnabled(true);
        settings.setDomStorageEnabled(true);//返回上个界面不刷新  允许本地缓存
        //        settings.setCacheMode(WebSettings.LOAD_DEFAULT);// 设置缓存LOAD_DEFAULT   LOAD_CACHE_ONLY,LOAD_NO_CACHE
        settings.setAllowFileAccess(true);// 设置可以访问文件
        settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);//不支持放大缩小
        settings.setDisplayZoomControls(false);//不支持放大缩小
        //      NORMAL:正常显示,没有渲染变化。
        //      SINGLE_COLUMN:把所有内容放到WebView组件等宽的一列中。   //这个是强制的,把网页都挤变形了
        //      NARROW_COLUMNS:可能的话,使所有列的宽度不超过屏幕宽度。 //好像是默认的

        mWebView.setLongClickable(true);
        mWebView.setScrollbarFadingEnabled(true);
        mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
        mWebView.setDrawingCacheEnabled(true)

 

js调取拍照和选择图片功能,兼容3.0以上

//5.0以下使用
    private ValueCallback<Uri> uploadMessage;
// 5.0及以上使用
    private ValueCallback<Uri[]> uploadMessageAboveL;

                    //覆盖WebView默认使用第三方或系统默认浏览器打开网页的行为,使网页用WebView打开
                     mWebView.setWebChromeClient(new WebChromeClient() {
                           // For Android < 3.0
                           public void openFileChooser(ValueCallback<Uri> valueCallback) {
                                 uploadMessage = valueCallback;
                                 openImageChooserActivity();
                            }

                            // For Android  >= 3.0
                           public void openFileChooser(ValueCallback valueCallback, String acceptType) {
                                uploadMessage = valueCallback;
                                openImageChooserActivity();
                            }

                            //For Android  >= 4.1
                            public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {
                                uploadMessage = valueCallback;
                                openImageChooserActivity();
                            }

                            // For Android >= 5.0
                            @Override
                            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
                                uploadMessageAboveL = filePathCallback;
                                openImageChooserActivity();
                                return true;
                            }
                      });

 

这里需要弹出一个对话框让用户选择拍照和图库,这里用的是第三方MaterialDialog

这里有个需要注意的地方,就是如果没有调用onReceiveValue(null)的方法,下一次js将无法生效,
我这里让用户不能按返回键和点击屏幕外消失,当点击取消按钮的时候调用onReceiveValue(null)方法

//图片
    private final static int FILE_CHOOSER_RESULT_CODE = 128;
//拍照
    private final static int FILE_CAMERA_RESULT_CODE = 129;
//拍照图片路径
    private String cameraFielPath;

    private void openImageChooserActivity() {
        new MaterialDialog.Builder(this)
                .items(R.array.photo)
                .positiveText("取消")
                .onPositive(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                        if (uploadMessageAboveL != null) {
                            uploadMessageAboveL.onReceiveValue(null);
                            uploadMessageAboveL = null;
                        }
                        if (uploadMessage != null) {
                            uploadMessage.onReceiveValue(null);
                            uploadMessage = null;
                        }
                        dialog.dismiss();
                    }
                })
                .cancelable(false)
                .canceledOnTouchOutside(false)
                .itemsCallback(new MaterialDialog.ListCallback() {
                    @Override
                    public void onSelection(MaterialDialog dialog, View itemView, int position, CharSequence text) {
                        if (position == 0) {
                            takeCamera();
                        } else if (position == 1) {
                            takePhoto();
                        }
                    }
                }).show();
    }
 
//选择图片
 private void takePhoto() {
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("image/*");
        startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILE_CHOOSER_RESULT_CODE);
    }

//拍照
    private void takeCamera() {
         Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

        File pictureFolder = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsoluteFile();
        File appDir = new File(pictureFolder ,getActivity().getString(R.string.app_name_cache_dir));
        if (!appDir.exists()) {
            appDir.mkdirs();
        }

        cameraFielPath = appDir.getAbsolutePath() + System.currentTimeMillis() + ".jpg";
        File outputImage = new File(cameraFielPath);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(outputImage));
        startActivityForResult(intent, FILE_CAMERA_RESULT_CODE);
    }

最后一步在界面onActivityResult中判断进行操作

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (null == uploadMessage && null == uploadMessageAboveL) return;
        if (resultCode != RESULT_OK) {//同上所说需要回调onReceiveValue方法防止下次无法响应js方法
            if (uploadMessageAboveL != null) {
                uploadMessageAboveL.onReceiveValue(null);
                uploadMessageAboveL = null;
            }
            if (uploadMessage != null) {
                uploadMessage.onReceiveValue(null);
                uploadMessage = null;
            }
            return;
        }
        Uri result = null;
        if (requestCode == FILE_CAMERA_RESULT_CODE) {
            if (null != data && null != data.getData()) {
                result = data.getData();
            }
            if (result == null && hasFile(cameraFielPath)) {
                result = Uri.fromFile(new File(cameraFielPath));
            }
            if (uploadMessageAboveL != null) {
                uploadMessageAboveL.onReceiveValue(new Uri[]{result});
                uploadMessageAboveL = null;
            } else if (uploadMessage != null) {
                uploadMessage.onReceiveValue(result);
                uploadMessage = null;
            }
        } else if (requestCode == FILE_CHOOSER_RESULT_CODE) {
            if (data != null) {
                result = data.getData();
            }
            if (uploadMessageAboveL != null) {
                onActivityResultAboveL(data);
            } else if (uploadMessage != null) {
                uploadMessage.onReceiveValue(result);
                uploadMessage = null;
            }
        }
    }

    /**
     * 判断文件是否存在
     */
    public static boolean hasFile(String path) {
        try {
            File f = new File(path);
            if (!f.exists()) {
                return false;
            }
        } catch (Exception e) {
            // TODO: handle exception
            return false;
        }
        return true;
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void onActivityResultAboveL(Intent intent) {
        Uri[] results = null;
        if (intent != null) {
            String dataString = intent.getDataString();
            ClipData clipData = intent.getClipData();
            if (clipData != null) {
                results = new Uri[clipData.getItemCount()];
                for (int i = 0; i < clipData.getItemCount(); i++) {
                    ClipData.Item item = clipData.getItemAt(i);
                    results[i] = item.getUri();
                }
            }
            if (dataString != null)
                results = new Uri[]{Uri.parse(dataString)};
        }
        uploadMessageAboveL.onReceiveValue(results);
        uploadMessageAboveL = null;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值