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

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

前言

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

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

正题

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


Webview中选择本地图片上传(一)_第1张图片
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 回调

   private ValueCallback mUploadMessage;
   private ValueCallback uploadMessageAboveL;
..........................................................................................................................
webView.setWebChromeClient(new WebChromeClient(){
           //Android 3.0 以下
           public void openFileChooser(ValueCallback 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 valueCallback, String acceptType, String capture) {
               mUploadMessage = valueCallback;
               selectImage();
           }
           // Android 5.0以上 
           @Override
           public boolean onShowFileChooser(WebView webView, ValueCallback 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)选择图片的操作就基本完成了
(嘘,上班期间躲着写的,可能思路有点乱,没看明白的可以留言,我看到了就会回)

你可能感兴趣的:(Webview中选择本地图片上传(一))