原创文章,转载请注明本文出处http://www.jianshu.com/p/841bfa47b45c
这篇文章的已知bug,我已经改好了,在我另一篇博文里,地址:http://www.jianshu.com/p/62f3750f72a8
前言
一周前做的项目中,要嵌入一个H5的页面,这个H5功能很简单,主要就是给用户提供预约申请,其中需要上传本人身份证。
在这里推荐一下github上面开源的小型AgentWeb
还有就是腾讯的TBS腾讯浏览服务
这两个我都在项目中尝试过,效果都还不错,关于这两个库的具体使用方法,我上面给出的github地址或官方技术接入指南讲的都比较详细,就不缀述了,您要是有疑问可以在评论区留言,咱们可以互相探讨。
正题
这是H5页面中需要上传图片的截图
H5页面中需要上传图片的截图.png
通过webview.loadUrl(“你要加载的地址”)加载网页时,在手持设备上点击图中上传图片时,用以上两个库不做任何处理的情况下,有以下问题:
- AgentWeb会出现弹出图片选择器,本以为接下来点击相册会进入相册,但是实际情况是(不同手机会有不同表现)点击相册之后,闪退。
- 集成TBS腾讯浏览服务,不给webView设置一个webview.webviewClient(),会从手机上已安装的一个浏览器正常打开相册,但是这样就像是从你的应用进入到了其他应用,所以一般还是要webView.setWebViewClient(),写上这个方法之后,点击上传图片会没有任何响应。
解决
这个时候我们需要H5跟Android互调(js跟java互调)
思路:在H5页面上点击这个上传图片时,调用的是Android原生方法来打开相册或者摄像头,下面以打开相册为例。
代码片段:
// js 调android 方法
webView.addJavascriptInterface(new DemoJavaScriptInterface(), "demo");
这里的DemoJavaScriptInterface是你要定义给JS调用的方法的所属类名,
下图中的demo.chickOnAndroid就是js中要拼接而成的方法
js中调用安卓方法.png
/**
* 定义的给js调的方法
*/
final class DemoJavaScriptInterface{
DemoJavaScriptInterface(){
}
@JavascriptInterface
public void clickOnAndroid(String s){
//这里执行你用Android原生方法打开相册或摄像头的操作
//用intent打开即可
startActivityForResult(把intent传进来);
}```
**clickOnAndroid(String s)中的String类型的参数s,
就是js中window.demo.clickOnAndroid(getJson())方法中,getJson()返回的值**
要打开手机中的文件还需要
//用来接收下面ValueCallback<Uri> 回调
private ValueCallback<Uri> mUploadMessage;
private ValueCallback<Uri[]> uploadMessageAboveL;
..........................................................................................................................
webView.setWebChromeClient(new WebChromeClient(){
//Android 3.0 以下
public void openFileChooser(ValueCallback<Uri> valueCallback) {
mUploadMessage = valueCallback;
selectImage();//就是上面
}
// Android 3~4.1
public void openFileChooser(ValueCallback valueCallback, String acceptType) {
mUploadMessage = valueCallback;
selectImage();
}
// Android 4.1以上
public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {
mUploadMessage = valueCallback;
selectImage();
}
// Android 5.0以上
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback,
WebChromeClient.FileChooserParams fileChooserParams ) {
uploadMessageAboveL = filePathCallback;
selectImage();
return true;
}
});
openFileChooser是WebChromeClient中的隐藏方法需要你手动去写
5.0之后就变成了onShowFileChooser
selectImage()就是你选择图片的一些操作
private void selectImage() {
FileUtils.delFile(compressPath);
Intent intent;
if (Build.VERSION.SDK_INT < 19) {
intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
} else {
intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
Intent wrapperIntent = Intent.createChooser(intent, null);
//REQ_CHOOSE是定义的一个常量
startActivityForResult(wrapperIntent, REQ_CHOOSE);
}
在Activity中还要重写onActivityResult()来处理你选择图片之后的操作
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if(null == intent){
//为了避免 弹出 相册选择器 之后 点击取消 闪退
mUploadMessage.onReceiveValue(null);
return;
}
if (null== mUploadMessage){
mUploadMessage.onReceiveValue(null);
return;
}
Uri uri = null;
if (requestCode ==REQ_CHOOSE){
uri = afterChosePic(intent);
//afterChosePic()这是选择照片之后要处理的
}
mUploadMessage.onReceiveValue(uri);
mUploadMessage = null;
}```
afterChosePic()方法代码
private Uri afterChosePic(Intent data) {
// 获取图片的路径:
String[] proj = { MediaStore.Images.Media.DATA };
// 好像是android多媒体数据库的封装接口,具体的看Android文档
Cursor cursor = managedQuery(data.getData(), proj, null, null, null);
if(cursor == null ){
Toast.makeText(this, "上传的图片仅支持png或jpg格式",Toast.LENGTH_SHORT).show();
return null;
}
// 按我个人理解 这个是获得用户选择的图片的索引值
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
// 将光标移至开头 ,这个很重要,不小心很容易引起越界
cursor.moveToFirst();
// 最后根据索引值获取图片路径
String path = cursor.getString(column_index);
if(path != null && (path.endsWith(".png")||path.endsWith(".PNG")||path.endsWith(".jpg")||path.endsWith(".JPG"))){
File newFile = FileUtils.compressFile(path, compressPath);
return Uri.fromFile(newFile);
}else{
Toast.makeText(this, "上传的图片仅支持png或jpg格式",Toast.LENGTH_SHORT).show();
}
return null;
}
#####到此,webview加载h5页面(也就是js)选择图片的操作就基本完成了
(嘘,上班期间躲着写的,可能思路有点乱,没看明白的可以留言,我看到了就会回)
网友评论