WebView极简用法

关键类

  • 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.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • WebView·开车指南 目录 WebView简介 WebView基本使用 WebView常用方法 WebSett...
    小庄bb阅读 3,486评论 3 25
  • Tips 由于WebView的用法实在太多,如果您只是想查询某个功能的使用——建议Ctrl+F(Commad+F)...
    BugDev阅读 7,736评论 11 109
  • WebView·开车指南 目录 WebView简介 WebView基本使用 WebView常用方法 WebSett...
    南城的人阅读 4,739评论 0 19
  • WebView·开车指南 2016-08-31BugDev 北京市东城区首席Bug布道师开山之作,一整月交通事故血...
    53c021c38a1d阅读 825评论 0 1
  • 我有一个朋友,本来打算在一桥江边的某小区买房子,过去看了楼盘。架不住推销员口吐莲花,先给人家交了5万定金。后来,他...
    Rabbit622阅读 398评论 7 2