android使用WebView来打开文件选择器

时间:2022-03-01 14:50:50

最近了解了一下android的webview可以默认的调用系统的文件选择器。首先,网页的html写法要有<input type="file" ...>,这个在ios上也是可以默认调用系统的文件选择器,只不过可以选择部分文件,毕竟ios对文件的选择做了限制;


今天主要来介绍一下,在android上要如何实现webview调用系统文件选择器,在网上一搜,是可以搜到许多,基本全都是要实现WebChromeClientopenFileChooser(…),我就按网上的教程试了下,突然发现在有些手机上可行,有的则不可行,这就很奇怪了,为什么有的手机不行呢?让我百思不得其解,去网上搜索了好多资料也没有解决,后来翻看了一下源码后恍然大悟,原来5.0的WebChromeClient不是用的openFileChooser(…),而是用的onShowFileChooser(…),所以以后要特别注意下Google是否对Android的源码有改动


接下来就是如何实现的代码了:

public class BaseWebChromeClient extends WebChromeClient {

public static final int FILECHOOSER_RESULTCODE = 10000;

// For Android < 3.0
public void openFileChooser(ValueCallback<Uri> uploadMsg) {

}

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

}

//For Android 4.1
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {

}
//For Android 5.0+
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> valueCallback, FileChooserParams fileChooserParams) {
return true;
}

public void onActivityResult(int resultCode, Intent data) {

}
}
class WebChromeClientAboveFive extends BaseWebChromeClient {

private ValueCallback<Uri[]> mUploadCallbackAboveFive;
private Activity mActivity;

public WebChromeClientAboveFive(Activity activity) {
this.mActivity = activity;
}

/**
* 兼容5.0及以上
*
* @param webView
* @param valueCallback
* @param fileChooserParams
* @return
*/

@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> valueCallback, android.webkit.WebChromeClient.FileChooserParams fileChooserParams) {
mUploadCallbackAboveFive = valueCallback;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
mActivity.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
return true;
}

@Override
public void onActivityResultInternal(int resultCode, Intent data) {
if (null == mUploadCallbackAboveFive) {
return;
}
Uri[] results = null;
if (resultCode == Activity.RESULT_OK) {
if (data != null) {
String dataString = data.getDataString();
ClipData clipData = data.getClipData();
if (clipData != null) {
int itemCount = clipData.getItemCount();
results = new Uri[itemCount];
for (int i = 0; i < itemCount; i++) {
ClipData.Item item = clipData.getItemAt(i);
results[i] = item.getUri();
}
}
if (dataString != null) {
results = new Uri[]{Uri.parse(dataString)};
}
}
}
mUploadCallbackAboveFive.onReceiveValue(results);
mUploadCallbackAboveFive = null;
return;
}
}
class DefaultWebChromeClient extends BaseWebChromeClient {

private ValueCallback<Uri> mUploadMessage;
private Activity mActivity;

public DefaultWebChromeClient(Activity activity) {
this.mActivity = activity;
}

// For Android < 3.0
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
openFileChooser(mUploadMessage, "", "");
}

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

//For Android 4.1
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
mActivity.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
}

@Override
public void onActivityResult(int resultCode, Intent data) {
if (null == mUploadMessage) {
return;
}
Uri result = data == null || resultCode != Activity.RESULT_OK ? null
: data.getData();
if (mUploadMessage != null) {
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
}
}

分别写了2个类来处理不同版本的,在Activity的onActivityResult()回调中,可以调用相应webChromeClient的onActivityResult()的方法