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;
}
}
}