欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android-WebView支持input file启用相机/选取照片

程序员文章站 2022-05-23 11:01:47
webview要调起input file拍照或者选取文件功能,可以在webview.setWebChromeClient方法中重写指定的方法,来拦截webview的input事件,并做我们相应的操作。 Android代码 这里的java代码是来拦截input事件的,里面做了很多api版本的判断,不同 ......

webview要调起input-file拍照或者选取文件功能,可以在webview.setwebchromeclient方法中重写指定的方法,来拦截webview的input事件,并做我们相应的操作。

android代码

webview.setwebchromeclient(new webchromeclient() {
            @override
            public void onprogresschanged(webview view, int newprogress) {
                if (newprogress == 100) {
                    progressbar.setvisibility(view.gone);//加载完网页进度条消失
                } else {
                    progressbar.setprogress(newprogress);//设置进度值
                    progressbar.setvisibility(view.visible);//开始加载网页时显示进度条
                }
            }
 
            /**
             * 8(android 2.2) <= api <= 10(android 2.3)回调此方法
             */
            private void openfilechooser(android.webkit.valuecallback<uri> uploadmsg) {
                log.e("wangj", "运行方法 openfilechooser-1");
                // (2)该方法回调时说明版本api < 21,此时将结果赋值给 muploadcallbackbelow,使之 != null
                muploadcallbackbelow = uploadmsg;
                takephoto();
            }
 
            /**
             * 11(android 3.0) <= api <= 15(android 4.0.3)回调此方法
             */
            public void openfilechooser(android.webkit.valuecallback<uri> uploadmsg, string accepttype) {
                log.e("wangj", "运行方法 openfilechooser-2 (accepttype: " + accepttype + ")");
                // 这里我们就不区分input的参数了,直接用拍照
                openfilechooser(uploadmsg);
            }
 
            /**
             * 16(android 4.1.2) <= api <= 20(android 4.4w.2)回调此方法
             */
            public void openfilechooser(android.webkit.valuecallback<uri> uploadmsg, string accepttype, string capture) {
                log.e("wangj", "运行方法 openfilechooser-3 (accepttype: " + accepttype + "; capture: " + capture + ")");
                // 这里我们就不区分input的参数了,直接用拍照
                openfilechooser(uploadmsg);
            }
 
            /**
             * api >= 21(android 5.0.1)回调此方法
             */
            @override
            public boolean onshowfilechooser(webview webview, valuecallback<uri[]> valuecallback, filechooserparams filechooserparams) {
                log.e("wangj", "运行方法 onshowfilechooser");
                // (1)该方法回调时说明版本api >= 21,此时将结果赋值给 muploadcallbackabovel,使之 != null
                muploadcallbackabovel = valuecallback;
                takephoto();
                return true;
            }
        });

这里的java代码是来拦截input事件的,里面做了很多api版本的判断,不同版本的api调用不同的方法,下面是一些其他方法:

调起相机/选择文件的方法:takephoto();

 /**
     * 调用相机
     */
    private void takephoto() {
        // 指定拍照存储位置的方式调起相机
        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);
 
        // 选择图片(不包括相机拍照),则不用成功后发刷新图库的广播
//        intent i = new intent(intent.action_get_content);
//        i.addcategory(intent.category_openable);
//        i.settype("image/*");
//        startactivityforresult(intent.createchooser(i, "image chooser"), request_code);
 
        intent captureintent = new intent(android.provider.mediastore.action_image_capture);
        captureintent.putextra(mediastore.extra_output, imageuri);
 
        intent photo = new intent(intent.action_pick,
                android.provider.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);
    }

onactivityresult回调:

@override
    protected void onactivityresult(int requestcode, int resultcode, intent data) {
        super.onactivityresult(requestcode, resultcode, data);
        if (requestcode == request_code) {
            // 经过上边(1)、(2)两个赋值操作,此处即可根据其值是否为空来决定采用哪种处理方法
            if (muploadcallbackbelow != null) {
                choosebelow(resultcode, data);
            } else if (muploadcallbackabovel != null) {
                chooseabove(resultcode, data);
            } else {
                toast.maketext(this, "发生错误", toast.length_short).show();
            }
        }
    }

其他一些方法:

/**
     * android api < 21(android 5.0)版本的回调处理
     * @param resultcode 选取文件或拍照的返回码
     * @param data 选取文件或拍照的返回结果
     */
    private void choosebelow(int resultcode, intent data) {
        log.e("wangj", "返回调用方法--choosebelow");
 
        if (result_ok == resultcode) {
            updatephotos();
 
            if (data != null) {
                // 这里是针对文件路径处理
                uri uri = data.getdata();
                if (uri != null) {
                    log.e("wangj", "系统返回uri:" + uri.tostring());
                    muploadcallbackbelow.onreceivevalue(uri);
                } else {
                    muploadcallbackbelow.onreceivevalue(null);
                }
            } else {
                // 以指定图像存储路径的方式调起相机,成功后返回data为空
                log.e("wangj", "自定义结果:" + 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) {
        log.e("wangj", "返回调用方法--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) {
                        log.e("wangj", "系统返回uri:" + uri.tostring());
                    }
                    muploadcallbackabovel.onreceivevalue(results);
                } else {
                    muploadcallbackabovel.onreceivevalue(null);
                }
            } else {
                log.e("wangj", "自定义结果:" + 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);
    }

相关的全局变量:

private android.webkit.valuecallback<uri[]> muploadcallbackabovel;
private android.webkit.valuecallback<uri> muploadcallbackbelow;
private uri imageuri;
private int request_code = 1234;

原文: