WebView踩坑系列(二)
来源:互联网 发布:膝盖骨刺用什么药 知乎 编辑:程序博客网 时间:2024/06/03 16:41
WebView传递图片给前端
webView中常常会遇到许多的问题,而这些问题给我们开发带来的痛苦已经不能用言语来形容,以下是可能会遇到的问题之一。
- 开发场景:
- 开发中可能会有这样的需求,webview加载的网页中要从本地获取图片(或者文件,这里以获取图片为例),获取的图片包括从本地文件夹中获取和拍照获取,在ios系统上前端是可以直接调用拍照或者从相册中获取图片的,但在Android系统上面这一些都要自己来处理,那好吧,我们自己来解决这个问题。
第一步:设置回调
允许webview接受文件,webview中属性如下
/** * Enables or disables file access within WebView. File access is enabled by default. Note that this enables or disables file system access only. Assets and resources are still accessible using file:///android_asset and file:///android_res. */ public abstract void setAllowFileAccess(boolean allow);
注释的意思是webview默认允许接收文件,但这个属性只作用于系统文件,即使这个属性设置为false,resources和assets下的文件仍然可用。
所以我们可以不设置这个属性,但如果设置了的话不要赋值为false。
重写WebChromeClient,获取ValueCallback回调对象,可以将该对象理解为快递员,他要去客户端取货并将该物品返回给前端:
public class MyWebChormeClient extends WebChromeClient { private WebCall webCall; public MyWebChormeClient(WebCall webCall) { this.webCall = webCall; } // For Android 3.0+ public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { if (webCall != null) webCall.fileChose(uploadMsg); } // 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); if(webCall != null){ webCall.fileChose(uploadMsg); } } // For Android > 5.0 @Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { if (webCall != null) { webCall.fileChose5(filePathCallback); Log.e("getValueCallBack", "onShowFileChooser: "); } return true; } public interface WebCall { void fileChose(ValueCallback<Uri> uploadMsg); void fileChose5(ValueCallback<Uri[]> uploadMsg); }}
第二步:回调处理
当WebView中执行获取图片操作,会执行openFileChooser方法或者onShowFileChooser方法,这两个方法会给我们传递ValueCallback
这个对象,该对象的泛型可以用两种对象代替,Uri和Uri数组,分别适用不同版本的系统,我们客户端通过拍照获取图片文件或者从本地选取文件之后,将文件交给ValueCallback对象来处理,处理方式如下:
if (uri != null) { if (mUploadMessage != null) { mUploadMessage.onReceiveValue(uri); mUploadMessage = null } else if (mUploadMessageForAndroid5 != null) { mUploadMessageForAndroid5.onReceiveValue(new Uri[]{uri}); mUploadMessageForAndroid5 = null; }}
上述代码中的mUploadMessage对象和mUploadMessageForAndroid5对象由WebCall接口回调过来。
第三步:释放对象
在对ValueCallback的onReceiveValue方法进行赋值之后,要将ValueCallback的对象释放。
以下为主要代码:
收到来自前端要获取图片的ValueCallback对象
@Override public void fileChose(ValueCallback<Uri> uploadMsg) { openFileChooserImpl(uploadMsg); } @Override public void fileChose5(ValueCallback<Uri[]> uploadMsg) { openFileChooserImplForAndroid5(uploadMsg); } private void openFileChooserImpl(ValueCallback<Uri> uploadMsg) { mUploadMessage = uploadMsg; showBottomPopupWindow(); } private void openFileChooserImplForAndroid5(ValueCallback<Uri[]> uploadMsg) { mUploadMessageForAndroid5 = uploadMsg; showBottomPopupWindow(); }
弹出选择框,选择拍照、从本地选择照片或者是取消,取消时要将ValueCallback对象释放。
private boolean isTouchEvent; /** * 弹出底部照片选择框 */ private void showBottomPopupWindow() { if (softInputIsActive()) { hideSoftInput(mToolBar); } isTouchEvent = false; final CommonPopupWindow popupWindow = new CommonPopupWindow(this, mToolBar); popupWindow.setOnText1ClickListener(new View.OnClickListener() { @Override public void onClick(View v) { isTouchEvent = true; takePhoto(); popupWindow.dismiss(); } }); popupWindow.setOnText2ClickListener(new View.OnClickListener() { @Override public void onClick(View v) { isTouchEvent = true; choicePic(); popupWindow.dismiss(); } }); popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() { @Override public void onDismiss() { popupWindow.popupDismiss(); if (!isTouchEvent) if (mUploadMessage != null) { mUploadMessage.onReceiveValue(Uri.EMPTY); mUploadMessage = null; } else if (mUploadMessageForAndroid5 != null) { mUploadMessageForAndroid5.onReceiveValue(new Uri[]{Uri.EMPTY}); mUploadMessageForAndroid5 = null; } } }); popupWindow.show(); }
拍照和选择照片,大家可以使用自己的方法
/** * 拍照 */ private void takePhoto() { Intent imageCaptureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); String strImgPath = Config.PATH_IMAGE_TEMP_PATH;// 存放照片的文件夹,Config.PATH_IMAGE_TEMP_PATH是自定义的存放图片的路径 String fileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".jpg";// 照片命名 File out = new File(strImgPath); if (!out.exists()) { out.mkdirs(); } out = new File(strImgPath, fileName); imagePath = strImgPath + fileName;// 该照片的绝对路径 Uri uri = Uri.fromFile(out); imageCaptureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(imageCaptureIntent, REQUEST_CAMERA); } /** * 选择照片 */ private void choicePic() { Intent intent = new Intent(Intent.ACTION_PICK, null); intent.setDataAndType( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*"); startActivityForResult(intent, REQUEST_IMAGE); }
对ValueCallback的onReceiveValue方法赋值,并在赋值之后释放对象
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (mUploadMessage == null && mUploadMessageForAndroid5 == null) { return; } Uri uri = null; if (resultCode == RESULT_OK) { switch (requestCode) { case REQUEST_CAMERA: uri = Uri.fromFile(new File(imagePath)); break; case REQUEST_IMAGE: //本地选择图片后返 if (data != null && data.getData() != null) { uri = Uri.parse(data.getData().toString()); ContentResolver cr = this.getContentResolver(); Cursor cursor = cr.query(uri, null, null, null, null); if (cursor != null) { cursor.moveToFirst(); for (int i = 0; i < cursor.getColumnCount(); i++) { imagePath = cursor.getString(cursor .getColumnIndex("_data")); } } else { imagePath = uri.getPath(); } } break; } if (uri != null) { if (mUploadMessage != null) { mUploadMessage.onReceiveValue(uri); mUploadMessage = null; } else if (mUploadMessageForAndroid5 != null) { mUploadMessageForAndroid5.onReceiveValue(new Uri[]{uri}); mUploadMessageForAndroid5 = null; } } } else { if (mUploadMessage != null) { mUploadMessage.onReceiveValue(null); mUploadMessage = null; } else { mUploadMessageForAndroid5.onReceiveValue(new Uri[]{null}); mUploadMessageForAndroid5 = null; } } }
文件处理要比图片处理简单一些,文件处理不需要拍照,所以没有弹框选择,等同于图片处理中直接从本地获取图片。
以上是我对webView中进行图片(文件)处理的解决方法,如果出现错误的地方,还请指正。
- WebView踩坑系列(二)
- WebView踩坑系列(一)
- Android实战系列(二)---多用户类型登录(webview)
- WebView(二)
- 王学岗webview(二)
- android跨平台开发系列之-使用webview和JS调用(二)
- Android WebView 学习(二)
- webview 使用总结(二)
- android WebView(二)缩放
- WebView开发详解(二)
- WebView--展示H5(二)
- Android WebView(转二):Android WebView使用深入浅出
- Andrid控件 之 WebView(二)
- Android WebView的使用(二)
- (二)webView加载html字符串
- (二)WebView控件---》应用程序内置浏览器
- ios webview 进度条展示(二)使用
- Android --- WebView -- 混合开发(二)
- 【Linux】Linux中常用操作命令
- HTTP协议URL解析的C语言实现
- 利用javascript在控制台输出1到100之间所有的质数
- 第二篇博客
- rabbit多机多节点集群
- WebView踩坑系列(二)
- 公众号从菜鸟到高手进化:公众号客服功能
- 微信小程序----全国机场索引列表(MUI索引列表)
- 20171020.01
- echarts图表动态获取后台数据详解(二)
- Learning world representation
- iMindMap 10的两种分支主题满足你多种需求
- 全能地图下载器对比
- Docker 镜像基本操作