html5仿原生相册,关于Webview中H5调起原生相册的问题

前言:

webview爬坑之路绵长慢慢, 混合开发, 当h5想调起系统原生的相机或者相册时, IOS无需做任何适配, 而Android还要苦逼的进行适配才行!

要想实现这个功能, 需要加以下代码:

mWebView.setWebChromeClient(new WebChromeClient() {

/**

* 16(Android 4.1.2) <= API <= 20(Android 4.4W.2)回调此方法

*/

public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) {

mUploadCallbackBelow = uploadMsg;

takePhoto();

}

/**

* API >= 21(Android 5.0.1)回调此方法

*/

@Override

public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {

// (1)该方法回调时说明版本API >= 21,此时将结果赋值给 mUploadCallbackAboveL,使之 != null

mUploadCallbackAboveL = filePathCallback;

takePhoto();

return true;

}

}

注意:

此处我只做了4.1以后的兼容处理, 再低的版本基本上现在市面上也很少有这样的机型了, 暂不做处理.

低于5.0的调用时会走openFileChooser()方法, 这个方法在SDK中被@hide注解了, 所以没有办法override, 但是你只需要重写上就可以.

takePhoto()方法的实现代码如下:

private void takePhoto() {

Intent i = new Intent(Intent.ACTION_GET_CONTENT);

i.addCategory(Intent.CATEGORY_OPENABLE);

i.setType("image/*");

startActivityForResult(Intent.createChooser(i, "Image Chooser"), 100);

}

重写onActivityResult()

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

super.onActivityResult(requestCode, resultCode, data);

if (requestCode == 100) {

//针对5.0以上, 以下区分处理方法

if (mUploadCallbackBelow != null) {

chooseBelow(resultCode, data);

} else if (mUploadCallbackAboveL != null) {

chooseAbove(resultCode, data);

} else {

Toast.makeText(this, "发生错误", Toast.LENGTH_SHORT).show();

}

}

}

/**

* Android API >= 21(Android 5.0) 版本的回调处理

*

* @param resultCode 选取文件或拍照的返回码

* @param data 选取文件或拍照的返回结果

*/

private void chooseAbove(int resultCode, Intent data) {

if (RESULT_OK == resultCode) {

updatePhotos();

if (data != null) {

// 这里是针对从文件中选图片的处理, 区别是一个返回的URI, 一个是URI[]

Uri[] results;

Uri uriData = data.getData();

if (uriData != null) {

results = new Uri[]{uriData};

mUploadCallbackAboveL.onReceiveValue(results);

} else {

mUploadCallbackAboveL.onReceiveValue(null);

}

} else {

mUploadCallbackAboveL.onReceiveValue(new Uri[]{imageUri});

}

} else {

mUploadCallbackAboveL.onReceiveValue(null);

}

mUploadCallbackAboveL = null;

}

private void updatePhotos() {

// 该广播即使多发(即选取照片成功时也发送)也没有关系,只是唤醒系统刷新媒体文件

Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);

intent.setData(imageUri);

sendBroadcast(intent);

}

/**

* Android API < 21(Android 5.0)版本的回调处理

*

* @param resultCode 选取文件或拍照的返回码

* @param data 选取文件或拍照的返回结果

*/

private void chooseBelow(int resultCode, Intent data) {

if (RESULT_OK == resultCode) {

updatePhotos();

if (data != null) {

// 这里是针对文件路径处理

Uri uri = data.getData();

if (uri != null) {

mUploadCallbackBelow.onReceiveValue(uri);

} else {

mUploadCallbackBelow.onReceiveValue(null);

}

} else {

// 以指定图像存储路径的方式调起相机,成功后返回data为空

mUploadCallbackBelow.onReceiveValue(imageUri);

}

} else {

mUploadCallbackBelow.onReceiveValue(null);

}

mUploadCallbackBelow = null;

}

以上便可以打开系统自带的相册, 同理可以处理打开系统自带相机, 但是要记得处理权限问题!

可能会遇到的问题:

打了Release包之后又打不开相册了, 这个问题我在开发的时候并没有遇到, 因为我们的项目没有进行混淆, 只是采用了加固. 但是我看别人的帖子有提到过这个问题.

原因: 由于项目中采用了混淆, 所以openFileChooser()由于不是重载的方法, 混淆之后找不到它了, 就没有办法调起相册,相机

解决办法:

混淆时做特殊处理:

-keepclassmembers class * extends android.webkit.WebChromeClient{

public void openFileChooser(…);

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值