WebView极简用法

作者: 墨革 | 来源:发表于2016-10-22 08:11 被阅读369次

    关键类

    • WebView
    • WebSettings
    • WebViewClient
    • WebChromeClient

    WebView基本用法:

    WebView myWebView = (WebView) findViewById(R.id.webview);
    myWebView.loadUrl("http://www.example.com");
    

    如果加载的是网络页面需要申请网络权限:

    <uses-permission android:name="android.permission.INTERNET" />
    

    补充

    • WebView还有两个方法,loadData(String data, String miniType,String edcoding)loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl).有时候loadData()只能加载‘data’,会导致其他协议的URL无法加载,当加载的URL不一定是‘data’时推荐用后一个方法。
      • mimeType: 数据类型,如:text/html.
      • encoding: 数据编码方式 base64 或者 url encoding.
      • baseUrl: 指定页面的根路径.
    • URL统一资源定位符(uniform resource locator),URI统一资源标识符(uniform resource identifier )。URI包括URL。URL的一般语法scheme:[//[user:password@]host[:port]][/]path[?query][#fragment]

    配置WebView

    配置WebView,需要先获得一个WebSettings对象。WebSettings对象并不是通过new来获得,而是在我们创建WebView的时候,就会获得一个默认的WebSettings对象。这个WebSetting对象可以通过myWebView.getSettings()来获得。

    WebSettings webSettings = myWebView.getSettings();
    webSettings.setJavaScriptEnabled(true);
    

    当我们通过WebView来加载了一个页面时,点击页面上的链接时,会弹出一个对话框,让我们选择通过哪个浏览器来打开,如果我们希望直接在自己的WebView中打开,就可以通过如下方法实现:

    myWebView.setWebViewClient(new WebViewClient());  
    

    WebView拦截资源请求

    有时候我们不希望自己的WebView处理相关的请求,例如页面中具有发邮件,打电话,发消息这类链接的时候,我们希望用户点击之后会启动第三方应用,而不是我们自己的WebView处理,就可以通过如下方式实现。

    首先我将一个html文档放在了main/assets目录下,注意不是res/目录下。模拟一个网页。html文档如下:

    <!DOCTYPE html>
    <html>
    <head>
        <title>WebView Test</title>
        <!--下面前两个方法通过javascript调用WebView中的java代码-->
        <!--第三个方法,就是简单的javascript代码,在网页打开,会有一个警告对话框-->
        <script type="text/javascript">
            var new_activity = function(){
                android.newActivity();
            }
    
            var send_notification = function(){
                android.sendNotification();
            }
    
             window.onload = function(){
                alert("alert from javascript");
            }
        </script>
    </head>
    <body>
    <p><a href="mailto: study@163.com">send email</a></p>
    <p><a href="tel: 12312312312">call</a></p>
    <p><a href="sms: 10086">send message</a></p>
    <!--两个绑定点击事件的按钮-->
    <button onclick="new_activity()">new activity</button>
    <button onclick="send_notification()">send notification</button>
    </body>
    </html>
    

    在java代码中重写WebViewClient的shouldOverrideUrlLoading(WebView view, String url)方法,该方法返回true,表示重写了该方法,这次请求不由自己的WebView处理,会调用第三方应用。

    // 注意url的写法。
    String url = "file:///android_asset/index_test.html";
    myWebView.setWebViewClient(new WebViewClient(){
        @Override
          public boolean shouldOverrideUrlLoading(WebView view, String url) {
             Uri uri = Uri.parse(url);
             if ("mailto".equalsIgnoreCase(uri.getScheme())
                  ||"tel".equalsIgnoreCase(uri.getScheme())
                  ||"sms".equalsIgnoreCase(uri.getScheme())){
              //注意这里Intent Action的写法。      
              Intent intent=new Intent(Intent.ACTION_VIEW, uri);
              startActivity( intent);
              return true;
              }
            return false;
          }
    });
    myWebView.loadUrl(url);
    

    补充

    • 当我们想要屏蔽掉网页的某些资源的时候,需要重写WebViewClient的shouldIntercepterRequest()方法,而重写shouldOverrideUrlLoading是没有效果的。因为网页的资源是在"IO"线程里加载的,而shouldOverrideUrlLoading运行在主线程,只能拦截新的URL对象,也就是页面需要重写加载的时候,才会回调。而shouldIntercepterRequest方法运行在IO线程里,可以对资源请求进行拦截,并且可以返回其他的资源。
    • 禁止加载图片
      webSettings.setLoadsImagesAutomatically(false)
    • 当页面载入错误时,可以重写WebViewClientonReceivedError()方法。

    JavaScript和WebView的交互

    Jave调用Javascript

    直接调用
    myWebView.loadUrl("javascript:alert(java to javascript)");  
    

    补充
    也可以通过evaluateJavascript方法来处理带有返回值的js方法。

    通过重载WebChromeClient调用

    注意上面的Html代码,当页面加载时会有一个弹出对话框。虽然已给WebView设置里setJavaScriptEnabled(true),但是WebView依然无法显示对话框。通过如下方法就可使对话框显示。

    myWebView.setWebChromeClient(new WebChromeClient());
    

    那么WebChromeClientWebViewClient有什么不同呢?前者主要负责辅助处理JS,与页面内容交互。后者主要负责页面加载过程中的事件通知。

    如果你觉得这个弹窗实在太难看了,我们可以通过如下方法,重新自定义:

    myWebView.setWebChromeClient(new WebChromeClient(){
        @Override
        public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
        Toast.makeText(MainActivity.this,message,Toast.LENGTH_SHORT).show();
        result.confirm();
        return true;
        }
    });
    

    Javascript调用java

    主要是通过addJavascriptInterface(Object object,String name),向Javascript中注入对象和对象的名字。在api17以下会注入所有public方法,api17以上只会注入添加了@JavascriptInterface注释的方法。

    首先我们创建一个类,如下:

    public class WebAppInterface {
        private Context mContext;
        private final static int NOTIFICATION_ID = 1;
    
        public WebAppInterface(Context c) {
            mContext = c;
        }
    // 对应html第一个方法
        @JavascriptInterface
        public void newActivity(){
            Intent intent = new Intent(mContext,JSActivity.class);
            mContext.startActivity(intent);
        }
    // 对应html中第二个方法
        @JavascriptInterface
        public void sendNotification(){
            Notification notification = new NotificationCompat.Builder(mContext)
                    .setContentTitle("hello")
                    .setContentText("this notification is sent by js")
                    .setSmallIcon(R.drawable.notification_icon)
                    .setAutoCancel(true)
                    .setDefaults(Notification.DEFAULT_ALL)
                    .build();
            NotificationManager manager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
            manager.notify(NOTIFICATION_ID,notification);
        }
    }
    

    然后为WebView添加这个js接口

    myWebView.addJavascriptInterface(new WebAppInterface(mContext),"android");  
    

    之后就可以通过js调用上面设置的两个方法了。详细信息请参考上面的html文件。

    WebView小拓展

    如果我们不希望用户点击了WebView中的链接跳转之后,按下返回键直接退出应用,可以在Activity中重写onBackPress方法

    @Override
        public void onBackPressed() {
            if (myWebView.canGoBack()){
                myWebView.goBack();
            }else {
                super.onBackPressed();
            }
        }     
    

    WebView调试技巧

    添加如下代码

    if (Build.VERSION.SDK_INT >=Build.VERSION_CODES.KITKAT && BuildConfig.DEBUG){
       myWebView.setWebContentsDebuggingEnabled(true);
    }
    

    在chrome浏览器中输入chrome//inspect/#devices.

    相关文章

      网友评论

      • Carson带你学安卓:来看我写的webview.很全很详细
        墨革:@Carson_Ho 可以看看,确实很详细。
        http://www.jianshu.com/p/3c94ae673e2a

      本文标题: WebView极简用法

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