默认情况下,Android的WebView不支持文件上传,需要手动适配,原理就是获取到选择文件的uri,然后传给页面去上传。
做的时候遇到不少坑,这里记录一下。
效果截图:
在小米上:
在原生上:
public class SelectFileWebClient extends WebChromeClient {
private static final int REQUEST_FILE_PICKER = 1;
private final Activity mActivity;
private ValueCallback<Uri> mFilePathCallback4;
private ValueCallback<Uri[]> mFilePathCallback5;
public SelectFileWebClient(Activity activity) {
this.mActivity = activity;
}
public void openFileChooser(ValueCallback<Uri> filePathCallback)
{
mFilePathCallback4 = filePathCallback;
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
mActivity.startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_FILE_PICKER);
}
public void openFileChooser(ValueCallback filePathCallback, String acceptType)
{
mFilePathCallback4 = filePathCallback;
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
mActivity.startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_FILE_PICKER);
}
public void openFileChooser(ValueCallback<Uri> filePathCallback, String acceptType, String capture)
{
mFilePathCallback4 = filePathCallback;
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
mActivity.startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_FILE_PICKER);
}
//5.0+
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams)
{
mFilePathCallback5 = filePathCallback;
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
mActivity.startActivityForResult(Intent.createChooser(intent, "File Chooser"), REQUEST_FILE_PICKER);
return true;
}
//外部在Activity的onActivityResult 调用
public void onActivityResult(int requestCode, int resultCode, Intent intent){
if(requestCode==REQUEST_FILE_PICKER){
if(mFilePathCallback4!=null)
{
Uri result = intent==null || resultCode!= Activity.RESULT_OK ? null : intent.getData();
if(result!=null)
{
mFilePathCallback4.onReceiveValue(result);
}
else
{
mFilePathCallback4.onReceiveValue(null);
}
}
if(mFilePathCallback5!=null)
{
Uri result = intent==null || resultCode!=Activity.RESULT_OK ? null : intent.getData();
if(result!=null)
{
mFilePathCallback5.onReceiveValue(new Uri[]{ result });
}
else
{
mFilePathCallback5.onReceiveValue(null);
}
}
mFilePathCallback4 = null;
mFilePathCallback5 = null;
}
}
}
Activity中
mWebView.setWebChromeClient(new SelectFileWebClient())
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(mSelectFileWebClient!=null){
mSelectFileWebClient.onActivityResult(requestCode,resultCode,data);
}
}
当然这只能打开file文件,如果想调用相机、录音的功能就需要另外来做
public class SelectFileWebClient extends WebChromeClient {
private static final int REQUEST_FILE_PICKER = 1;
private final Activity mActivity;
private ValueCallback<Uri> mFilePathCallback4;
private ValueCallback<Uri[]> mFilePathCallback5;
public SelectFileWebClient(Activity activity) {
this.mActivity = activity;
}
// For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
if (mUploadMessage != null) return;
mUploadMessage = uploadMsg;
startActivityForResult(createDefaultOpenableIntent(),
BrowserActivity.FILECHOOSER_RESULTCODE);
}
}
// For Android < 3.0
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
openFileChooser( uploadMsg, "" );
}
private Intent createDefaultOpenableIntent() {
// Create and return a chooser with the default OPENABLE
// actions including the camera, camcorder and sound
// recorder where available.
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
Intent chooser = createChooserIntent(createCameraIntent(), createCamcorderIntent(),
createSoundRecorderIntent());
chooser.putExtra(Intent.EXTRA_INTENT, i);
return chooser;
}
private Intent createChooserIntent(Intent... intents) {
Intent chooser = new Intent(Intent.ACTION_CHOOSER);
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, intents);
chooser.putExtra(Intent.EXTRA_TITLE, "File Chooser");
return chooser;
}
private Intent createCameraIntent() {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File externalDataDir = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM);
File cameraDataDir = new File(externalDataDir.getAbsolutePath() +
File.separator + "browser-photos");
cameraDataDir.mkdirs();
String mCameraFilePath = cameraDataDir.getAbsolutePath() + File.separator +
System.currentTimeMillis() + ".jpg";
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mCameraFilePath)));
return cameraIntent;
}
private Intent createCamcorderIntent() {
return new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
}
private Intent createSoundRecorderIntent() {
return new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
}
//外部在Activity的onActivityResult 调用
public void onActivityResult(int requestCode, int resultCode, Intent intent){
if(requestCode==REQUEST_FILE_PICKER){
if (null == mUploadMessage) return;
Uri result = data == null || resultCode != RESULT_OK ? null
: data.getData();
if (result == null && data == null && resultCode == Activity.RESULT_OK) {
File cameraFile = new File(mCameraFilePath);
if (cameraFile.exists()) {
result = Uri.fromFile(cameraFile);
// Broadcast to the media scanner that we have a new photo
// so it will be added into the gallery for the user.
sendBroadcast(
new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
}
}
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
}
}
}
Activity中
mWebView.setWebChromeClient(new SelectFileWebClient())
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(mSelectFileWebClient!=null){
mSelectFileWebClient.onActivityResult(requestCode,resultCode,data);
}
}