疫情的影响,让迭代 App 的周期越来越短,很多情况下,为了快速发版,会使用 Webview 内嵌 H5 来开发,这两天遇到了发布一些资料的需求,这个是需要 H5 来做的。
为了限制发布图片的规格(避免调用拍照造成的更多的小问题),有了一个限制开启相机的需求,最好做到点击 H5 中的上传图片,就能够吊起系统相册。
当然了,没搜索到相关的技术贴,所以才有了今天的这篇文章。
其实也是在不断试错中试出来的。
一、排除了使用 H5 的 input 标签来限制
如果各位读者小伙伴用 input 标签中的内容限制住了,不妨评论一下。
二、只能从本地代码这找突破口了
用过 H5 交互的小伙伴应该都知道,如果用 H5 调用相机的话,我们可以使用
WebChromeClient 中的 onShowFileChooser,去捕捉到一些动作,所以添加了自定义的 WebChromeClient。
我这里只适配了 android 5.0 版本之上的,低版本的如果大家需要适配,可以实现以下这个 onShowFileChooser 方法的同名方法
public class JustImgWebViewClient extends WebChromeClient {@Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { return requestPermission(filePathCallback); } }
然后设置给 webview,当然其余的 setting 也一定记得设定啊
在初始化 webview 的时候,对webview 的setting 做了必要的设置。
private void init() { WebSettings settings = getSettings(); settings.setJavaScriptEnabled(true); settings.setUseWideViewPort(true); settings.setLoadWithOverviewMode(true); settings.setDomStorageEnabled(true); settings.setGeolocationEnabled(true); settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); settings.setAllowFileAccess(true); setWebChromeClient(new JustImgWebViewClient()); }
在调用本地相机相册系统之前,会执行 onShowFileChooser 方法,而在这个方法内部,需要做拍照和访问本地存储卡权限的处理,如果权限处理好了,就可以执行真正的逻辑了,权限的处理如下
public boolean requestPermission(ValueCallback<Uri[]> filePathCallback) {if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ) { Toast.makeText(getContext(), "请打开相机权限", Toast.LENGTH_SHORT).show(); ActivityCompat.requestPermissions((Activity) getContext(), new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, 110); return false; } else { mUploadCallbackAboveL = filePathCallback; take(); return true; } }
当然,权限的回调需要放到 Activity 中去处理了,这里我们先忽略掉权限的处理。直接看本文章的重点:去除拍照的选项。
直接看代码逻辑吧
public void take() { File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyApp"); if (!imageStorageDir.exists()) { imageStorageDir.mkdirs(); } File file = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg"); imageUri = Uri.fromFile(file); final List<Intent> cameraIntents = new ArrayList<Intent>(); final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); final PackageManager packageManager = getContext().getPackageManager(); final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0); for (ResolveInfo res : listCam) { final String packageName = res.activityInfo.packageName; final Intent i = new Intent(captureIntent); if (!res.activityInfo.name.contains("amera")) { 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[]{})); ((Activity) getContext()).startActivityForResult(chooserIntent, FILE_CHOOSER_RESULT_CODE); }}
真正的逻辑就在这里
通过 packageManager 可以拿到 H5 调用的 android 手机本地的选择器
final List<ResolveInfo> listCam = packageManager.queryIntentActivities(captureIntent, 0);
然后我打印了下这个调用选择器的 内容
然后,我有了一个大胆的想法
直接过滤掉 包含 camera 的意图,代码中通过
if (!res.activityInfo.name.contains("amera"))
做了判断。
结果万万没想到的是,竟然可以实现了这个功能,经测试一加、华为、vivo、小米 的手机都没有问题,实现了限制相机的功能,直接跳转到了相册页面。
所以才有了这篇文章,就当给大家做个参考吧,如果各位小伙伴有更好的办法,还望不吝赐教。
如果这篇文章对你还有点帮助,点个赞再划走吧,蟹蟹~
如果各位读者有一些难解决的问题,不妨留个言,留言点赞多的话,我会就你的问题来写个文章哦~
举报/反馈

黑键手记

78获赞 9粉丝
不太正经的 Android 工程师
关注
0
0
收藏
分享