android webview本身不支持文件上传,因此我们需要重写webview的WebChromeClient,对其中的onShowFileChooser(高版本会调用这个)和openFileChooser(低版本会调用这个)做相应处理,先上代码:
public class MyChromeClient extends WebChromeClient {
private UrlActivity activity;
public static final int FILECHOOSER_RESULTCODE = 5173;
public static String mCameraFilePath = "";
@SuppressWarnings("deprecation")
public MyChromeClient(UrlActivity cordova) {
this.activity = cordova;
}
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
}
// <input type="file" name="fileField" id="fileField" />
// Android > 4.1.1
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
FileChooserParams fileChooserParams) {
// TODO 自动生成的方法存根
this.activity.setmUploadMsgList(filePathCallback);
// UploadMsg2 = filePathCallback;
this.activity.startActivityForResult(createDefaultOpenableIntent(), this.FILECHOOSER_RESULTCODE);
// return false;
// Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
// intent.addCategory(Intent.CATEGORY_OPENABLE);
// intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
// "image/*");
// this.activity.startActivityForResult(Intent.createChooser(intent,
// ""), this.FILECHOOSER_RESULTCODE);
return true; // 如果返回false,在选择文件过程中按返回键会崩溃,不知道为啥
}
@SuppressWarnings("static-access")
public void openFileChooser(ValueCallback<Uri> uploadMsg,
String acceptType, String capture) {
this.activity.setmUploadMsg(uploadMsg);
this.activity.startActivityForResult(createDefaultOpenableIntent(), this.FILECHOOSER_RESULTCODE);
}
// 3.0 +
@SuppressWarnings("static-access")
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
this.activity.setmUploadMsg(uploadMsg);
this.activity.startActivityForResult(createDefaultOpenableIntent(), this.FILECHOOSER_RESULTCODE);
}
// Android < 3.0
@SuppressWarnings("static-access")
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
this.activity.setmUploadMsg(uploadMsg);
this.activity.startActivityForResult(createDefaultOpenableIntent(), this.FILECHOOSER_RESULTCODE);
}
private Intent createDefaultOpenableIntent() {
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
"image/*");
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, "选择图片");
return chooser;
}
@SuppressWarnings("static-access")
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 + "515aaa");
cameraDataDir.mkdirs();
String mCameraFilePath = cameraDataDir.getAbsolutePath()
+ File.separator + System.currentTimeMillis() + ".jpg";
this.mCameraFilePath = mCameraFilePath;
cameraIntent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);
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); }
*/
public static Uri getImageContentUri(Context context, java.io.File imageFile) {
String filePath = imageFile.getAbsolutePath();
Cursor cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Images.Media._ID },
MediaStore.Images.Media.DATA + "=? ",
new String[] { filePath }, null);
if (cursor != null && cursor.moveToFirst()) {
int id = cursor.getInt(cursor
.getColumnIndex(MediaStore.MediaColumns._ID));
Uri baseUri = Uri.parse("content://media/external/images/media");
return Uri.withAppendedPath(baseUri, "" + id);
} else {
if (imageFile.exists()) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, filePath);
return context.getContentResolver().insert(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} else {
return null;
}
}
}
}
此时还需要重写加载webview的这个Activity的onActivityResult方法,在这里才是把文件传给web的
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case MyChromeClient.FILECHOOSER_RESULTCODE:
if (null == mUploadMsg && null == mUploadMsgList) {
Log.i("webview activity", "UploadMsg =null");
return;
}
Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
if (result != null) {
if (null != mUploadMsg) {
mUploadMsg.onReceiveValue(result);
}
if (null != mUploadMsgList) {
mUploadMsgList.onReceiveValue(new Uri[] { result });
}
} else {
Log.i("webview activity", "result =null");
setResultNull();
}
break;
default:
break;
}
}
private void setResultNull() {
if (null != mUploadMsg) {
mUploadMsg.onReceiveValue(null);
}
if (null != mUploadMsgList) {
mUploadMsgList.onReceiveValue(null);
}
}
mUploadMsg.onReceiveValue(null); 和mUploadMsgList.onReceiveValue(null);是必须要有的,比如正在选择图片上传时按返回键,如果不回传null,
web端会一直等待结果,导致你再次点击无响应。
mUploadMsgList是ValueCallback<Uri[]> 的对象,4.1以后的版本都使用的是Uri数组回传,以前是使用Uri即只能传单个文件
mUploadMsg是ValueCallback<Uri>的对象,这两个变量定义在WebView的activity里面,在
MyChromeClient里面是有相应赋值的。
如此即可。