欢迎来到德薄能鲜网

德薄能鲜网

H5获取手机相机或相册图片两种方式

时间:2025-06-24 12:45:55 阅读(143)

需求目的:手机机通过webView展示H5网页,在特殊场景下,需要使用相机拍照或者从相册获取照片,上传后台。

完整流程效果:如下图
H5调用相机相册使用组件库方式流程

一、H5界面样例代码

使用html文件格式,文件直接打开就可以展示布局;一会在andriod webview中直接加载

<!DOCTYPEhtml><htmllang="en"xmlns:v-on="http://www.w3.org/1999/xhtml"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title></head><divid="app"><h1>alllalalallalal 默认会被覆盖</h1></div><templateid="why"><div><h2>{ { message}}</h2><h2>{ { counter}}</h2><button@click="increment">+1</button><button@click="decrement">-1</button><h1style="text-align:center;">{ {  title }}</h1><div><h2style="text-align:center;">android选中照片H5展示</h2><!--HTML5提供了<input type="file">元素来实现选取文件的功能,在WebView表现为调用onShowFileChooser--><inputaccept="image/*"capture="camera"ref="imgFile"type="file"multiple@change="previewFiles"><divid="preview"><imgv-for="imgSrc in imageSources":src="imgSrc":key="imgSrc"style="max-width:100px;max-height:100px;margin:10px;"></div></div></div></template><body><!-- 引入 Vue 3 的 CDN 资源网络加载不了 --><!-- <script src="https://unpkg.com/vue@next"></script> --><!-- 引入 Vue 3 的 CDN 资源,本地引用 --><scriptsrc="vue3.2.12global.js"></script><script>Vue.createApp({ template:'#why',data:function(){ return{ message:"功能开发中,敬请期待!",counter:100,pictureSelectorContent:"相机选择结果:",imageSources:[]// 存储图片的数据URL}},// 在你的 Vue 组件中处理 Webview 传递的数据mounted(){ // 设置全局函数,用于接收 WebView 调用// window.pictureSelectorResult = this.pictureSelectorResult;},methods:{ increment(){ this.counter++;console.log("点击了+1");},decrement(){ this.counter--;consloe.log("点击了-1");},startPictureSelector(){ window.android.startPictureSelector();},previewFiles(){ constfiles =this.$refs.imgFile.files;this.imageSources =[];for(leti =0;i <files.length;i++){ constfile =files[i];constreader =newFileReader();reader.onload=(e)=>{ this.imageSources.push(e.target.result);};reader.readAsDataURL(file);}},},}).mount("#app")</script><style>h1{ font-size:80px;font-weight:bold;margin-bottom:20px;}h2{ font-size:20px;font-weight:bold;color:#C8EFD4;}h3{ font-size:10px;font-weight:bold;color:#C8EFD4;}button1{ font-size:60px;padding:10px 20px;background-color:#007bff;color:#fff;border:none;border-radius:4px;cursor:pointer;margin-bottom:20px;margin-top:20px;text-align:center;/* 将文字水平居中显示 */display:flex;/* 将按钮设置为flex容器 */align-items:center;/* 将文字在垂直方向上居中显示 */}</style></body></html>

上述代码是前端代码,使用vue3框架展示一个基础 加减demo界面(不重要的冗余),以及 一个打开文件的按钮以及展示图片
在这里插入图片描述

其中HTML5提供了元素来实现选取文件的功能,当在WebView表现为调用onShowFileChooser后,回调图片uri列表一一获取并展示

二、Android打开相机以及相册的两种方式

方式一:android 原生方式

实际效果和流程示图
在这里插入图片描述

1.android界面逻辑代码
这边使用的是kotlin语言,使用的fragment界面展示,使用binding加载了布局,以及声明了webview组件,在webview上导入html链接,使本地H5界面展示

classVisitorFragment :Fragment(){ privatelateinitvarbinding:FragmentVisitorBinding    lateinitvarmActivity:Activity    privatelateinitvarmRoot:View    companionobject{ constvalTAG ="VisitorFragment"}privatevarmWebViewUrl:String ="file:///android_asset/vue_android_demo.html"varmAppName =MainApplication.instance.configuration.BASE_APP_LOGIN_IDENTITY    varmSystemName =WebViewConstant.DEFAULT_SYSTEM_NAME    privatevarmVisitorAndroidJs:VisitorAndroidJs =VisitorAndroidJs(this)privatevarmWebView:WebView?=nullvarmAndroidId:String =WebViewConstant.DEFAULT_DEVICE_SIGN    varmApiKey:String =WebViewConstant.DEFAULT_API_KEY    //回传H5时使用的对象privatevarmUploadCallback:ValueCallback<Array<Uri>>?=null//拍照传递的路径uriprivatevarmImageUri:Uri?=null/**     * onCreate方法是Activity生命周期的第一个回调方法     * ,当Activity被创建时被调用。     * 在这个方法中,你可以进行一些初始化的操作,比如设置布局、绑定控件、初始化数据等。     *     * @param savedInstanceState If the fragment is being re-created from     * a previous saved state, this is the state.     */overridefunonCreate(savedInstanceState:Bundle?){ super.onCreate(savedInstanceState)binding =FragmentVisitorBinding.inflate(layoutInflater)mRoot =binding.root        //记录valviewModel =ViewModelProvider(requireActivity())[DashboardViewModel::class.java]viewModel.setFragment(this)LogUtils.d(TAG,"onCreate")}/**     * onCreateView方法是Fragment生命周期的回调方法,     * 当Fragment创建并绘制其用户界面时被调用。     * 在这个方法中,你可以通过返回一个View对象来定义Fragment的用户界面。     * 它常用于加载布局文件、查找和初始化控件等操作。     *     * @return     */overridefunonCreateView(inflater:LayoutInflater,container:ViewGroup?,savedInstanceState:Bundle?):View { LogUtils.d(TAG,"onCreateView")initView(mRoot,layoutInflater,null)returnmRoot    }funinitView(parent:View?,inflater:LayoutInflater?,container:ViewGroup?){ //设置当前fragmentmAndroidId =DeviceUtils.getUniqueId(mActivity)initWebView()mWebView?.loadUrl(mWebViewUrl)//弹出展示链接showToast("${ getString(R.string.current_develop_environment)}$mWebViewUrl")initData()}overridefunonAttach(context:Context){ super.onAttach(context)mActivity =context asActivity    }/**     * @param msg 内容     */funshowToast(msg:String?){ valactivity:Activity?=activity        activity?.runOnUiThread{ Toast.makeText(activity,msg,Toast.LENGTH_SHORT            ).show()}}privatefuninitData(){ }overridefunonResume(){ super.onResume()LogUtils.d(TAG,"onResume")}@SuppressLint("SetJavaScriptEnabled")privatefuninitWebView(){ LogUtils.d(TAG,"initWebView")mWebView =binding.mainWebView        mWebView?.requestFocus()mWebView?.isHorizontalScrollBarEnabled =falsemWebView?.isVerticalScrollBarEnabled =falsevalsetting =mWebView?.settings        setting?.mixedContentMode =WebSettings.MIXED_CONTENT_ALWAYS_ALLOW;setting?.javaScriptEnabled =true//用于开启或禁用其 DOM(文档对象模型)存储功能,浏览器缓存这些数据setting?.domStorageEnabled =true//允许访问文件,默认允许setting?.allowFileAccess =true//设置不,会引起webView重新不急,默认NARROW_COLUMNSsetting?.layoutAlgorithm =WebSettings.LayoutAlgorithm.NARROW_COLUMNS        //自动缩放setting?.setSupportZoom(true)setting?.builtInZoomControls =true//自适应屏幕setting?.useWideViewPort =truesetting?.loadWithOverviewMode =true//支持多窗口setting?.setSupportMultipleWindows(true)setting?.setAppCacheEnabled(true)setting?.domStorageEnabled =true//定位setting?.setGeolocationEnabled(true)//优先使用缓存数据,在缓存数据不存在的情况下才去获取网络数据setting?.cacheMode =WebSettings.LOAD_CACHE_ELSE_NETWORK        setting?.savePassword =false//设置js接口mVisitorAndroidJs.let{ mWebView?.addJavascriptInterface(it,"android")}//页面不跳转浏览器mWebView?.webViewClient =object:WebViewClient(){ overridefunshouldOverrideUrlLoading(view:WebView,url:String):Boolean { LogUtils.d(TAG,"url: $url")view.loadUrl(url)returntrue}overridefunshouldInterceptRequest(view:WebView,request:WebResourceRequest            ):WebResourceResponse?{ varuri =request.url                varpath =uri.path                LogUtils.d(TAG,"uri: $uri, path: $path")returnsuper.shouldInterceptRequest(view,request)}}//webView官方打开文件选取方法onShowFileChooser,把网页回传文件mWebView?.webChromeClient =object:WebChromeClient(){ //API >=21(android 5.0.1)回调此方法overridefunonShowFileChooser(webView:WebView?,filePathCallback:ValueCallback<Array<Uri>>?,fileChooserParams:FileChooserParams?):Boolean { mUploadCallback =filePathCallback                //使用拍照或者打开文件mImageUri =ChoosePhotoFile.takePhoto(mActivity)//设置false会IllegalStateException: Duplicate showFileChooser resultreturntrue}}}funonActivityResultResponse(requestCode:Int,resultCode:Int,intent:Intent?){ LogUtils.d(TAG,"onActivityResultResponse requestCode $requestCode, resultCode:$resultCode")// 扫描二维码/条码回传if(requestCode ==ScanCodeUtils.REQUEST_CODE_SCAN &&resultCode ==Activity.RESULT_OK){ LogUtils.d(TAG,"onActivityResultResponse ${ intent?.extras}")if(intent ==null){ //弹出展示链接showToast("扫描结果为空")return}//传递给js,格式是"scanCodeResult('${ data.extras}')",其中单引号很重要,可能导致js script error//codedContent是组件中定义的参数名setEvaluateJavascript("scanCodeResult('${ intent.getStringExtra("codedContent")}')")}elseif(requestCode ==ChoosePhotoFile.REQUEST_CODE){ //拍照,界面跳回后,结果文件的使用ChoosePhotoFile.takeActivityResult(requestCode,intent,mUploadCallback,mImageUri)}}@OverrideoverridefunonDestroy(){ //防止更新dialog内存泄漏super.onDestroy()}/**     * 登录成功后跳转     */openfunloginSuccessJump(){ }/**     * 给网页传值     * 传递给js,格式是"scanCodeResult('${ data.extras}')"     * 其中单引号很重要,可能导致js script error     */privatefunsetEvaluateJavascript(jspMethodAndValue:String){ LogUtils.d(TAG,"setEvaluateJavascript mWebView ${ mWebView}, jspMethodAndValue $jspMethodAndValue")mWebView?.evaluateJavascript(jspMethodAndValue,ValueCallback<String>(){ LogUtils.d(TAG,"给网页传值为: $jspMethodAndValue")})}}

android layout布局

<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><WebViewandroid:id="@+id/main_web_view"android:layout_width="match_parent"android:layout_height="match_parent"/></androidx.constraintlayout.widget.ConstraintLayout>

2.获取照片的主要思路是两个方法:

  • webView官方打开文件选取方法onShowFileChooser,把网页回传文件
//webView官方打开文件选取方法onShowFileChooser,把网页回传文件mWebView?.webChromeClient =object:WebChromeClient(){ //API >=21(android 5.0.1)回调此方法overridefunonShowFileChooser(webView:WebView?,filePathCallback:ValueCallback<Array<Uri>>?,fileChooserParams:FileChooserParams?):Boolean { mUploadCallback =filePathCallback                //使用拍照或者打开文件mImageUri =ChoosePhotoFile.takePhoto(mActivity)//设置false会IllegalStateException: Duplicate showFileChooser resultreturntrue}}
  • 拍照或者相册选中后界面跳回后,使用ValueCallback<Array>回传
funonActivityResultResponse(requestCode:Int,resultCode:Int,intent:Intent?){ LogUtils.d(TAG,"onActivityResultResponse requestCode $requestCode, resultCode:$resultCode")if(requestCode ==ChoosePhotoFile.REQUEST_CODE){ //拍照或者相册选中后界面跳回后,结果文件的使用ChoosePhotoFile.takeActivityResult(requestCode,intent,mUploadCallback,mImageUri)}}
  • 以上onActivityResultResponse方法需要在actvity onActivityResult方法中使用
    (因为我这里是activity嵌套fragment的,如果直接在activity使用webview就不需我这太麻烦)
overridefunonActivityResult(requestCode:Int,resultCode:Int,data:Intent?){ super.onActivityResult(requestCode,resultCode,data)LogUtils.d(TAG,"onActivityResult requestCode11 $requestCode, resultCode:$resultCode")//设置当前fragmentvalfragment =mDashboardViewModel.fragment.value        Log.d(TAG,"fragment: $fragment")Log.d(TAG,"fragment.isResumed: ${ fragment?.isResumed}")//界面返回时VisitorFragment还没有Resumedif(fragment isVisitorFragment){ valvisitorFragment:VisitorFragment =fragment            visitorFragment.onActivityResultResponse(requestCode,resultCode,data)}}

3.打开相机和相册的工具类

objectChoosePhotoFile { privateconstvalTAG ="ChoosePhotoFile"constvalREQUEST_CODE:Int =12345funtakePhoto(activity:Activity):Uri { //相机可以访问的公共位置才能存储,获取时需要读取文件权限valfile:String =Environment.getExternalStorageDirectory().toString()+File.separator +Environment.DIRECTORY_PICTURES +File.separator        valfileName ="Image_${ SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())}.jpg"valrealFile =File(file,fileName)valimageUri =Uri.fromFile(realFile)LogUtils.d(TAG,"realFile:$realFile, imageUri: $imageUri")// 拍照后获取图片需要文件权限,界面跳转直接拿文件不需要权限//检查申请读文件权限CheckPermissionUtils.requestPermissions(activity,arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CAMERA))//调起相机,拍一张照片valcaptureIntent =Intent(MediaStore.ACTION_IMAGE_CAPTURE)captureIntent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri)//调起相册,取一张照片valphotoIntent =Intent(Intent.ACTION_PICK,MediaStore.Images.Media.EXTERNAL_CONTENT_URI)//选择方式,拍照或者相册valchooserIntent =Intent.createChooser(photoIntent,"Image Chooser")chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS,arrayOf<Parcelable>(captureIntent))activity.startActivityForResult(chooserIntent,REQUEST_CODE)returnimageUri    }/**     * H5针对从拍照或者相册中选中的图片做处理     * @param imageUri 拍照返回的数据,     */funtakeActivityResult(requestCode:Int,intent:Intent?,filePathCallback:ValueCallback<Array<Uri>>?,imageUri:Uri?){ if(requestCode ==REQUEST_CODE){ //从相册获取,返回的intentif(intent !=null&&intent.data !=null){ varuri:Uri =intent.data asUri                LogUtils.d(TAG,"file uri: $uri")filePathCallback?.onReceiveValue(arrayOf<Uri>(uri))}else{ //从拍照中获取图片,已经返回的imageUriLogUtils.d(TAG,"take photo imageUri: $imageUri")if(imageUri !=null){ filePathCallback?.onReceiveValue(arrayOf<Uri>(imageUri))}else{ filePathCallback?.onReceiveValue(null)}}}}}
方式二:使用android 组件库是实现-朋友圈获取照片功能

实际效果和流程示图
在这里插入图片描述
1.获取照片的主要思路是两个方法-替换

  • webView官方打开文件选取方法onShowFileChooser,把网页回传文件
//webView官方打开文件选取方法onShowFileChooser,把网页回传文件mWebView?.webChromeClient =object:WebChromeClient(){ //API >=21(android 5.0.1)回调此方法overridefunonShowFileChooser(webView:WebView?,filePathCallback:ValueCallback<Array<Uri>>?,fileChooserParams:FileChooserParams?):Boolean { mUploadCallback =filePathCallback                //使用拍照或者打开文件//                mImageUri = ChoosePhotoFile.takePhoto(mActivity)//模拟微信朋友圈获取照片模式LogUtils.d(TAG,"onShowFileChooser")PictureSelectorUtils.startPictureSelector(mActivity)//设置false会IllegalStateException: Duplicate showFileChooser resultreturntrue}}
  • 拍照或者相册选中后界面跳回后,使用ValueCallback<Array>回传
funonActivityResultResponse(requestCode:Int,resultCode:Int,intent:Intent?){ LogUtils.d(TAG,"onActivityResultResponse requestCode $requestCode, resultCode:$resultCode")if(requestCode ==PictureSelectorUtils.REQUEST_PICTURE_SELECTOR){ LogUtils.d(TAG,"onActivityResultResponse REQUEST_PICTURE_SELECTOR")PictureSelectorUtils.takeActivityResult(requestCode,intent,mUploadCallback)}}

2.打开相机和相册的工具类

objectPictureSelectorUtils { constvalREQUEST_PICTURE_SELECTOR =10012constvalTAG ="PictureSelectorUtils"funstartPictureSelector(activity:Activity){ LogUtils.d(TAG,"startPictureSelector")// 拍照后获取图片需要文件权限,界面跳转直接拿文件不需要权限//检查申请读文件权限//        CheckPermissionUtils.requestPermissions(//            activity,//            arrayOf(//                Manifest.permission.CAMERA,//                Manifest.permission.READ_EXTERNAL_STORAGE,//                Manifest.permission.WRITE_EXTERNAL_STORAGE//            )//        )//插件里自带了静态权限以及权限校验PictureSelector.create(activity).openGallery(PictureMimeType.ofImage()).imageEngine(GlideEngine)// Please refer to the Demo GlideEngine.java.isWeChatStyle(true)// 是否开启微信图片选择风格.selectionMode(PictureConfig.MULTIPLE).forResult(REQUEST_PICTURE_SELECTOR)}fungetPictures(data:Intent):MutableList<Uri>{ valselectList =PictureSelector.obtainMultipleResult(data)LogUtils.d(TAG,"getPicture selectList: $selectList")// 将照片路径转换成 Uri 列表valimageUris:MutableList<Uri>=ArrayList()if(selectList.isEmpty()){ LogUtils.d(TAG,"getPicture selectList isEmpty")returnimageUris        }for(imagePath inselectList){ varpath =imagePath.path            LogUtils.d(TAG,"path: $path")valuri =Uri.parse(path)LogUtils.d(TAG,"uri: $uri")imageUris.add(uri)}LogUtils.d(TAG,"imageUris: ${ imageUris.toString()}")returnimageUris    }/**     * H5针对从文件钟选中的图片做处理     */funtakeActivityResult(requestCode:Int,intent:Intent?,filePathCallback:ValueCallback<Array<Uri>>?,){ if(requestCode ==REQUEST_PICTURE_SELECTOR){ valselectList =PictureSelector.obtainMultipleResult(intent)LogUtils.d(TAG,"getPicture selectList: $selectList")// 将照片路径转换成 Uri 列表valimageUris:MutableList<Uri>=ArrayList()if(selectList.isEmpty()){ LogUtils.d(TAG,"getPicture selectList isEmpty")filePathCallback?.onReceiveValue(null)return}for(imagePath inselectList){ varpath =imagePath.path                LogUtils.d(TAG,"path: $path")valuri =Uri.parse(path)LogUtils.d(TAG,"uri: $uri")imageUris.add(uri)}LogUtils.d(TAG,"imageUris: ${ imageUris.toString()}")filePathCallback?.onReceiveValue(imageUris.toTypedArray())}}}

其中使用第三方组件库-实现类似朋友圈获取照片的样式,需要引入一下依赖

//照片获取类微信朋友圈implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.6.0'

拍照后获取图片需要文件权限,界面跳转直接拿文件不需要权限,且第三方插件库里自带了静态权限以及权限请求

3.我完整的代码——类似朋友圈获取界面逻辑

classVisitorFragment :Fragment(){ privatelateinitvarbinding:FragmentVisitorBinding    lateinitvarmActivity:Activity    privatelateinitvarmRoot:View    companionobject{ constvalTAG ="VisitorFragment"}privatevarmWebViewUrl:String ="file:///android_asset/vue_android_demo.html"varmAppName =MainApplication.instance.configuration.BASE_APP_LOGIN_IDENTITY    varmSystemName =WebViewConstant.DEFAULT_SYSTEM_NAME    privatevarmVisitorAndroidJs:VisitorAndroidJs =VisitorAndroidJs(this)privatevarmWebView:WebView?=nullvarmAndroidId:String =WebViewConstant.DEFAULT_DEVICE_SIGN    varmApiKey:String =WebViewConstant.DEFAULT_API_KEY    //回传H5时使用的对象privatevarmUploadCallback:ValueCallback<Array<Uri>>?=null//拍照传递的路径uriprivatevarmImageUri:Uri?=null/**     * onCreate方法是Activity生命周期的第一个回调方法     * ,当Activity被创建时被调用。     * 在这个方法中,你可以进行一些初始化的操作,比如设置布局、绑定控件、初始化数据等。     *     * @param savedInstanceState If the fragment is being re-created from     * a previous saved state, this is the state.     */overridefunonCreate(savedInstanceState:Bundle?){ super.onCreate(savedInstanceState)binding =FragmentVisitorBinding.inflate(layoutInflater)mRoot =binding.root        //记录valviewModel =ViewModelProvider(requireActivity())[DashboardViewModel::class.java]viewModel.setFragment(this)LogUtils.d(TAG,"onCreate")}/**     * onCreateView方法是Fragment生命周期的回调方法,     * 当Fragment创建并绘制其用户界面时被调用。     * 在这个方法中,你可以通过返回一个View对象来定义Fragment的用户界面。     * 它常用于加载布局文件、查找和初始化控件等操作。     *     * @return     */overridefunonCreateView(inflater:LayoutInflater,container:ViewGroup?,savedInstanceState:Bundle?):View { LogUtils.d(TAG,"onCreateView")initView(mRoot,layoutInflater,null)returnmRoot    }funinitView(parent:View?,inflater:LayoutInflater?,container:ViewGroup?){ //设置当前fragmentmAndroidId =DeviceUtils.getUniqueId(mActivity)initWebView()mWebView?.loadUrl(mWebViewUrl)//弹出展示链接showToast("${ getString(R.string.current_develop_environment)}$mWebViewUrl")initData()}overridefunonAttach(context:Context){ super.onAttach(context)mActivity =context asActivity    }/**     * @param msg 内容     */funshowToast(msg:String?){ valactivity:Activity?=activity        activity?.runOnUiThread{ Toast.makeText(activity,msg,Toast.LENGTH_SHORT            ).show()}}privatefuninitData(){ }overridefunonResume(){ super.onResume()LogUtils.d(TAG,"onResume")}@SuppressLint("SetJavaScriptEnabled")privatefuninitWebView(){ LogUtils.d(TAG,"initWebView")mWebView =binding.mainWebView        mWebView?.requestFocus()mWebView?.isHorizontalScrollBarEnabled =falsemWebView?.isVerticalScrollBarEnabled =falsevalsetting =mWebView?.settings        setting?.mixedContentMode =WebSettings.MIXED_CONTENT_ALWAYS_ALLOW;setting?.javaScriptEnabled =true//用于开启或禁用其 DOM(文档对象模型)存储功能,浏览器缓存这些数据setting?.domStorageEnabled =true//允许访问文件,默认允许setting?.allowFileAccess =true//设置不,会引起webView重新不急,默认NARROW_COLUMNSsetting?.layoutAlgorithm =WebSettings.LayoutAlgorithm.NARROW_COLUMNS        //自动缩放setting?.setSupportZoom(true)setting?.builtInZoomControls =true//自适应屏幕setting?.useWideViewPort =truesetting?.loadWithOverviewMode =true//支持多窗口setting?.setSupportMultipleWindows(true)setting?.setAppCacheEnabled(true)setting?.domStorageEnabled =true//定位setting?.setGeolocationEnabled(true)//优先使用缓存数据,在缓存数据不存在的情况下才去获取网络数据setting?.cacheMode =WebSettings.LOAD_CACHE_ELSE_NETWORK        setting?.savePassword =false//设置js接口mVisitorAndroidJs.let{ mWebView?.addJavascriptInterface(it,"android")}//页面不跳转浏览器mWebView?.webViewClient =object:WebViewClient(){ overridefunshouldOverrideUrlLoading(view:WebView,url:String):Boolean { LogUtils.d(TAG,"url: $url")view.loadUrl(url)returntrue}overridefunshouldInterceptRequest(view:WebView,request:WebResourceRequest            ):WebResourceResponse?{ varuri =request.url                varpath =uri.path                LogUtils.d(TAG,"uri: $uri, path: $path")returnsuper.shouldInterceptRequest(view,request)}}//webView官方打开文件选取方法onShowFileChooser,把网页回传文件mWebView?.webChromeClient =object:WebChromeClient(){ //API >=21(android 5.0.1)回调此方法overridefunonShowFileChooser(webView:WebView?,filePathCallback:ValueCallback<Array<Uri>>?,fileChooserParams:FileChooserParams?):Boolean { mUploadCallback =filePathCallback                //使用拍照或者打开文件//                mImageUri = ChoosePhotoFile.takePhoto(mActivity)//模拟微信朋友圈获取照片模式LogUtils.d(TAG,"onShowFileChooser")PictureSelectorUtils.startPictureSelector(mActivity)//设置false会IllegalStateException: Duplicate showFileChooser resultreturntrue}}}funonActivityResultResponse(requestCode:Int,resultCode:Int,intent:Intent?){ LogUtils.d(TAG,"onActivityResultResponse requestCode $requestCode, resultCode:$resultCode")// 扫描二维码/条码回传if(requestCode ==ScanCodeUtils.REQUEST_CODE_SCAN &&resultCode ==Activity.RESULT_OK){ LogUtils.d(TAG,"onActivityResultResponse ${ intent?.extras}")if(intent ==null){ //弹出展示链接showToast("扫描结果为空")return}//传递给js,格式是"scanCodeResult('${ data.extras}')",其中单引号很重要,可能导致js script error//codedContent是组件中定义的参数名setEvaluateJavascript("scanCodeResult('${ intent.getStringExtra("codedContent")}')")//        } else if (requestCode == ChoosePhotoFile.REQUEST_CODE) { //            //拍照,界面跳回后,结果文件的使用//            ChoosePhotoFile.takeActivityResult(requestCode, intent, mUploadCallback, mImageUri)}elseif(requestCode ==PictureSelectorUtils.REQUEST_PICTURE_SELECTOR){ LogUtils.d(TAG,"onActivityResultResponse REQUEST_PICTURE_SELECTOR")PictureSelectorUtils.takeActivityResult(requestCode,intent,mUploadCallback)}}@OverrideoverridefunonDestroy(){ //防止更新dialog内存泄漏super.onDestroy()}/**     * 登录成功后跳转     */openfunloginSuccessJump(){ }/**     * 给网页传值     * 传递给js,格式是"scanCodeResult('${ data.extras}')"     * 其中单引号很重要,可能导致js script error     */privatefunsetEvaluateJavascript(jspMethodAndValue:String){ LogUtils.d(TAG,"setEvaluateJavascript mWebView ${ mWebView}, jspMethodAndValue $jspMethodAndValue")mWebView?.evaluateJavascript(jspMethodAndValue,ValueCallback<String>(){ LogUtils.d(TAG,"给网页传值为: $jspMethodAndValue")})}}

三、总结一下

  • H5调用公共获取图片文件方法,
  • 在android手机端,H5主要依赖Webview,
  • 这边在webview声明并重写该方法onShowFileChooser
  • 使用工具类打开相机或相册,可以两种方式安卓原生方式或者利用第三方组件库方式
  • 选中图片,返回uri列表给H5
  • H5收到uri照片列表,并且使用前端方式展示

创造价值,乐哉分享!

分享到:

温馨提示:以上内容和图片整理于网络,仅供参考,希望对您有帮助!如有侵权行为请联系删除!

友情链接: