项目中遇到了需要在webview上传图片的需求,搜索了一把,找到几个可行的方法,同时也踩了个webview的坑,总结一下
我找到的是这样的方法
***首先 重写WebChromeClient 添加openFileChooser 方法
// For Android 3.0+
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {//最终调用的都是这个
if (mUploadMessage != null) return;//坑就在这里 看后边注释
mUploadMessage = uploadMsg;
selectImage();
}
// For Android < 3.0
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
openFileChooser(uploadMsg, "");
}
// For Android > 4.1.1
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
openFileChooser(uploadMsg, acceptType);
}
*** 然后自己实现selectImage()方法
```
private void selectImage() {//模仿IOS的弹出框
List<map <String, String>> list = new ArrayList<>();
HashMap<string , String> ch1 = new HashMap<>();
HashMap</string><string , String> ch2 = new HashMap<>();
HashMap</string><string , String> ch3 = new HashMap<>();
ch1.put("key", "从相册选择");
ch2.put("key", "拍照上传");
ch3.put("key", "取消");
<pre><code> list.add(ch1);
list.add(ch2);
list.add(ch3);
ListAdapter ad = new SimpleAdapter(this, list, R.layout.my_simple_list_item_1, new String[]{"key"}, new int[]{android.R.id.text1});
chosePicDialog = new AlertDialog.Builder(this).setAdapter(ad, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
switch (i) {
case 0:
getImageFromAlbum();
break;
case 1:
getImageFromCamera();
break;
case 2:
mUploadMessage.onReceiveValue(null);//这里是坑,如果取消了 不调用这句mUploadMessage.onReceiveValue()的话 整个webview就都没有响应了
mUploadMessage = null;//还有这里 上边已标出
break;
}
}
}).setCancelable(false).create();
chosePicDialog.getWindow().setGravity(Gravity.BOTTOM);
chosePicDialog.show();
}
</code></pre>
```
然后分别实现 从图库选择和拍照上传的方法
```
/**
* 调用相册
<em>/
protected void getImageFromAlbum() {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/</em>");//相片类型
startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
}
<pre><code>/**
* 调用相机
*/
protected void getImageFromCamera() {//这里采用的是获取拍照原图的方法
String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
File f = FileUtil.getNewPicFilePath();
Uri u = Uri.fromFile(f);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, u);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);
startActivityForResult(intent,REQUEST_CODE_CAPTURE_CAMEIA);
} else {
Toast.makeText(getApplicationContext(), "请确认已经插入SD卡", Toast.LENGTH_LONG).show();
}
}
</code></pre>
```
***FileUtil.class内容
```
public class FileUtil {
private static String LastPicFilePath = null;
<pre><code>public static File getNewPicFilePath() {
String dirStr = Environment.getExternalStorageDirectory().getPath() + "/DCIM/Camera/";
File dir = new File(dirStr);
if (!dir.exists()) {
dir.mkdirs();
}
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String nowTime = format.format(new Date());
String localTempFileName = nowTime + ".jpg";
File f = new File(dir, localTempFileName);
setLastPicFilePath(f.getPath());
Log.e("getLastPicFilePath",getLastPicFilePath());
return f;
}
public static String getLastPicFilePath() {
return LastPicFilePath;
}
public static void setLastPicFilePath(String lastPicFilePath) {
LastPicFilePath = lastPicFilePath;
}
</code></pre>
}
```
***再重写onActivityResult@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) {
mUploadMessage.onReceiveValue(null);//这里防止拍照的时候取消了回来webview无响应的问题,这里是大坑
mUploadMessage = null;//上边注释说了,这里是坑
mWebView.requestFocus();
return;
}
if (requestCode == REQUEST_CODE_PICK_IMAGE) {
Uri uri = data.getData();
//to do find the path of pic by uri
mUploadMessage.onReceiveValue(uri);
} else if (requestCode == REQUEST_CODE_CAPTURE_CAMEIA) {
Uri uri = Uri.parse(FileUtil.getLastPicFilePath());//从上边指定的地址生成uri
mUploadMessage.onReceiveValue(uri);
}
super.onActivityResult(requestCode, resultCode, data);
}
总结
总体来说最坑的就是这个 mUploadMessage.onReceiveValue( );方法
没看WebChromeClient源码 猜想是如果不回调这句的话webview会一直等着你操作,造成整个webview界面没有响应,这个问题让我纠结了一下午时间,总结出来,希望对其他人有帮助。