Android(安卓)WebView实现选择本地图片拍照功能
相关文章
Android 仿微信加载H5页面进度条实现
Android WebView系列(二)Android和JS互调,BridgeWebView的使用。
前言
Android中通过WebView和H5页面进行交互,有时候会有其他需求比如H5页面需要从手机本地文件中选择图片。本篇以BridgeWebView介绍功能的实现。
1.自定义ProgressWebView
class ProgressWebView(context: Context, attr: AttributeSet) : BridgeWebView(context, attr) { private var progressBar: ProgressBar? = null private var hasComplate: Boolean = false private var listener: OnImageSelectorListener? = null init { progressBar = ProgressBar(context, null, android.R.attr.progressBarStyleHorizontal) progressBar!!.progressDrawable = context.resources.getDrawable(R.drawable.webview_hori_progress) val layoutParams = FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, 6, 0) progressBar!!.layoutParams = layoutParams addView(progressBar) webChromeClient = object : WebChromeClient() { override fun onProgressChanged(view: WebView?, newProgress: Int) { super.onProgressChanged(view, newProgress) if (progress == 100) { hasComplate = true progressBar!!.visibility = View.GONE } else { if (!hasComplate) { progressBar!!.visibility = View.VISIBLE progressBar!!.progress = progress } hasComplate = false } } fun openFileChooser(valueCallback: android.webkit.ValueCallback<Uri>, acceptType: String, capture: String) { listener!!.chooseImageFromSys4(valueCallback) } override fun onShowFileChooser(webView: WebView?, filePathCallback: android.webkit.ValueCallback<Array<Uri>>?, fileChooserParams: FileChooserParams?): Boolean { listener!!.chooseImageFromSys(filePathCallback) return true } } } interface OnImageSelectorListener { fun chooseImageFromSys(filePathCallback: ValueCallback<Array<Uri>>?) fun chooseImageFromSys4(valueCallback: android.webkit.ValueCallback<Uri>) } fun setOnSelectListener(listener: OnImageSelectorListener) { this.listener = listener }}
之前有篇博客介绍了仿微信加载H5进度条的实现,以此为基础,之前在加载csdn网站时,出现了一个现象,监听页面加载progress时,已经到了100后,进度又会重新加载一次,具体产生原因不知,猜测是加载页面后网址进行了重定向。所以这里做了一个小优化,加载完成后设置标志位让进度条不再显示。
openFileChooser和onShowFileChooser 这两个方式是WebView辅助类WebChromeClient用来监听JS中事件,事件用来调用系统文件。当监听到后回调到Activity进行选择图片操作。
ValueCallback,这个类的作用是,将我们选择的图片回调给JS。而回调的类型是图片的Uri。ValueCallback提供了一个方法.onReceiveValue(uri)。
2.XML声明自定义的View
<com.xxx.yyyyy.widget.ProgressWebView android:id="@+id/progressWebView" android:layout_width="match_parent" android:layout_height="match_parent" />
3.设置WebView,选择图片回调
3-1.配置WebView
这里是WebView几个重要必要的配置选项,其他配置根据自己情况而定
val setting = progressWebView!!.settingssetting!!.allowFileAccess = truesetting.javaScriptEnabled = truesetting.cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORKsetting.userAgentString = setting.userAgentString + "penglaiapp"if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { setting.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW}progressWebView!!.setDefaultHandler(MyHadlerCallBack())private inner class MyHadlerCallBack : DefaultHandler() { override fun handler(data: String?, function: CallBackFunction?) { if (function != null) { Toast.makeText(this@IssueInvoiceActivity, "自定义类继承DefaultHandler:" + data!!, Toast.LENGTH_SHORT).show() } } } val params = HashMap<String, Any>()params["token"] = "token"params["money"] = invoiceMoneyparams["invoiceflag"] = invoiceTypeprogressWebView.callHandler("invoice", Gson().toJson(params)) {}progressWebView!!.registerHandler("goBack") { _, _ -> finish()} progressWebView!!.loadUrl(invoiceUrl)
3-2.WebView回调Activity
WebView回调选择图片操作在Activity里进行。
progressWebView!!.setOnSelectListener(object : ProgressWebView.OnImageSelectorListener { /*4.0以上系统*/ override fun chooseImageFromSys4(valueCallback: ValueCallback) { uploadMessage = valueCallback chooseImageFromSys() } /*5.0以上系统*/ override fun chooseImageFromSys(filePathCallback: ValueCallback>?) { uploadMessageAboveL = filePathCallback chooseImageFromSys() } })
这里是自定义的弹窗选择拍照或者相册方式。
private fun chooseImageFromSys() { SelectorDialog.Builder(this) .addItem(1, resources.getString(R.string.camera)) .addItem(2, resources.getString(R.string.gallery)) .setCancelable(false).setOnSelectedListener { id, name -> when (id) { /*选择相机拍照 这里默认已经获取权限*/ 1 -> onPickFromCameraClicked() /*相册选择*/ 2 -> onPickFromGaleryClicked() /*ValueCallback对象置空,否则无法再次获取JS事件*/ -1 -> { /*取消按钮*/ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { uploadMessageAboveL!!.onReceiveValue(null) uploadMessageAboveL = null } else { uploadMessage!!.onReceiveValue(null) uploadMessage = null } } } }.build().show()}
3-3.相册选择与相机拍照
3-3-1.相册选择图片
private val PICK_IMAGE_FROM_GALERY = 0x0002//相册选择RequestCode private fun onPickFromGaleryClicked() { val intent = Intent(Intent.ACTION_PICK) intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*") startActivityForResult(intent, PICK_IMAGE_FROM_GALERY) }
3-3-2.调用相机拍照
private var imageUri: Uri? = null //拍照Uri对象private var tempCameraFile: File? = null //拍照获取File文件对象private val PICK_IMAGE_FROM_CAMERA = 0x0001 //拍照RequestCodeprivate fun openCamera() { tempCameraFile = File(externalCacheDir, getString(R.string.cache__image, System.currentTimeMillis())) //7.0以上 FileProvider 获取Uri imageUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //通过FileProvider创建一个content类型的Uri FileProvider.getUriForFile(this, "com.xxx.yyyy.fileProvider", tempCameraFile) } else { Uri.fromFile(tempCameraFile) } val intent = Intent() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //添加这一句表示对目标应用临时授权该Uri所代表的文件 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) } //设置Action为拍照 intent.action = MediaStore.ACTION_IMAGE_CAPTURE //将拍取的照片保存到指定URI intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri) startActivityForResult(intent, PICK_IMAGE_FROM_CAMERA) }
3-4.选择图片回调
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (resultCode == RESULT_CANCELED) { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { uploadMessageAboveL!!.onReceiveValue(null) uploadMessageAboveL = null } else { uploadMessage!!.onReceiveValue(null) uploadMessage = null } } when (requestCode) { PICK_IMAGE_FROM_GALERY -> { tempCropFile = File(externalCacheDir, "pl_cover" + System.currentTimeMillis() + ".jpg") handleImageOnKitKat(data) } PICK_IMAGE_FROM_CAMERA-> { if (tempCameraFile!!.exists()) { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { uploadMessageAboveL!!.onReceiveValue(arrayOf(Uri.fromFile(tempCameraFile))) uploadMessageAboveL = null } else { uploadMessage!!.onReceiveValue(Uri.fromFile(tempCameraFile)) uploadMessage = null } } } } }
//相册选择 获取uri private fun handleImageOnKitKat(data: Intent?) { imagePath = null if (data != null) { imageUri = data.data if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { uploadMessageAboveL!!.onReceiveValue(arrayOf(imageUri)) uploadMessageAboveL = null } else { uploadMessage!!.onReceiveValue(imageUri) uploadMessage = null } }}
效果图
结尾
本篇介绍了WebView中选择图片功能实现。目前已经测试可用,大家也可以做参考。也有功能需要完善比如图片剪裁压缩等功能等。
更多相关文章
- Android(安卓)Studio App设置TextView文字内容大小颜色
- Android(安卓)TextView 中如何使用第三方字体
- Android项目运行提示
- android studio学习日记
- 日历视图的XML属性
- 安卓017ListView & GridView & ScrollView
- android中layout_gravity 和 gravity的区别
- Android黑科技动态加载(四)之动态启动插件Activity
- 【Android进阶】android:configChanges属性总结