4.混合开发必学的WebView

作者: KnifeStone | 来源:发表于2017-01-13 19:15 被阅读709次

    apk/源码下载地址

    封面.png

    目录

    1.基本使用
    2.与JS交互之 WebChromeClient
    3.与JS交互之 addJavascriptInterface
    4.实战之 浏览器

    1.基本使用

    • 布局文件中使用 webview标签
    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <WebView
            android:id="@+id/webView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
    </FrameLayout>
    
    • 添加联网权限
    <uses-permission android:name="android.permission.INTERNET" />
    
    • 加载一个网址
    public class _4_1_Activity extends BaseActivity {
        private WebView mWebView;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_4_webview);
            mWebView = (WebView) findViewById(R.id.webView);
            mWebView.loadUrl("http://m.youdao.com/");
        }
    }
    
    • WebViewClient 页面加载过程中的事件通知控制
    //自己控制Web加载 有些机型可能回自动调用系统浏览器
    mWebView.setWebViewClient(new WebViewClient() {
    
        /**
         * 拦截新的url
         * 拦截对象:新的Url
         * 调用线程:UI线程
         * @return 控制范围:只能是yes或no
         */
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }
    
        /**
         * 拦截资源请求
         * 拦截对象:WebResourceRequest
         * 调用线程:IO线程
         * @return 控制范围:模拟数据
         */
        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                //拦截图片请求 用空数据替换 见下图
                if (request.getUrl().toString().contains(".png")) {
                    return new WebResourceResponse(null, null,
                            new ByteArrayInputStream(new byte[0]));
                }
            }
            return super.shouldInterceptRequest(view, request);
        }
    
        /**
         * 拦截收到错误
         */
        @Override
        public void onReceivedError(WebView view, WebResourceRequest request,
                                    WebResourceError error) {
            //这里自定义了一个错误页面
            String data = "<html><body>404 not found</body></html>";
            view.loadData(data, "text/html", null);
        }
    });
    
    • WebSettings 其它设置
    WebSettings settings = mWebView.getSettings();
    //设置默认文本编码的名字
    settings.setDefaultTextEncodingName("utf-8");
    //禁止加载图片
    settings.setLoadsImagesAutomatically(false);
    //启用JavaScript
    settings.setJavaScriptEnabled(true);
    //设置布局算法 TEXT_AUTOSIZING
    settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING);
    //开启缩放
    settings.setSupportZoom(true);
    //扩大比例的缩放
    settings.setUseWideViewPort(true);
    settings.setBuiltInZoomControls(true);
    //隐藏缩放控件
    settings.setDisplayZoomControls(false);
    //是否读取缓存模式
    settings.setCacheMode(WebSettings.LOAD_DEFAULT);
    //启用设置水平滚动条
    mWebView.setHorizontalScrollBarEnabled(true);
    //设置垂直滚动条启用
    mWebView.setVerticalScrollBarEnabled(true);
    // 安全考虑,防止密码泄漏,尤其是root过的手机
    settings.setSavePassword(false);
    //自适应屏幕
    settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
    settings.setLoadWithOverviewMode(true);
    settings.setDatabaseEnabled(true);
    
    • 返回键捕捉
    @Override
    public void onBackPressed() {
        //webview有上级页面
        if (mWebView.canGoBack()){
            //回退
            mWebView.goBack();
        }else{
            super.onBackPressed();
        }
    }
    

    2.与JS交互之 WebChromeClient

    与JS交互之WebChromeClient.gif
    • 项目中内置一个写好网页 main/assets/_4_2_javascript.html
    <html>
        <!-- 写好的javascript代码 -->
        <script type="text/javascript">
            <!-- 提醒 -->
            function userAlert(){
                alert("来自网页的提醒");
            }
            <!-- 提示 -->
            function userPrompt(){
                var result = prompt("来自网页的提示");
                document.getElementById("a2").innerText = result;
            }
            <!-- 加载成功注入 -->
            function writeDiv1(message) {
                document.getElementById("div1").innerText =  message;
            }
        </script>
        <body>
            <h4 id="title">欢迎来到webview与js交互的内容</h4>
            <div id = "div1"></div><br/>
            <a  href="javascript:void" onclick="userAlert()">点击弹出提醒</a><br/>
            <a id="a2" href="javascript:void" onClick="userPrompt()">点击弹出提示</a>
        </body>
    </html>
    
    • java中代码
    public class _4_2_Activity extends BaseActivity {
    
        private WebView mWebView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_4_webview);
            mWebView = (WebView) findViewById(R.id.webView);
            
            //启用JavaScript
            mWebView.getSettings().setJavaScriptEnabled(true);
            //不加载缓存
            mWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
            mWebView.setWebViewClient(new WebViewClient(){
                /**
                 * 页面加载成功后调用
                 */
                @Override
                public void onPageFinished(WebView view, String url) {
                    super.onPageFinished(view, url);
                    //页面加载成功后 调用js中的代码
                    mWebView.loadUrl("javascript:loadSuccess('页面加载成功android注入的内容')");
                }
            });
            mWebView.setWebChromeClient(new WebChromeClient(){
    
                //处理来自js的提醒
                @Override
                public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                    Toast.makeText(_4_2_Activity.this, message, Toast.LENGTH_SHORT).show();
                    //处理掉这个弹窗
                    result.confirm();
                    return true;
                }
                //处理来自js的提示
                @Override
                public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                    Toast.makeText(_4_2_Activity.this, message, Toast.LENGTH_SHORT).show();
                    result.confirm("来自android的-莫慌");
                    return true;
                }
    
            });
            mWebView.loadUrl("file:///android_asset/_4_2_javascript.html");
        }
    }
    

    3.与JS交互之 addJavascriptInterface

    与JS交互之addJavascriptInterface.gif
    • 项目中内置一个写好的main/assets/_4_3_add_interface.html
    <!Doctype html>
    <html>
        <script type="text/javascript">
            <!-- 页面加载调用的方法 -->
            window.onload = function() {
                <!-- 调用初始化标题的接口 -->
                var str = MyJavascriptInterface.initTitle();
                document.getElementById("title").innerText = str;
            }
            <!-- 调用相加的接口 -->
            function add(){
                var sum = MyJavascriptInterface.add(1, 11);
                document.getElementById("div1").innerText = "1 + 11 = " + sum;
            }
            <!-- 被android调用的js -->
            function androidCall(){
                return "hello android";
            }
        </script>
        <body>
            <h4 id="title"></h4>
            <div id = "div1">1+11=?</div>
            <div ><a href="javascript:void" onclick="add()">执行运算</a></div>
        </body>
    </html>
    
    • java中的全部代码
    public class _4_3_Activity extends BaseActivity {
    
        private WebView mWebView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_4_webview);
            mWebView = (WebView) findViewById(R.id.webView);
            //注入Javascript接口 addJavascriptInterFace(注入对象实例,注入对象的名字)
            mWebView.addJavascriptInterface(new MyJavascriptInterface(),"MyJavascriptInterface");
            //开启javascript
            mWebView.getSettings().setJavaScriptEnabled(true);
            mWebView.loadUrl("file:///android_asset/_4_3_add_interface.html");
        }
    
        /**
         * 需要注入的类
         * 注入范围:
         *          api17一下注入所有Public Method
         *          api17以上 @JavascriptInterface注释的
         */
        private class MyJavascriptInterface {
    
            @JavascriptInterface
            public String initTitle(){
                return getTitle().toString();
            }
            @JavascriptInterface
            public int add(int x, int y) {
                return x + y;
            }
        }
    
        @Override
        public void onBackPressed() {
            //在按下返回键的时候java调用js
            mWebView.evaluateJavascript("androidCall()", new ValueCallback<String>() {
                @Override
                public void onReceiveValue(String value) {
                    Toast.makeText(_4_3_Activity.this, value, Toast.LENGTH_SHORT).show();
                }
            });
            super.onBackPressed();
        }
    }
    

    4.实战之 浏览器

    实战之 浏览器.gif
    • 布局文件activity_4_webview.xml
    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="48dp">
    
            <EditText
                android:id="@+id/etInput"
                android:layout_width="match_parent"
                android:text="http://m.youdao.com/"
                android:hint="输入网址"
                android:layout_height="wrap_content"
                android:inputType="textNoSuggestions" />
        </android.support.v7.widget.Toolbar>
    
        <ProgressBar
            android:id="@+id/progressBar"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="match_parent"
            android:layout_height="3dp"
            android:layout_below="@id/toolbar"
            android:visibility="gone"
            android:background="@android:color/white"/>
    
        <WebView
            android:id="@+id/webView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/progressBar" />
    
    </RelativeLayout>
    
    • 新建一个menu文件_4_4_menu.xml
    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
        <item
            android:id="@+id/menu_go"
            android:title="前往"
            app:showAsAction="always" />
        <item
            android:id="@+id/menu_refresh"
            android:title="刷新"
            app:showAsAction="never" />
        <item
            android:id="@+id/back"
            android:title="后退"
            app:showAsAction="never" />
    
        <item
            android:id="@+id/forward"
            android:title="前进"
            app:showAsAction="never" />
    </menu>
    
    • java代码
    public class _4_4_Activity extends AppCompatActivity {
    
        private Toolbar mToolbar;
        private WebView mWebView;
        private EditText mInputEdit;
        private ProgressBar mProgressBar;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_4_4);
            mToolbar = (Toolbar) findViewById(R.id.toolbar);
            //设置菜单
            mToolbar.inflateMenu(R.menu._4_4_menu);
            //设置菜单监听
            mToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    switch (item.getItemId()) {
                        case R.id.menu_go:
                            String url = mInputEdit.getText().toString().trim();
                            mWebView.loadUrl(url);
                            break;
                        case R.id.menu_refresh:
                            mWebView.reload();
                            break;
                        case R.id.back:
                            mWebView.goBack();
                            break;
                        case R.id.forward:
                            //goBackOrFprward 负数back 正数
                            mWebView.goForward();
                            break;
                    }
                    return true;
                }
            });
            //菜单设置回调函数
            mToolbar.setMenuCallbacks(new MenuPresenter.Callback() {
                @Override
                public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
    
                }
    
                @Override
                public boolean onOpenSubMenu(MenuBuilder subMenu) {
                    //webView可以回退才显示回退
                    mToolbar.getMenu().findItem(R.id.back).setEnabled(mWebView.canGoBack());
                    //webView可以前进才显示前进
                    mToolbar.getMenu().findItem(R.id.forward).setEnabled(mWebView.canGoForward());
                    return false;
                }
            }, null);
    
            mWebView = (WebView) findViewById(R.id.webView);
            mInputEdit = (EditText) findViewById(R.id.etInput);
            mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
            mWebView.setWebViewClient(new WebViewClient(){
                @Override
                public boolean shouldOverrideUrlLoading(WebView view, String url) {
                    Uri uri = Uri.parse(url);
                    return !uri.getScheme().toLowerCase().startsWith("http");
                }
    
                //开始加载
                @Override
                public void onPageStarted(WebView view, String url, Bitmap favicon) {
                    super.onPageStarted(view, url, favicon);
                    //显示进度条
                    mProgressBar.setVisibility(View.VISIBLE);
                }
    
                //加载结束
                @Override
                public void onPageFinished(WebView view, String url) {
                    super.onPageFinished(view, url);
                    //隐藏进度条
                    mProgressBar.setVisibility(View.GONE);
                }
            });
            mWebView.setWebChromeClient(new WebChromeClient(){
                //加载中
                @Override
                public void onProgressChanged(WebView view, int newProgress) {
                    super.onProgressChanged(view, newProgress);
                    //显示进度
                    mProgressBar.setProgress(newProgress);
                }
            });
            //设置下载监听
            mWebView.setDownloadListener(new DownloadListener() {
                @Override
                public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
                    //交给系统去处理
                    Intent intent = new Intent(Intent.ACTION_VIEW);
                    intent.setData(Uri.parse(url));
                    startActivity(intent);
                }
            });
    
            WebSettings settings = mWebView.getSettings();
            settings.setJavaScriptEnabled(true);
            settings.setUseWideViewPort(true);
            settings.setSupportZoom(true);
            settings.setBuiltInZoomControls(true);
            settings.setDisplayZoomControls(false);
            settings.setCacheMode(WebSettings.LOAD_DEFAULT);
            settings.setLoadWithOverviewMode(true);
            //cookie 服务器存储在终端的数据 这里不缓存cookie
            CookieManager cookieManager = CookieManager.getInstance();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                cookieManager.removeAllCookies(null);
            } else {
                cookieManager.removeAllCookie();
            }
        }
    
        @Override
        public void onBackPressed() {
            if (mWebView.canGoBack()) {
                mWebView.goBack();
            } else {
                super.onBackPressed();
            }
        }
    }
    
    该系列已经出来好几期,这一期开始将在原本枯燥的文字文章中加入gif图片的演示效果,不知道这种形式的文章需要的朋友们会不会喜欢这种风格的文章,或者有那些可以改良的地方,感谢提出。

    apk下载地址

    相关文章

      网友评论

      本文标题:4.混合开发必学的WebView

      本文链接:https://www.haomeiwen.com/subject/qmvsbttx.html