android js交互_H5 通过 input 标签调起 Android 相册,点击取消时手机卡住

4d2dc3007b16adf450b7366c859976c2.png

如题,其实 H5 调起 Android 手机的相册相机功能,最好是使用 JS 与 Android 进行交互,因为这样可调节性大一些,可定制型强很多。

但是,现实的情况的的确确是发生了,H5 就是用了 input 标签,这样他能自动调起 Android 端的相机和文件,就像这样

d58e637a660efbb988f87ef79b822177.png

点击「上传头像」调起 Android 自带的相册和文件

ee83214c29b429ced671f14f0157e8f4.png

但是,当点击取消的时候,如果不做任何处理,手机就会卡住,无法操作。

那么发生了怎么办呢?只能找 百度、谷歌 “帮帮我了”呗

be39139a896c9c140e09a77bba4c697c.png

那你帮帮我吧

那么最终的结果是什么呢?

在取消的时候,也要将结果返回,否则会引起界面卡住

具体怎么操作呢?来看看吧

1、给webview 添加这样的 WebChromeClient,并重写 input 调起的方法

public class MyFileWebChromeClient extends WebChromeClient {public static final int REQUEST_FILE_PICKER = 1;public ValueCallback mFilePathCallback;public ValueCallback mFilePathCallbacks;Activity mContext;/** * 记录选择图片的 uri */public Uri imageUri;@Overridepublic void onReceivedTitle(WebView webView, String s) { super.onReceivedTitle(webView, s);}public MyFileWebChromeClient(Activity mContext) { super(); this.mContext = mContext;}/** * Android < 3.0 调用这个方法 * * @param filePathCallback */public void openFileChooser(final ValueCallback filePathCallback) { mFilePathCallback = filePathCallback; take();}/** * 3.0 + 调用这个方法 * * @param filePathCallback * @param acceptType */public void openFileChooser(final ValueCallback filePathCallback, final String acceptType) { mFilePathCallback = filePathCallback; take();}/** * js上传文件的事件捕获,也就在这里啦 * Android >4.1.1调用这个方法 * * @param filePathCallback * @param acceptType * @param capture */public void openFileChooser(final ValueCallback filePathCallback, final String acceptType, final String capture) { mFilePathCallback = filePathCallback; take();}@Overridepublic boolean onShowFileChooser(final WebView webView, final ValueCallback filePathCallback, final FileChooserParams fileChooserParams) { mFilePathCallbacks = filePathCallback; take(); return true;}/** * 返回选择相册或者拍照的图片 */private void take() { File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyApp"); // Create the storage directory if it does not exist if (!imageStorageDir.exists()) { imageStorageDir.mkdirs(); } File file = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg"); imageUri = Uri.fromFile(file); final List cameraIntents = new ArrayList(); final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); final PackageManager packageManager = mContext.getPackageManager(); final List listCam = packageManager.queryIntentActivities(captureIntent, 0); for (ResolveInfo res : listCam) { final String packageName = res.activityInfo.packageName; final Intent i = new Intent(captureIntent); i.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name)); i.setPackage(packageName); i.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); cameraIntents.add(i); } Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.addCategory(Intent.CATEGORY_OPENABLE); i.setType("image/*"); Intent chooserIntent = Intent.createChooser(i, "Image Chooser"); chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{})); mContext.startActivityForResult(chooserIntent, REQUEST_FILE_PICKER);}}

结合注释,应该能看懂吧。

2、在 webview 所在的 activity 重写 onActivityResult 方法

public class MyFileOnActivityResult {private static MyFileOnActivityResult myFileOnActivityResult;public MyFileOnActivityResult(MyFileWebChromeClient myFileWebChromeClient) { this.myFileWebChromeClient = myFileWebChromeClient;}public static MyFileOnActivityResult getInstance(MyFileWebChromeClient myFileWebChromeClient) { if (myFileOnActivityResult == null) { myFileOnActivityResult = new MyFileOnActivityResult(myFileWebChromeClient); } return myFileOnActivityResult;}MyFileWebChromeClient myFileWebChromeClient;/** * 以下代码是为了适应H5调用本地图片并且显示在h5上 */public void onActivityResult(int requestCode, int resultCode, Intent intent) { if (requestCode == MyFileWebChromeClient.REQUEST_FILE_PICKER) { if (null == myFileWebChromeClient.mFilePathCallback && null == myFileWebChromeClient.mFilePathCallbacks) { return; } Uri result = ((intent == null || resultCode != RESULT_OK) ? null : intent.getData()); if (myFileWebChromeClient.mFilePathCallbacks != null) { onActivityResultAboveL(requestCode, resultCode, intent); } else if (myFileWebChromeClient.mFilePathCallback != null) { myFileWebChromeClient.mFilePathCallback = null; } }}@SuppressWarnings("null")@TargetApi(Build.VERSION_CODES.BASE)private void onActivityResultAboveL(int requestCode, int resultCode, Intent data) { if (requestCode != MyFileWebChromeClient.REQUEST_FILE_PICKER || myFileWebChromeClient.mFilePathCallbacks == null) { return; } Uri[] results = null; if (resultCode == Activity.RESULT_OK) { if (data == null) { /** * 如果返回的结构为空,那么不从结果里面拿数据,而是直接从选择图片的路径拿 */ results = new Uri[]{myFileWebChromeClient.imageUri}; } else { /** * 如果返回了数据,则将返回的数据解析成 uri */ String dataString = data.getDataString(); ClipData clipData = data.getClipData(); if (clipData != null) { /** * 如果获取的图片经过了裁剪 */ results = new Uri[clipData.getItemCount()]; for (int i = 0; i < clipData.getItemCount(); i++) { ClipData.Item item = clipData.getItemAt(i); results[i] = item.getUri(); } } if (dataString != null) /** * 没有经过裁剪,直接取得的图片 */ results = new Uri[]{Uri.parse(dataString)}; } } /** * 如果经过了上面的处理,result 不为空,说明用户确实取得了图片,那么将 result 返回即可 * * 否则,返回空的图片(图片只有名字,并没有真正的图片) */ if (results != null) { myFileWebChromeClient.mFilePathCallbacks.onReceiveValue(results); myFileWebChromeClient.mFilePathCallbacks = null; } else { results = new Uri[]{myFileWebChromeClient.imageUri}; myFileWebChromeClient.mFilePathCallbacks.onReceiveValue(results); myFileWebChromeClient.mFilePathCallbacks = null; }}}

为了方便使用,搞了一个类,再 onActivityResult 中调用即可

这样:

 @Overrideprotected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { MyFileOnActivityResult instance = MyFileOnActivityResult.getInstance(myFileWebChromeClient); instance.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data);}

3、在点击时,也要判断下是否赋予了 拍照 和 读写 sd 卡的权限,这里就不贴代码了

ok , 这样就能解决点击取消键,界面卡住的问题了。

4、代码提交到 github 了,用户名 「guaju」,仓库名「AndroidCommonUtils」有需要看看吧

感谢各位朋友的支持,关注,转发,持续更新,蟹蟹!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值