Webview中选择本地图片上传(一)

作者: monkey_who | 来源:发表于2017-07-20 16:25 被阅读201次

    原创文章,转载请注明本文出处http://www.jianshu.com/p/841bfa47b45c
    这篇文章的已知bug,我已经改好了,在我另一篇博文里,地址:http://www.jianshu.com/p/62f3750f72a8

    前言

    一周前做的项目中,要嵌入一个H5的页面,这个H5功能很简单,主要就是给用户提供预约申请,其中需要上传本人身份证。

    在这里推荐一下github上面开源的小型AgentWeb
    还有就是腾讯的TBS腾讯浏览服务
    这两个我都在项目中尝试过,效果都还不错,关于这两个库的具体使用方法,我上面给出的github地址或官方技术接入指南讲的都比较详细,就不缀述了,您要是有疑问可以在评论区留言,咱们可以互相探讨。

    正题

    这是H5页面中需要上传图片的截图


    H5页面中需要上传图片的截图.png

    通过webview.loadUrl(“你要加载的地址”)加载网页时,在手持设备上点击图中上传图片时,用以上两个库不做任何处理的情况下,有以下问题:

      1. AgentWeb会出现弹出图片选择器,本以为接下来点击相册会进入相册,但是实际情况是(不同手机会有不同表现)点击相册之后,闪退。
      1. 集成TBS腾讯浏览服务,不给webView设置一个webview.webviewClient(),会从手机上已安装的一个浏览器正常打开相册,但是这样就像是从你的应用进入到了其他应用,所以一般还是要webView.setWebViewClient(),写上这个方法之后,点击上传图片会没有任何响应。

    解决

    这个时候我们需要H5跟Android互调(js跟java互调)
    思路:在H5页面上点击这个上传图片时,调用的是Android原生方法来打开相册或者摄像头,下面以打开相册为例。
    代码片段:

    //  js 调android 方法
            webView.addJavascriptInterface(new DemoJavaScriptInterface(), "demo");
    

    这里的DemoJavaScriptInterface是你要定义给JS调用的方法的所属类名,
    下图中的demo.chickOnAndroid就是js中要拼接而成的方法


    js中调用安卓方法.png
      /**
         * 定义的给js调的方法
         */
        final class DemoJavaScriptInterface{
            DemoJavaScriptInterface(){
            }
    
            @JavascriptInterface
            public void clickOnAndroid(String s){
               //这里执行你用Android原生方法打开相册或摄像头的操作
               //用intent打开即可
           startActivityForResult(把intent传进来);
      }```
    **clickOnAndroid(String s)中的String类型的参数s,
    就是js中window.demo.clickOnAndroid(getJson())方法中,getJson()返回的值**
    
    要打开手机中的文件还需要
    

    //用来接收下面ValueCallback<Uri> 回调

       private ValueCallback<Uri> mUploadMessage;
       private ValueCallback<Uri[]> uploadMessageAboveL;
    ..........................................................................................................................
    webView.setWebChromeClient(new WebChromeClient(){
               //Android 3.0 以下
               public void openFileChooser(ValueCallback<Uri> valueCallback) {
                   mUploadMessage = valueCallback;
                   selectImage();//就是上面
               }
               // Android 3~4.1
               public void openFileChooser(ValueCallback valueCallback, String acceptType) {
                   mUploadMessage = valueCallback;
                   selectImage();
               }
               // Android  4.1以上
               public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {
                   mUploadMessage = valueCallback;
                   selectImage();
               }
               // Android 5.0以上 
               @Override
               public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
                       WebChromeClient.FileChooserParams fileChooserParams ) {
                   uploadMessageAboveL = filePathCallback;
                   selectImage();
                   return true;
               }
    });
    

    openFileChooser是WebChromeClient中的隐藏方法需要你手动去写
    5.0之后就变成了onShowFileChooser
    selectImage()就是你选择图片的一些操作

    private void selectImage() {
            FileUtils.delFile(compressPath);
            Intent intent;
            if (Build.VERSION.SDK_INT < 19) {
                intent = new Intent(Intent.ACTION_GET_CONTENT);
                intent.setType("image/*");
            } else {
                intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
             Intent wrapperIntent = Intent.createChooser(intent, null);
            //REQ_CHOOSE是定义的一个常量
            startActivityForResult(wrapperIntent, REQ_CHOOSE);
            }
    

    在Activity中还要重写onActivityResult()来处理你选择图片之后的操作

    @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
            super.onActivityResult(requestCode, resultCode, intent);
            if(null == intent){
                //为了避免  弹出  相册选择器 之后 点击取消  闪退
                mUploadMessage.onReceiveValue(null);
                return;
            }
            if (null== mUploadMessage){
                mUploadMessage.onReceiveValue(null);
                return;
            }
            Uri uri = null;
            if (requestCode ==REQ_CHOOSE){
                uri = afterChosePic(intent);
         //afterChosePic()这是选择照片之后要处理的
            }
            mUploadMessage.onReceiveValue(uri);
            mUploadMessage = null;
        }```
    
    afterChosePic()方法代码
    

    private Uri afterChosePic(Intent data) {

        // 获取图片的路径:
        String[] proj = { MediaStore.Images.Media.DATA };
        // 好像是android多媒体数据库的封装接口,具体的看Android文档
        Cursor cursor = managedQuery(data.getData(), proj, null, null, null);
        if(cursor == null ){
            Toast.makeText(this, "上传的图片仅支持png或jpg格式",Toast.LENGTH_SHORT).show();
            return null;
        }
        // 按我个人理解 这个是获得用户选择的图片的索引值
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        // 将光标移至开头 ,这个很重要,不小心很容易引起越界
        cursor.moveToFirst();
        // 最后根据索引值获取图片路径
        String path = cursor.getString(column_index);
        if(path != null && (path.endsWith(".png")||path.endsWith(".PNG")||path.endsWith(".jpg")||path.endsWith(".JPG"))){
            File newFile = FileUtils.compressFile(path, compressPath);
            return Uri.fromFile(newFile);
        }else{
            Toast.makeText(this, "上传的图片仅支持png或jpg格式",Toast.LENGTH_SHORT).show();
        }
        return null;
    }
    
    #####到此,webview加载h5页面(也就是js)选择图片的操作就基本完成了
    (嘘,上班期间躲着写的,可能思路有点乱,没看明白的可以留言,我看到了就会回)

    相关文章

      网友评论

      • da5f9afd4272:clickOnAndroid(String s) s的参数怎么写啊,还有我是用第三方打开相册的,这个问题又怎么解决,我集成的是腾讯X5
        monkey_who:@facebig 现在公司不忙,可以看看,我也就是个普通人,尽力而为,不保证看得懂。
        da5f9afd4272:@monkey_who 可以不用js交互可以不,我看网上的方法都没有用到交互,我选中手机相册,返回有值,就是webview上不显示刚才选中的图片,可以帮我看看吗
        monkey_who:这里的参数 是js中的返回值,我这边js返回是个json字符串,所以我这样写的。腾讯X5是个功能很强大的浏览器服务,我理解是一个完整的浏览器(包含浏览器内核的),webview这个控件只是一个展示网页的,更没有浏览器内核,不具备浏览器功能。其实我这里这样写还是有坑,国产手机型号太多了,总有没测到的手机。X5我也用过,用的人很多,又是大厂出品,比自己写,省心很多。

      本文标题:Webview中选择本地图片上传(一)

      本文链接:https://www.haomeiwen.com/subject/axedkxtx.html