赞
踩
最近和三方公司H5某些业务进行对接,本来说的是直接用WebView加载这个H5界面就完事了,后面才发现他们的需求不止于此…项目写完了,那边才说需要调用摄像头进行识别拍照等等,然而我这边不处理的话webview是无法调用摄像头的.
开始说问题:
1.权限,我这里用到的:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
2.webview页面WebViewSettings:
webView.requestFocusFromTouch();// 支持获取手势焦点,输入用户名、密码或其他 String ua = webView.getSettings().getUserAgentString(); webView.getSettings().setUserAgentString(ua+ "zdgj_1.0.0"); WebSettings webSettings = webView.getSettings(); webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件 webSettings.setJavaScriptEnabled(true);//支持js webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口 webSettings.setDatabaseEnabled(false);// 数据库缓存 webSettings.setAppCacheEnabled(false);// 打开缓存 webSettings.setDomStorageEnabled(true);// 打开dom storage缓存 webSettings.setAllowFileAccess(true); //设置可以访问文件 webSettings.setAllowContentAccess(true); // 是否可访问Content Provider的资源,默认值 true webSettings.setAllowFileAccess(true); // 是否可访问本地文件,默认值 true webSettings.setJavaScriptEnabled(true);// 允许网页与JS交互 webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH);// 提高渲染级别 webSettings.setLoadsImagesAutomatically(true);// 自动加载网络图片 webSettings.setDefaultTextEncodingName("utf-8");// 设置默认编码方式 // 是否允许通过file url加载的Javascript读取本地文件,默认值 false webSettings.setAllowFileAccessFromFileURLs(false); // 是否允许通过file url加载的Javascript读取全部资源(包括文件,http,https),默认值 false webSettings.setAllowUniversalAccessFromFileURLs(false); // 支持缩放 webSettings.setSupportZoom(true); webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);// 布局方式
这里对userAgent加了我们app的标识,方便三方公司的区分识别,不需要可以去掉
下面两个方法是提供给H5调用的
protected void initChildInfo() { webView.addJavascriptInterface(new onJavaScriptInterface(), "android"); } private class onJavaScriptInterface { /** * 返回上个界面 */ @JavascriptInterface public void finishView() { webView.post(new Runnable() { @Override public void run() { finish(); } }); } /** * 打电话 */ @JavascriptInterface public void callMobile(final String mobile) { webView.post(new Runnable() { @Override public void run() { Intent intent = new Intent(Intent.ACTION_DIAL); Uri data = Uri.parse("tel:" + mobile); intent.setData(data); startActivity(intent); } }); } }
3.最重要的自定义PaxWebChromeClient继承WebChromeClient :
public class PaxWebChromeClient extends WebChromeClient { private static final String TAG = "PaxWebChromeClient"; private final static int VIDEO_REQUEST = 0x11; private final static int PHOTO_REQUEST = 0x22; private Activity mActivity; private ValueCallback<Uri> uploadFile;//定义接受返回值 private ValueCallback<Uri[]> uploadFiles; private Uri imageUri; public PaxWebChromeClient(@NonNull Activity activity) { this.mActivity = activity; } @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); } @Override public void onReceivedTitle(WebView view, String title) { super.onReceivedTitle(view, title); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void onPermissionRequest(PermissionRequest request) { request.grant(request.getResources()); } // For Android 3.0+ public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { this.uploadFile = uploadMsg; openCamera(acceptType); } // For Android < 3.0 public void openFileChooser(ValueCallback<Uri> uploadMsgs) { this.uploadFile = uploadMsgs; } // For Android > 4.1.1 // @Override public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { this.uploadFile = uploadMsg; openCamera(acceptType); } // For Android >= 5.0 @Override @SuppressLint("NewApi") public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { this.uploadFiles = filePathCallback; String[] acceptTypes = fileChooserParams.getAcceptTypes(); for (int i = 0; i < acceptTypes.length; i++) { openCamera(acceptTypes[i]); LogUtils.e("类型类型类型:" + acceptTypes[i]); } return true; } private void openCamera(String accept) { if (accept.contains("image")) {// image/* // File fileUri = new File(Environment.getExternalStorageDirectory().getPath() + "/" + SystemClock.currentThreadTimeMillis() + ".jpg"); // imageUri = Uri.fromFile(fileUri); // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // imageUri = FileProvider.getUriForFile(mFragment.getActivity(), "com.mgyb.suning" + ".fileprovider", fileUri);//通过FileProvider创建一个content类型的Uri // } // PhotoUtils.takePicture(mFragment.getActivity(), imageUri, PHOTO_REQUEST); // 指定拍照存储位置的方式调起相机 String filePath = Environment.getExternalStorageDirectory() + File.separator + Environment.DIRECTORY_PICTURES + File.separator; String fileName = "IMG_" + DateFormat.format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".jpg"; imageUri = Uri.fromFile(new File(filePath + fileName)); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); mActivity.startActivityForResult(intent, PHOTO_REQUEST); } else if (accept.contains("video")) {// video/* Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE); // set the video file name intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0.5); //限制时长 intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 5); //开启摄像机 mActivity.startActivityForResult(intent, VIDEO_REQUEST); } } public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == RESULT_OK) { switch (requestCode) { case VIDEO_REQUEST: if (null != uploadFile) { Uri result = data == null || resultCode != RESULT_OK ? null : data.getData(); uploadFile.onReceiveValue(result); uploadFile = null; } if (null != uploadFiles) { Uri result = data == null || resultCode != RESULT_OK ? null : data.getData(); uploadFiles.onReceiveValue(new Uri[]{result}); uploadFiles = null; } break; case PHOTO_REQUEST: if (null == uploadFile && null == uploadFiles) return; Uri result = data == null || resultCode != RESULT_OK ? null : data.getData(); if (uploadFiles != null) { onActivityResultAboveL(requestCode, resultCode, data); } else if (uploadFile != null) { uploadFile.onReceiveValue(result); uploadFile = null; } break; default: break; } } else if (resultCode == Activity.RESULT_CANCELED) { if (null != uploadFile) { uploadFile.onReceiveValue(null); uploadFile = null; } if (null != uploadFiles) { uploadFiles.onReceiveValue(null); uploadFiles = null; } } } @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void onActivityResultAboveL(int requestCode, int resultCode, Intent data) { if (requestCode != PHOTO_REQUEST || uploadFiles == null) { return; } Uri[] results = null; if (resultCode == Activity.RESULT_OK) { if (data == null) { results = new Uri[]{imageUri}; } else { 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)}; } } uploadFiles.onReceiveValue(results); uploadFiles = null; } }
我在onShowFileChooser方法里对js的accept进行了处理,区别是录像还是拍照,然后在分别进行对应的操作
4.在webviewActivity 的 回调里调用 自定义chromeClient的onActivityResult()方法
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
chromeClient.onActivityResult(requestCode, resultCode, data);
super.onActivityResult(requestCode, resultCode, data);
}
5.如需要返回键网页逐级返回,就在加个监听
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// 处理返回键,在webview界面,按下返回键,不退出程序
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (webView.canGoBack()) {
webView.goBack();
return true;
} else {
onActivityBackPressed();
}
}
return super.onKeyDown(keyCode, event);
}
6.最后附上webviewActivity代码:
public class WebViewActivity extends BaseActivity { private PaxWebChromeClient chromeClient; private String mUrl; private WebView webView; public static void start(Context context, String url) { Intent intent = new Intent(context, WebViewActivity.class); intent.putExtra("url", url); context.startActivity(intent); } @Override public int getLayoutId() { return R.layout.activity_webview; } @Override protected void initView(View rootView) { webView = (WebView) findViewById(R.id.webview); Intent intent = getIntent(); mUrl = intent.getStringExtra("url"); chromeClient = new PaxWebChromeClient(this); initWebViewSettings(); webView.setWebChromeClient(chromeClient); webView.setWebViewClient(new MyWebViewClient()); webView.loadUrl(mUrl); initChildInfo(); } private void initWebViewSettings() { if (webView == null) { throw new NullPointerException("webview is null. please use initWebView(WebView webView) method"); } webView.requestFocusFromTouch();// 支持获取手势焦点,输入用户名、密码或其他 String ua = webView.getSettings().getUserAgentString(); webView.getSettings().setUserAgentString(ua+ "zdgj_1.0.0"); WebSettings webSettings = webView.getSettings(); webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件 webSettings.setJavaScriptEnabled(true);//支持js webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口 webSettings.setDatabaseEnabled(false);// 数据库缓存 webSettings.setAppCacheEnabled(false);// 打开缓存 webSettings.setDomStorageEnabled(true);// 打开dom storage缓存 webSettings.setAllowFileAccess(true); //设置可以访问文件 webSettings.setAllowContentAccess(true); // 是否可访问Content Provider的资源,默认值 true webSettings.setAllowFileAccess(true); // 是否可访问本地文件,默认值 true webSettings.setJavaScriptEnabled(true);// 允许网页与JS交互 webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH);// 提高渲染级别 webSettings.setLoadsImagesAutomatically(true);// 自动加载网络图片 webSettings.setDefaultTextEncodingName("utf-8");// 设置默认编码方式 // 是否允许通过file url加载的Javascript读取本地文件,默认值 false webSettings.setAllowFileAccessFromFileURLs(false); // 是否允许通过file url加载的Javascript读取全部资源(包括文件,http,https),默认值 false webSettings.setAllowUniversalAccessFromFileURLs(false); // 支持缩放 webSettings.setSupportZoom(true); webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE); webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);// 布局方式 } protected void initChildInfo() { webView.addJavascriptInterface(new onJavaScriptInterface(), "android"); } private class onJavaScriptInterface { /** * 返回上个界面 */ @JavascriptInterface public void finishView() { webView.post(new Runnable() { @Override public void run() { finish(); } }); } /** * 打电话 */ @JavascriptInterface public void callMobile(final String mobile) { webView.post(new Runnable() { @Override public void run() { Intent intent = new Intent(Intent.ACTION_DIAL); Uri data = Uri.parse("tel:" + mobile); intent.setData(data); startActivity(intent); } }); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { chromeClient.onActivityResult(requestCode, resultCode, data); super.onActivityResult(requestCode, resultCode, data); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { // 处理返回键,在webview界面,按下返回键,不退出程序 if (keyCode == KeyEvent.KEYCODE_BACK) { if (webView.canGoBack()) { webView.goBack(); return true; } else { onActivityBackPressed(); } } return super.onKeyDown(keyCode, event); } @Override public void onPause() { super.onPause(); webView.onPause(); } @Override public void onResume() { super.onResume(); webView.onResume(); } @Override public void onDestroy() { super.onDestroy(); try { webView.stopLoading(); webView.getSettings().setJavaScriptEnabled(false); webView.clearHistory(); webView.removeAllViews(); webView.destroy(); } catch (Exception e) { } } private class MyWebViewClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); hideStatusView(); } } }
到这里android 对 H5调用摄像头的处理就结束啦,感谢各位看官~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。