如何让webview支持文件上传

android webview默认是不支持文件上传功能的,需要借助WebChromeClient来实现.
继承WebChromeClient后,重写openFileChooser和onShowFileChooser这2个方法.

Android3.0以下的SDK,openFileChooser仅有一个参数:
openFileChooser(ValueCallback< Uri > uploadFile)。

Android3.0以上的SDK,openFileChooser有两个参数:
openFileChooser(ValueCallback< Uri > uploadFile, String acceptType)。

Android4.1以上的SDK,openFileChooser增加到三个参数:
openFileChooser(ValueCallback< Uri > uploadFile, String acceptType, String capture)

Android5.0以上的SDK,openFileChooser被onShowFileChooser给替代了
onShowFileChooser(WebView webview,ValueCallback< Uri > filePathCallback,FileChooserParams fileChooserParams)

我这里整理了一个工具类,直接获取一个自带文件上传功能的WebChromeClient,代码如下:

/**
 * WebChromeClient工具类
 * Created by mChenys on 2018/4/3.
 */
public class WebChromeClientUtils {
    //处理文件上传的请求吗
    public static final int FILECHOOSER_RESULTCODE = 8083;
    private static ValueCallback<Uri> mUploadMessage;
    private static ValueCallback<Uri[]> mUploadMessageAboveL;

    //支持文件上传的WebChromeClient
    public static WebChromeClient getFileChromeClient(final Activity activity) {
        return new WebChromeClient() {
            // For Android 3.0+
            public void openFileChooser(ValueCallback<Uri> uploadMsg) {
                openFileChooser(uploadMsg, null, null);
            }

            // For Android 3.0+
            public void openFileChooser(ValueCallback uploadMsg, String acceptType) {
                openFileChooser(uploadMsg, acceptType, null);
            }

            // For Android 4.1
            public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, 
                                        String capture) {
                if (mUploadMessage != null) {
                    mUploadMessage.onReceiveValue(null);
                }
                mUploadMessage = uploadMsg;
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                String type = TextUtils.isEmpty(acceptType) ? "*/*" : acceptType;
                i.setType(type);
                activity.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
            }

            //Android 5.0+
            @Override
            @SuppressLint("NewApi")
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
                                             WebChromeClient.FileChooserParams fileChooserParams) {
                if (mUploadMessageAboveL != null) {
                    mUploadMessageAboveL.onReceiveValue(null);
                }
                mUploadMessageAboveL = filePathCallback;
                Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                i.addCategory(Intent.CATEGORY_OPENABLE);
                if (fileChooserParams != null && fileChooserParams.getAcceptTypes() != null
                        && fileChooserParams.getAcceptTypes().length > 0) {
                    i.setType(fileChooserParams.getAcceptTypes()[0]);
                } else {
                    i.setType("*/*");
                }
                activity.startActivityForResult(Intent.createChooser(i, "File Chooser"), 
                        FILECHOOSER_RESULTCODE);
                return true;
            }
        };
    }

    //上面的方法调用后,记得回调该方法
    public static void onActivityResult(Activity activity, int requestCode,
                                        int resultCode, Intent data) {
        if (requestCode == FILECHOOSER_RESULTCODE) {
            if (mUploadMessage != null) {//5.0以下
                Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
                if (null != result) {
                    mUploadMessage.onReceiveValue(result);
                } else {
                    mUploadMessage.onReceiveValue(Uri.EMPTY);
                }
                mUploadMessage = null;

            } else if (mUploadMessageAboveL != null) {//5.0+
                Uri result = (data == null || resultCode != RESULT_OK) ? null : data.getData();
                if (result != null) {
//                    mUploadMessageAboveL.onReceiveValue(new Uri[]{result});
                    onActivityResultAboveL(data);
                } else {
                    mUploadMessageAboveL.onReceiveValue(new Uri[]{});
                }
                mUploadMessageAboveL = null;
            }
        }
    }

    //Android 5.0+
    private static void onActivityResultAboveL(Intent data) {
        Uri[] results = null;
        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)};
        }
        mUploadMessageAboveL.onReceiveValue(results);
        mUploadMessageAboveL = null;
    }
}

使用方式

	...
	mWebView.setWebChromeClient(WebChromeClientUtils.getFileChromeClient(this));
	...
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	    super.onActivityResult(requestCode, resultCode, data);
	    if (requestCode == WebChromeClientUtils.FILECHOOSER_RESULTCODE) {
	        WebChromeClientUtils.onActivityResult(this, requestCode, resultCode, data);
	    }
	}
	...

附加

图片上传处理,直接以5.0+为例

	public ValueCallback<Uri[]> uploadMessage;
	public static final int REQUEST_SELECT_FILE = 100;
	
	@Override
	public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
	 								FileChooserParams fileChooserParams) {
	    if (uploadMessage != null) {
	        uploadMessage.onReceiveValue(null);
	        uploadMessage = null;
	    }
	    uploadMessage = filePathCallback;
	    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
	    intent.addCategory(Intent.CATEGORY_OPENABLE);
	    intent.setType("image/*");
	    try {
	        startActivityForResult(Intent.createChooser(intent, "Image Chooser"), REQUEST_SELECT_FILE);
	    } catch (ActivityNotFoundException e) {
	        uploadMessage = null;
	        return false;
	    }
	    return true;
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	     super.onActivityResult(requestCode, resultCode, data);
	     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
	         if (requestCode == REQUEST_SELECT_FILE) {
	             if (uploadMessage == null)
	                 return;
	             uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, data));
	             uploadMessage = null;
	         }
	     }
	 }

你可能感兴趣的:(Android)