当前位置:   article > 正文

Android WebView调用系统相册和相机,注入以及与H5的交互_webview 增加打开相机相册交互

webview 增加打开相机相册交互

Android WebView调用系统相册和相机,注入以及与H5的交互

推荐:
如何设计一个优雅健壮的Android WebView?(上)
如何设计一个优雅健壮的Android WebView?(下)

Android Webview在使用的过程中,其实也是挺简单的,最基本的只需要加Seeting的配置即可成为一个H5链接的承载,但是不乏在使用的会遇到一些坑,这篇文章主要总结的是我在项目中所使用的一下Webview的功能等。各位大神,如果写的不正确的地方,请提出来!
一.Webview的基本配置

Webview的WebSettings基本配置大概也就那么多,当然了也有其他的少用的配置,这个可以根据需求来定,具体的每一个配置属性有注释,其他的属性大家可以在网上都能查到。我所使用的如下:

				public void setWebSettings(WebView mView){
				        WebSettings setting = mView.getSettings();
				        //支持Js
				        setting.setJavaScriptEnabled(true);
				        setting.setJavaScriptCanOpenWindowsAutomatically(true);
				        //缓存模式
				        setting.setCacheMode(WebSettings.LOAD_DEFAULT);
				        //支持内容重新布局
				        setting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
				        //将图片调整到适合webview的大小
				        setting.setUseWideViewPort(true);
				        setting.setLoadWithOverviewMode(true);
				        //设置可以访问文件
				        setting.setAllowFileAccess(true);
				        //支持自动加载图片
				        setting.setLoadsImagesAutomatically(true);
				        try {
				            setting.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
				        } catch (NoSuchMethodError e) {
				            e.printStackTrace();
				        }
				    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

对于Webview中的两个Client(WebViewClient和WebChromeClient)的配置,这里我也不在简述,毕竟方法太多了,在接下来的书写中会有一部分的描述使用。

二.Webview调用系统相册和相机
  1. 所需要的权限(注意针对于6.0系统,需要申请权限)
android.Manifest.permission.CAMERA)
android.Manifest.permission.READ_EXTERNAL_STORAGE
  • 1
  • 2
  1. 继承mWebChromeClient,对于系统相机和相册都是通过表单数据来返回给webview的,这里注意对比5.0以上和以下系统所是使用的方法,以下所有的代码都是对相机和相册的使用封装
		public class BaseWebChromeClient extends WebChromeClient {
		    private final static int FILE_REQUEST_CODE_SNAPSHOT = 100; //拍照表单的结果回调
		    private final static int FILE_CHOOSER_RESULT_CODE = 101;// 相册表单的结果回调
		    private ValueCallback<Uri> mUploadMessage;// 5.0以下表单的数据信息
		    public ValueCallback<Uri[]> mUploadCallbackAboveL;//5.0以上表单的数据信息
		    private Uri imageUri;
		    private Context mContext;
		
		    public BaseWebChromeClient(Context context) {
		        mContext = context;
		    }
		
		    @Override
		    public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
		        return super.onJsAlert(view, url, message, result);
		    }
		
		    @Override
		    public void onProgressChanged(WebView view, int newProgress) {
		        super.onProgressChanged(view, newProgress);
		        if (newProgress == 100) {
		            ((BaseActivity) mContext).dismissLoadingDialog();
		        }
		    }
		
		    @Override
		    public void onReceivedTitle(WebView view, String title) {
		        super.onReceivedTitle(view, title);
		        //处理404错误 android 6.0 以下通过title获取
		        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
		            if (title.contains("404") || title.contains("500") || title.contains("Error")) {
		                if (mContext instanceof BaseWebActivity) {
		                    ((BaseWebActivity) mContext).showErrorRefresh(view, mContext.getResources().getString(R.string.webview_not_found));
		                }
		            }
		        }
		    }
		
		//<---------------------------------重要代码-------------------------------------------->
		    @Override
		    public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
		        mUploadCallbackAboveL = filePathCallback;
		        PictureBusiness.getInstance().setUploadCallbackAboveL(mUploadCallbackAboveL);
		        String[] fileParams = fileChooserParams.getAcceptTypes();
		        if (fileParams.length > 0) {
		            for (int i = 0; i < fileParams.length; i++) {
		                LogUtil.i("BaseWebChromeClient", "FileChooserParams ----> " + fileParams[i]);
		            }
		        }
		        if (fileParams[0].equals(PictureBusiness.IMAGE)) {
		            PictureBusiness.getInstance().changePicture((Activity) mContext, PictureBusiness.IMAGE, false);
		        } else if (fileParams[0].contains(PictureBusiness.VIDEO)) {
		            PictureBusiness.getInstance().changePicture((Activity) mContext, PictureBusiness.VIDEO, false);
		        }
		        return true;
		    }
		
		    public void openFileChooser(ValueCallback<Uri> uploadMsg) {
		        mUploadMessage = uploadMsg;
		    }
		
		    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) {
		        mUploadMessage = uploadMsg;
		    }
		
		    public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
		        mUploadMessage = uploadMsg;
		    }
		
		
		    public void onActivityResult(int requestCode, int resultCode, Intent data) {
		        if (resultCode != Activity.RESULT_OK) {
		            if (mUploadMessage != null) {
		                mUploadMessage.onReceiveValue(null);
		            }
		            return;
		        }
		        //相册 & 拍照
		        if (requestCode == FILE_REQUEST_CODE_SNAPSHOT || requestCode == FILE_CHOOSER_RESULT_CODE) {
		            if (null == mUploadMessage && null == mUploadCallbackAboveL) {
		                return;
		            }
		            Uri result = data == null || (resultCode != RESULT_OK) ? null : data.getData();
		            if (mUploadCallbackAboveL != null) {
		                onActivityResultAboveL(requestCode, resultCode, data);
		            } else if (mUploadMessage != null) {
		                /*if (result != null) {
		                    String path = getPath(mContext.getApplicationContext(), result);
		                    Uri uri = Uri.fromFile(new File(path));
		                    mUploadMessage.onReceiveValue(uri);
		                } else {
		                    mUploadMessage.onReceiveValue(imageUri);
		                }
		                mUploadMessage = null;*/
		            }
		        }
		    }
		
		
		    @SuppressWarnings("null")
		    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
		    private void onActivityResultAboveL(int requestCode, int resultCode, Intent data) {
		        if (mUploadCallbackAboveL == null) {
		            return;
		        }
		        Uri[] results = null;
		        switch (requestCode) {
		            case FILE_CHOOSER_RESULT_CODE:
		                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)};
		                        }
		                    }
		                }
		                break;
		            case FILE_REQUEST_CODE_SNAPSHOT:
		                if (resultCode == Activity.RESULT_OK) {
		                    String videoPath = null;
		                    File capture = PictureBusiness.getInstance().getSnapshot();
		                    if (capture != null && capture.exists()) {
		                        videoPath = capture.getAbsolutePath();
		                    }
		                    if (videoPath != null) {
		                        results = new Uri[]{Uri.parse("file://" + videoPath)};
		                    }
		                }
		                break;
		            default:
		                break;
		        }
		
		        if (results != null) {
		            mUploadCallbackAboveL.onReceiveValue(results);
		            mUploadCallbackAboveL = null;
		        } else {
		            results = new Uri[]{imageUri};
		            mUploadCallbackAboveL.onReceiveValue(results);
		            mUploadCallbackAboveL = null;
		        }
		        return;
		    }
		
		}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
