解决Android中webview无法弹出文件选择框的问题

      最近在维护一个项目,发现安卓里面的webview点击网页的<input type="file">类型的控件时,无论你多使劲点都发现无法弹出安卓原生文件选择界面,简直要崩溃了尴尬(主要是ios那边可以...)

      刚开始以为是权限 问题,后来发现该有的权限都给了,而且也给webview支持了javaScript的设置,最后在想应该是webview哪里被限制了,最后通过一番资料查询,发现要重写WebChromeClient类里面的方法--||(为什么要这么麻烦难过

   先说一下执行的步骤:

       1.通过webview.setWebChromeClient(),传入一个WebChromeClient的实现类,在WebChromeClient实现类里面我们要重写里面的openFileChooser方法,这个方法会在文件准备上传时进行回调。

       2.在openFileChooser这个方法里面我们设置Intent打开支持第三方文件的应用

       3.然后在ActivityResult将第三方应用提供的内容通过ValueCallback的存储形式回传给webview。

   一言不合直接贴代码..

  public void openFileChooser(ValueCallback<Uri> uploadMsg) {
            Log.d(TAG, "openFileChoose(ValueCallback<Uri> uploadMsg)");
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            MainActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
      }
      public void openFileChooser( ValueCallback uploadMsg, String acceptType ) {
            Log.d(TAG, "openFileChoose( ValueCallback uploadMsg, String acceptType )");
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            MainActivity.this.startActivityForResult(
                    Intent.createChooser(i, "File Browser"),
                    FILECHOOSER_RESULTCODE);
      }
      public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
            Log.d(TAG, "openFileChoose(ValueCallback<Uri> uploadMsg, String acceptType, String capture)");
            mUploadMessage = uploadMsg;
            Intent i = new Intent(Intent.ACTION_GET_CONTENT);
            i.addCategory(Intent.CATEGORY_OPENABLE);
            i.setType("*/*");
            MainActivity.this.startActivityForResult( Intent.createChooser( i, "File Browser" ), MainActivity.FILECHOOSER_RESULTCODE );
        }
因为openFileChooser有多个重载方法,所以我们都帮它复写..

接下来是ActivityForResult的方法实现

if(requestCode==FILECHOOSER_RESULTCODE)
	     {
	            if (null == mUploadMessage && null == mUploadCallbackAboveL) return;
	             Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
				 if (mUploadMessage != null) {
	                mUploadMessage.onReceiveValue(result);
	                mUploadMessage = null;
	           }
	      }
这样大致就可以实现webview文件上传功能了, 但是问题来了!! 微笑 微笑

你会发现安卓5.0以上的机器还是没有反应,后来发现它回调的不是openFileChooser而是onShowFileChooser!!挖槽,挖槽,挖槽。

这简直是一个大坑啊!!!~~~~再见直接看代码

// For Android 5.0+
public boolean onShowFileChooser (WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
         mUploadCallbackAboveL = filePathCallback;
         Intent i = new Intent(Intent.ACTION_GET_CONTENT);
         i.addCategory(Intent.CATEGORY_OPENABLE);
         i.setType("*/*");
         MainActivity.this.startActivityForResult(
                    Intent.createChooser(i, "File Browser"),
                    FILECHOOSER_RESULTCODE);
         return true;
        }
});
ActivityForResult的方法也需要改下,应该它现在回调的是ValueCallback(Uri[])类型而不是ValueCallback(Uri)类型了、

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode==FILECHOOSER_RESULTCODE)
    {
        if (null == mUploadMessage && null == mUploadCallbackAboveL) return;
        Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
        if (mUploadCallbackAboveL != null) {
            onActivityResultAboveL(requestCode, resultCode, data);
        }
        else  if (mUploadMessage != null) {
            mUploadMessage.onReceiveValue(result);
            mUploadMessage = null;
        }
    }
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void onActivityResultAboveL(int requestCode, int resultCode, Intent data) {
    if (requestCode != FILECHOOSER_RESULTCODE
            || mUploadCallbackAboveL == null) {
        return;
    }
    Uri[] results = null;
    if (resultCode == Activity.RESULT_OK) {
        if (data == null) {
        } else {
            String dataString = data.getDataString();
            ClipData clipData = data.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)};
        }
    }
    mUploadCallbackAboveL.onReceiveValue(results);
    mUploadCallbackAboveL = null;
    return;
}

这样就可以适配android5.0+的设备了,终于把坑填了......记录下来,防止继续掉坑~~~






猜你喜欢

转载自blog.csdn.net/zz6880817/article/details/53195937