android原生webview兼容h5的inputtype=file摄像和选择相片问题
2023年7月15日发(作者:)
android原⽣webview兼容h5的inputtype=file摄像和选择相⽚问题h5的在ios中app中能够正常调⽤显⽰拍照或者选择相⽚的选项框。在android⾃带的浏览器和微信中打开也是没有问题的。但是当在android app嵌套h5页⾯。发现在webview中,h5⽆法直接调起android的摄像头和选择相册功能。于是查了资料才发现。android中webview不能⽀持h5的直接调⽤摄像头和选择相册功能。需要需要setWebChromeClient并重写WebChromeClient下的openFileChooser和onShowFileChooser(5.0以后的)⽅法。input点击会触发这两个函数。需要在这⾥⽤android代码去调⽤摄像头和相册功能,然后把图⽚地址处理后回传给h5.1.先说⼀下坑吧,第⼀个就是权限问题,⼀个是读取存储权限,⼀个是照相机权限。这两个权限都是属于危险权限,在android6.0以后需要动态申请权限d 7.0以后访问⽂件需要设置FileProvider3.要设置webview的setting相关配置 ticalScrollBarEnabled(false); izontalScrollBarEnabled(false); WebSettings settings = tings(); WideViewPort(true); dWithOverviewMode(true); //注意这⾥ StorageEnabled(true); aultTextEncodingName("UTF-8"); owContentAccess(true); // 是否可访问Content Provider的资源,默认值 true owFileAccess(true); // 是否可访问本地⽂件,默认值 true // ⽀持缩放 portZoom(true);4.在manifest⾥⾯记得申请权限 5.如果要达到跟ios⼀样,点击h5页⾯就能弹出选择拍照或者相册,需要⾃⼰通过设置intent的相关参数进⾏处理 Intent intentPhoto = new Intent(_PICK); aAndType(AL_CONTENT_URI, "image/*"); File fileUri = new File(ernalStorageDirectory().getPath() + "/" + tThreadTimeMillis() + ".jpg"); imageUri = le(fileUri); if (_INT >= N_CODES.N) { imageUri = ForFile(this, getPackageName() + ".fileprovider", fileUri);//通过FileProvider创建⼀个content类型的Uri } //调⽤系统相机 Intent intentCamera = new Intent(); if (_INT >= N_CODES.N) { gs(_GRANT_READ_URI_PERMISSION); //添加这⼀句表⽰对⽬标应⽤临时授权该Uri所代表的⽂件 } ion(_IMAGE_CAPTURE); //将拍照结果保存⾄photo_file的Uri中,不保留在相册中 ra(_OUTPUT, imageUri); Intent chooser = new Intent(_CHOOSER); ra(_TITLE, "Photo Chooser"); ra(_INTENT, intentPhoto); ra(_INITIAL_INTENTS, new Intent[]{intentCamera}); startActivityForResult(chooser, PHOTO_REQUEST);全部关键代码如下:import issions;import ;import le;import esApi;import patActivity;import ovider;import er;public class WebActivity extends AppCompatActivity { private final static String TAG = "test"; private WebView webView; private ValueCallback mUploadMessage; private ValueCallback mUploadCallbackAboveL; private final static int PHOTO_REQUEST = 100; private final static int VIDEO_REQUEST = 110; private final static String url = "/ttf/v1/ocr/openOcrCcint?token=53aa357cabbb40a98a1bec9cef5added"; private LinearLayout parentLayout; private Uri imageUri; private boolean isVideo = false; private String acceptType; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { te(savedInstanceState); setContentView(ty_web); initView(); initData(); } protected void initView() { parentLayout = (LinearLayout) this .findViewById(Layout); webView = new WebView(this); Params lp = new Params( _PARENT, _PARENT); outParams(lp); w(webView); ticalScrollBarEnabled(false); izontalScrollBarEnabled(false); WebSettings settings = tings(); WideViewPort(true); WideViewPort(true); dWithOverviewMode(true); //注意这⾥ StorageEnabled(true); aultTextEncodingName("UTF-8"); owContentAccess(true); // 是否可访问Content Provider的资源,默认值 true owFileAccess(true); // 是否可访问本地⽂件,默认值 true owFileAccessFromFileURLs(false); // 是否允许通过file url加载的Javascript读取本地⽂件,默认值 false owUniversalAccessFromFileURLs(false); // 是否允许通过file url加载的Javascript读取全部资源(包括⽂件,http,https),默认值 false //开启JavaScript⽀持 aScriptEnabled(true); // ⽀持缩放 portZoom(true); //注意这⾥ 辅助WebView设置处理关于页⾯跳转,页⾯请求等操作 ViewClient(new WebViewClient(){ @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { //如果有视频或者别的url 可以在此处进⾏判断处理 if (!y(url)) { isVideo = ns("vedio"); } l(url); return true; } }); //注意这⾥ 辅助WebView处理图⽚上传操作 ChromeClient(new MyChromeWebClient()); } protected void initData() { l(url); } @Override protected void onResume() { me(); } @Override protected void onPause() { e(); } @Override protected void onDestroy() { if (parentLayout!= null && webView != null){ View(webView); ading(); tings().setJavaScriptEnabled(false); istory(); iew(); AllViews(); try { y(); } catch (Exception e) { tackTrace(); } } roy(); } /** * 注意申请读取相机和读取内存的权限 */ private void startGetPhoto() { new RxPermissions(this).request(_EXTERNAL_STORAGE) .subscribe(new Consumer() { @Override public void accept(Boolean aBoolean) { if (aBoolean) { new RxPermissions().request() .subscribe(new Consumer() { @Override public void accept(Boolean aBoolean) { if (aBoolean) { //启动拍照或者选择相册图⽚⽂件 showPhotoChooser(); } else { Intent intent = new Intent(_APPLICATION_DETAILS_SETTINGS); Uri uri = rts("package", getPackageName(), null); a(uri); startActivityForResult(intent, 100); } } }); } else { xt(, "读取权限被拒绝,请在设置⾥⾯开启相应权限,若⽆相应权限部分功能将⽆法使⽤", _SHORT).show(); Intent intent = new Intent(_APPLICATION_DETAILS_SETTINGS); Uri uri = rts("package", getPackageName(), null); a(uri); startActivityForResult(intent, 100); } } }); } //⾃定义 WebChromeClient 辅助WebView处理图⽚上传操作【 ⽂件上传标签】 public class MyChromeWebClient extends WebChromeClient { // For Android 3.0- public void openFileChooser(ValueCallback uploadMsg) { mUploadMessage = uploadMsg; if (isVideo){ recordVideo(); }else { startGetPhoto(); } } // For Android 3.0+ public void openFileChooser(ValueCallback uploadMsg, String acceptType) { mUploadMessage = uploadMsg; acceptType = acceptType; if (isVideo){ recordVideo(); }else { startGetPhoto(); } } //For Android 4.1 public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) { mUploadMessage = uploadMsg; acceptType = acceptType; if (isVideo){ recordVideo(); }else { startGetPhoto(); } } // For Android 5.0+ @RequiresApi(api = N_OP) public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, ooserParams fileChooserParams) { mUploadCallbackAboveL = filePathCallback; acceptType = eptTypes()[0]; if (isVideo){ recordVideo(); }else { startGetPhoto(); xt(, "摄像机权限被拒绝,请在设置⾥⾯开启相应权限,若⽆相应权限部分功能将⽆法使⽤", _SHORT).sh startGetPhoto(); } return true; } } /** * 打开选择⽂件/相机 */ private void showPhotoChooser() { Intent intentPhoto = new Intent(_PICK); aAndType(AL_CONTENT_URI, "image/*");// Intent intentPhoto = new Intent(_GET_CONTENT);// egory(RY_OPENABLE);// e("*/*"); File fileUri = new File(ernalStorageDirectory().getPath() + "/" + tThreadTimeMillis() + ".jpg"); imageUri = le(fileUri); if (_INT >= N_CODES.N) { imageUri = ForFile(this, getPackageName() + ".fileprovider", fileUri);//通过FileProvider创建⼀个content类型的Uri } //调⽤系统相机 Intent intentCamera = new Intent(); if (_INT >= N_CODES.N) { gs(_GRANT_READ_URI_PERMISSION); //添加这⼀句表⽰对⽬标应⽤临时授权该Uri所代表的⽂件 } ion(_IMAGE_CAPTURE); //将拍照结果保存⾄photo_file的Uri中,不保留在相册中 ra(_OUTPUT, imageUri); Intent chooser = new Intent(_CHOOSER); ra(_TITLE, "Photo Chooser"); ra(_INTENT, intentPhoto); ra(_INITIAL_INTENTS, new Intent[]{intentCamera}); startActivityForResult(chooser, PHOTO_REQUEST); } /** * 录像 */ private void recordVideo() { Intent intent = new Intent(_VIDEO_CAPTURE); ra(_VIDEO_QUALITY, 1); //限制时长 ra(_DURATION_LIMIT, 10); //开启摄像机 startActivityForResult(intent, VIDEO_REQUEST); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { //如果按下的是回退键且历史记录⾥确实还有页⾯ if ((keyCode == E_BACK) && ack()) { (); return true; } return own(keyCode, event); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { vityResult(requestCode, resultCode, data); if (requestCode == PHOTO_REQUEST) { if (null == mUploadMessage && null == mUploadCallbackAboveL) { return; } Uri result = data == null || resultCode != RESULT_OK ? null : a(); if (mUploadCallbackAboveL != null) { onActivityResultAboveL(requestCode, resultCode, data); } else if (mUploadMessage != null) { iveValue(result); mUploadMessage = null; } } } } @TargetApi(N_OP) private void onActivityResultAboveL(int requestCode, int resultCode, Intent data) { if (requestCode != PHOTO_REQUEST || mUploadCallbackAboveL == null) { return; } Uri[] results = null; if (resultCode == _OK) { if (data == null) { results = new Uri[]{imageUri}; } else { String dataString = aString(); ClipData clipData = pData(); if (clipData != null) { results = new Uri[mCount()]; for (int i = 0; i < mCount(); i++) { item = mAt(i); results[i] = (); } } if (dataString != null) results = new Uri[]{(dataString)}; } }else if (requestCode == VIDEO_REQUEST) { if (null == mUploadMessage && null == mUploadCallbackAboveL) return; Uri result = data == null || resultCode != RESULT_OK ? null : a(); if (mUploadCallbackAboveL != null) { if (resultCode == RESULT_OK) { iveValue(new Uri[]{result}); mUploadCallbackAboveL = null; } else { iveValue(new Uri[]{}); mUploadCallbackAboveL = null; } } else if (mUploadMessage != null) { if (resultCode == RESULT_OK) { iveValue(result); mUploadMessage = null; } else { iveValue(); mUploadMessage = null; } } } iveValue(results); mUploadCallbackAboveL = null; }}Manifest⽂件 Gradle 引⼊rxjava和 rxpermissions⽅便权限判断 //rxjava implementation '2:rxjava:2.1.14' implementation 'issions2:rxpermissions:0.9.4@aar'
发布者:admin,转转请注明出处:http://www.yc00.com/web/1689425902a246237.html
评论列表(0条)