我在使用的过程中基本上是 没有问题的,但是部分手机上显示到webivew中的时候图片会有反转,这个也没有来的急解决,各位大佬有改过的可以评论一下方法

3.代码中使用
①在onResume中做判断

		if (mWebChromeClient.mUploadCallbackAboveL != null) {
		            mWebChromeClient.mUploadCallbackAboveL.onReceiveValue(null);
		            mWebChromeClient.mUploadCallbackAboveL = null;
		        }
  • 1
  • 2
  • 3
  • 4

②重写onActivityResult方法

		 mWebChromeClient.onActivityResult(requestCode, resultCode, data);
  • 1
三.使用Webview的拦截方法 shouldOverrideUrlLoading (重定向)

shouldOverrideUrlLoading :这个方法的返回值

  return true 表示当前url即使是重定向url也不会再执行(除了在return true之前使用webview.loadUrl(url)除外,因为这个会重新加载)
  return false  表示由系统执行url,直到不再执行此方法,即加载完重定向的ur(即具体的url,不再有重定向)
  • 1
  • 2

这个拦截方法其实也可以作为和H5的交互,比如在我自已的项目需求中,有一个按钮需要点击跳转,这个时候将返回设置为true,通过H5返回的数据(协商定义)进行判断跳转处理

四.解析Webview的Cookie

获取Cookie使用的是CookieManager,这里我举例项目中使用Cookie,如下代码:

		 @Override
		    protected void shouldUrlLoading(WebView view, String request) {
		        if (request.contains("backpwd") || request.contains("regagreement") || request.contains("problem/a5.html")) {
		            mBaseWeb.loadUrl(request);
		        } else {
		            //登录成功后,拦截操作
		            try {
		                LogUtil.i("login", URLDecoder.decode(request, "utf-8"));
		                if (URLDecoder.decode(request, "utf-8").contains(boLogin.getRedirect_url())) {
		                //------使用代码 start-------
		                    CookieManager cookieManager = CookieManager.getInstance();
		                    String cookieStr = cookieManager.getCookie(url);
		                    LoginCookie cookie = getLoginCookie(cookieStr);
		                    //------使用代码 end-----
		                    LoginBean loginBean = new LoginBean();
		                    loginBean.setUid(cookie.getBfuid());
		                    loginBean.setThirdUid("");
		                    loginBean.setToken(cookie.getLoginToken());
		                    loginBean.setuName(cookie.getBf_user_name());
		                    loginBean.setLoginType(cookie.getLogin_type());
		                    LoginBusiness.login(this, loginBean);
		                }
		            } catch (UnsupportedEncodingException e) {
		                e.printStackTrace();
		            }
		        }
		    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

getLoginCookie方法如下:

			/**
			     * 解析Cookie
			     *
			     * @param cookieStr
			     * @return
			     */
			    protected LoginCookie getLoginCookie(String cookieStr) {
			        HashMap<String, String> cookieContiner = new HashMap<>();
			        String[] keyvalues = cookieStr.split(";");
			        for (int i = 0; i < keyvalues.length; i++) {
			            String[] keyPair = keyvalues[i].split("=");
			            String cookieKey = keyPair[0].trim();
			            String cookieValue = keyPair.length > 1 ? keyPair[1].trim() : "";
			            cookieContiner.put(cookieKey, cookieValue);
			        }
			        String cookie = JSONObject.toJSONString(cookieContiner);
			        LogUtil.i("cookie", "login cookie = " + cookieStr + "\n" + cookie);
			        LoginCookie loginCookie = JSONObject.parseObject(cookie, LoginCookie.class);
			        return loginCookie;
			    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

以上只是举个例子,具体H5返回的Cookie需要由后端来定

五.Webview的注入

关于Webview的注入我了解的有两种,也是最常用的,即H5调用Android的方式和Android调用H5的方式

  1. Android调用H5的方式
    一般我们加载网页的是通过mWeb.loadUrl(url);加载的,这个其实也可以调用H5提供的方法,既能表示也能注入也能表示调用H5的方式,具体一行代码搞定:
    		    webView.loadUrl("javascript:"+"方法名");
    
    • 1
  2. H5调用Android的方式
    写一个类,加注解@JavascriptInterface,如下
@SuppressLint("JavascriptInterface")
    class JSInterface {
        /**
         * Toast
         *
         * @param mToast 显示内容
         */
        @JavascriptInterface
        public void toast(String mToast) {
            SRLog.i(TAG, "--->toast " + mToast);
            Toast.makeText(WebActivity.this, mToast, Toast.LENGTH_SHORT).show();
        }

        /**
         * 中间件  消息控制
         *
         * @param str 内容
         */
        @JavascriptInterface
        public void startMiddleWare(String str) {
            SRLog.i(TAG, "--->middle " + str);
            TellManager.getInstance().sendAsr(getApplication(), getPackageName(), str);
            finish();
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

注意,WebSettings中的属性setJavaScriptEnabled(true);要设置为true
使用方式:

        JSInterface  mJsInterface = new JSInterface(this);
        mBaseWeb.addJavascriptInterface(mJsInterface, "InjectOsUser");
        //InjectOsUser这个是需要提供给H5调用的,如InjectOsUser.toast("xxx");
  • 1
  • 2
  • 3
六.总结
以上就是WebView的部分使用,这也是有可能大部分项目中能使用到的功能,这里我也不在叙述WebViewClient中的一些方法,如onPageStarted,onPageFinished等,这些方法的使用也比较简单。最后在推荐一个对WebView的使用非常全的网站,大家可以在上面查到更多的方法。

如何设计一个优雅健壮的Android WebView?(上)
如何设计一个优雅健壮的Android WebView?(下)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/105044
推荐阅读
相关标签
  

闽ICP备14008679号