您的位置:首页 > 移动开发

Android 内置浏览器之webview

2017-02-22 13:20 357 查看

目录:

1.webview概述
2.webview常用方法
3.webview基本使用

3.1 真的基本使用(还有假的吗?白眼)

3.2 cookie处理

3.3 缓存处理

3.4 页面导航处理

3.5 缩放与窗口管理
4.webview相关类介绍

4.1 相关类思维导图

4.2 webSettings

4.3 WebViewClient

4.4 WebChromeClient
5.webview与javascript
6.webview加载URL或本地网页

1.webview概述

webview是SDK中封装的一款基于webkit内核(后面开始基于Chromium内核)的浏览器组件,通过它我们可以实现网页的展示,实现某些实时性强的内容的更新,现在流行的混合型移动端其实最大一点好处就是可以实现热更新,webview其实也有那么一点意味在里面。

2.webview常用方法

//后退到上一页面

webView.goBack();

//前进到下一页面

webView.goForward();

//前进或者后退指定的页面数

webView.goBackOrForward(2);

//滑动到页面顶端

webView.pageUp(true);

//滑动到页面底端

webView.pageDown(true);


//以当前的页面为基准,判断是否webview的历史记录可以实现前进和后退指定的页数,正数向前,负数向后

webView.canGoBackOrForward(-2);

//判断webview的历史记录是否还可以实现回退

webView.canGoBack();

//判断webview的历史记录里面还可以实现向前

webView.canGoForward();


//清空网页的缓存数据,true表示全清空,false表示只清空内存资源缓存,不清空磁盘里面的

webView.clearCache(true);

//清除访问历史记录

webView.clearHistory();

//清空当前表单域中的表单数据

webView.clearFormData();


//加载指定网页

webView.loadUrl("https://www.baidu.com");

//获取当前页面的URL

webView.getUrl();

//重新加载当前的URL

webView.reload();

[/code]

3.webview基本使用

3.1 真的基本使用(还有假的吗?白眼)

我们先实现一个webview的简单使用,不添加任何添加剂,纯天然的webview~~~
(1)布局文件activity_main.xml

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout

xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

android:paddingBottom="@dimen/activity_vertical_margin"

tools:context="com.example.webview.MainActivity">


<WebView

android:id="@+id/webView"

android:layout_width="match_parent"

android:layout_height="match_parent">


</WebView>

</RelativeLayout>

[/code]

(2)Java文件实现绑定并加载一个简单的网页

package com.example.webview;


import android.os.Bundle;

import android.support.v7.app.AppCompatActivity;

import android.webkit.WebView;


public class MainActivity extends AppCompatActivity {

private WebView webView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);


webView= (WebView) findViewById(R.id.webView);


//加载指定网页

webView.loadUrl("https://www.baidu.com");

}

}

[/code]

(3)别忘了manifest.xml添加网络访问权限

<!--添加网络访问权限-->

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

[/code]

ok,纯天然webview制作完成,看看效果先





妈蛋,说好的内置呢,跟说好的不一样啊,为毛是调用系统的浏览器?好吧,看来的继续研究研究。
3.2 cookie处理
(1)cookie概述

在webview中设置cookie的主要作用是方便我们的native部分与我们的H5部分实现某些信息的同步,比如某个需要登录的应用,当你在native部分登录

但是某些操作需要在H5部分进行,这时候cookie同步就可以派上用场了。

(2)cookie同步的实现

(2.1)native部分从服务端获取发送给H5端,然后H5端通过ajax(异步JS和xml)接收,这里设计ajax交互我也不是很懂就不多做讲解

(2.2)将本地的cookie数据直接同步到webview中

webview的cookie保存在data/data/包名/databases/webviewCookiesChromium.db(我的Android模拟器版本是4.3的,之前的版本应该会有不一样)下面
当webview需要加载URL的时候就将这个数据库保存的对应的cookie同步上去,再与服务器交互的。

(2.3)cookie同步类CookieManager/CookieSyncManager

URL url=null;

URLConnection conn= null;

String cookie=null;

try {

url=new URL("http://www.baidu.com");

//定义访问URLConnection请求

conn = url.openConnection();

//URLConnection获取响应头中的cookie信息

cookie = conn.getHeaderField("Set-Cookie");

} catch (Exception e) {

e.printStackTrace();

}

//httpClient获取cookie

// List Cookies = httpClient.getCookieStore().getCookies();


//判斷API版本是否小于21,小于21版本的需要CookieSyncManager来进行同步

if (Build.VERSION.SDK_INT<Build.VERSION_CODES.LOLLIPOP){

CookieSyncManager syncManager=CookieSyncManager.createInstance(this);

//更新cookie操作

//啓動同步,在更新cookie后同步时调用

syncManager.sync();

}

//獲取有一个cookieManager实例

CookieManager cookieManager = CookieManager.getInstance();

//同步cookie  setCookie(String url, String value)

cookieManager.setCookie("http://www.baidu.com",cookie);

[/code]

3.3 缓存处理
(1)缓存的应用概述

缓存的应用场景主要在一些需要频繁更新的的内容类APP,例如:资讯类,新闻类,阅读类,大多这类APP都有在没网的情况下阅读的需求
而缓存的应用恰好就在这里,它可以实现在有网的时候提前缓存你的网页内容,当你在没网的情况下,打开时它通过加载缓存中的内容展示给你,从
而实现离线缓存。

(2)缓存分类





(3)缓存处理的方式

LOAD_CACHE_ONLY//不使用网络只读取本地缓存数据

LOAD_DEFAULT//根据cache-control决定是否从网络获取

LOAD_CACHE_NORMAL//API 17以后弃用

LOAD_NO_CACHE//从网络获取

LOAD_CACHE_ELSE_NETWORK//如果有本地缓存则从本地获取,如果没有则从网络获取

[/code]

(4)缓存与删除缓存案例
--1.MainActivity.java

package com.example.webview;


import android.os.Bundle;

import android.support.v7.app.AppCompatActivity;

import android.view.View;

import android.webkit.WebSettings;

import android.webkit.WebView;

import android.webkit.WebViewClient;

import android.widget.Button;


public class MainActivity extends AppCompatActivity {

private WebView webView;

private Button clearCacheBt;

private static final String url="http://36kr.com/";

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);


webView= (WebView) findViewById(R.id.webView);

clearCacheBt= (Button) findViewById(R.id.clear_cache);


//加载链接页面

webView.loadUrl(url);

//重写WebViewClient的shouldOverrideUrlLoading方法,实现在webview内加载网页

final WebViewClient webViewClient = new WebViewClient(){

@Override

public boolean shouldOverrideUrlLoading(WebView view,String url){

view.loadUrl(url);

return true;

}

};

webView.setWebViewClient(webViewClient);

//获取WebSettings对象

WebSettings settings=webView.getSettings();

//设置支持js
settings.setJavaScriptEnabled(true);
//设置缓存使用方式为优先加载本地缓存

settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);

//开启DOM存储API功能

settings.setDomStorageEnabled(true);

//开启数据库存储API功能

settings.setDatabaseEnabled(true);

//构造缓存路径

String cacheDirPath=getFilesDir().getAbsolutePath()+"/webcache/";


//设置数据库缓存路径

settings.setAppCacheEnabled(true);

settings.setAppCachePath(cacheDirPath);


clearCacheBt.setOnClickListener(new View.OnClickListener() {

@Override

    public void onClick(View v) {

webView.clearCache(true);

}

});


}


@Override

public void onBackPressed(){

if (webView.canGoBack()){

    webView.goBack();

}else {

    super.onBackPressed();

}

}

}

[/code]

--2.activity_main.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

tools:context="com.example.webview.MainActivity">


<WebView

android:id="@+id/webView"

android:layout_width="match_parent"

android:layout_weight="1"

android:layout_height="0dp">

</WebView>

<LinearLayout

android:layout_width="match_parent"

android:layout_height="wrap_content">

<Button

    android:id="@+id/clear_cache"

    android:text="清除缓存"

android:layout_width="match_parent"

    android:layout_height="wrap_content" />

</LinearLayout>

</LinearLayout>

[/code]

-- 3.假巴意思截个图,前一个是访问后断开网路再次访问的结果,后一个是点击清除缓存后的结果









3.4 页面导航处理
前面有列出webview中实现页面向前向后的方法,如下

//后退到上一页面

webView.goBack();

//前进到下一页面

webView.goForward();

//前进或者后退指定的页面数

webView.goBackOrForward(2);

//滑动到页面顶端

webView.pageUp(true);

//滑动到页面底端

webView.pageDown(true);

[/code]

但是webview并不是默认支持的,有时候如果我们不设置back键的效果,当我们按back键的时候,我们的webview浏览器会直接退掉,并不会达到我们想象的点击back键后,网页会回到我们浏览的页面的效果,要达到这样的效果我们需要设置一下,代码如下:

/*

* 重写按键操作处理方法

**/

@Override

public boolean onKeyDown(int keyCode, KeyEvent event){

//如果为按下back键操作并且webview能返回前一页,则设置返回

if ((keyCode==KeyEvent.KEYCODE_BACK)&&webView.canGoBack()){

    webView.goBack();

    return true;

}

return super.onKeyDown(keyCode,event);

}

[/code]

3.5 缩放与窗口管理
通常我们会有两种需求:1.加载页面可缩放;2.加载页面屏幕自适应且不可缩放

1.加载页面可缩放

//设置适应屏幕

settings.setUseWideViewPort(true);

settings.setLoadWithOverviewMode(true);

//设置缩放

settings.setSupportZoom(true);

//显示缩放控件

settings.setDisplayZoomControls(true);

[/code]

2.加载页面屏幕自适应且不可缩放

在加载的资源HTML页面中加入如下代码:

<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">

[/code]

4.webview相关类介绍

4.1 相关类思维导图





4.2 webSettings

常用类简单总结:

//获取WebSettings对象

WebSettings settings=webView.getSettings();


//设置开启数据库存储API权限

settings.setDatabaseEnabled(true);

//设置开启DOM存储API权限

settings.setDomStorageEnabled(true);


//设置是否开启定位功能

settings.setGeolocationEnabled(true);

//设置保存地理信息数据路径

settings.setGeolocationDatabasePath("");


//设置支持屏幕播放

settings.setSupportZoom(true);

//设置是否开启内置缩放机制

settings.setBuiltInZoomControls(true);

//设置开启内置缩放机制后是否显示缩放控件

settings.setDisplayZoomControls(true);


//设置支持JS

settings.setJavaScriptEnabled(true);


//设置是否使用预览模式加载页面

settings.setLoadWithOverviewMode(true);

//设置是否很使用viewport

// false:加载页面的宽度总是使用webview

//true:由页面的viewport标签决定

settings.setUseWideViewPort(true);


settings.setAllowContentAccess(true);

//设置是否支持文件访问

settings.setAllowFileAccess(true);

settings.setAllowFileAccessFromFileURLs(true);


//设置是否开启缓存

settings.setAppCacheEnabled(true);

//设置缓存的路径

settings.setAppCachePath("/webCache/");

//设置缓存模式

settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);


//设置是否以http,https方式从网路加载图片资源

settings.setBlockNetworkImage(true);

//设置是否从网络加载资源

settings.setBlockNetworkLoads(true);


//设置是否支持保存表单数据

settings.setSaveFormData(true);


//设置webView的底层布局算法

settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);

[/code]

4.3 WebViewClient

常用类简单总结:

final WebViewClient webViewClient = new WebViewClient(){

/*

    * 设置是否交由内置的webview来处理加载页面的操作

**/

@Override

public boolean shouldOverrideUrlLoading(WebView view,String url){

view.loadUrl(url);

return true;

}

/*

    * 在webview开始加载URL时回调,方便开发者做一些操作

**/

@Override

    public void onPageStarted(WebView view, String url, Bitmap favicon) {


}

/*

    * 在加载完当前页面时的回调方法

**/

@Override

    public void onPageFinished(WebView view, String url) {

}


@Override

    public void onLoadResource(WebView view, String url) {

}

/*

    * 指定页面访问错误时的回调方法

**/

@Override

    public void onReceivedError(WebView view, int errorCode,

String description, String failingUrl) {

}

/*

    * 设置浏览器重复post提交

**/

@Override

    public void onFormResubmission(WebView view, Message dontResend,

   Message resend) {

dontResend.sendToTarget();

}

/*

    * 通知应用程序可以将此URL保存到数据库,网页加载时只是调用一次

**/

@Override

    public void doUpdateVisitedHistory(WebView view, String url,

       boolean isReload) {

}


/*

    * 设置当加载页面出现SSL错误时我们应该做的操作,cancel还是proceed

**/

@Override

    public void onReceivedSslError(WebView view, SslErrorHandler handler,

   SslError error) {

handler.proceed();

}

/*

    *收到客户端证书请求时的回调方法

**/

@Override

    public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {

//需要API 21以上

request.cancel();

}

/*

    * 在webview接收到HTTP auth请求时的回调方法

**/

@Override

    public void onReceivedHttpAuthRequest(WebView view,

  HttpAuthHandler handler, String host, String realm) {

handler.cancel();

}

/*

    * 键盘时间触发后的回调方法

    * 返回值为true,事件交由应用程序处理

    * 返回值为false,事件交由webview处理

**/

@Override

    public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event) {

return false;

}


/*

    * 作用:在view被縮放的时候的回调方法,也就是在发生缩放时间后,后续触发的动作

**/

@Override

    public void onScaleChanged(WebView view, float oldScale, float newScale) {

}

    

/*

    * 收到登陸请求时的方法回调

**/

@Override

    public void onReceivedLoginRequest(WebView view, String realm,

       String account, String args) {

}

};

[/code]

4.4 WebChromeClient

常用类简单总结:

WebChromeClient chromeClient = new WebChromeClient(){


/*

    * 接收到一个标题时的回调方法

**/

@Override

    public  void onReceivedTitle(WebView view, String title) {

Log.d("title",title);

}

/*

    * 页面加载进度改变时候的回调

**/

@Override

    public void onProgressChanged(WebView view, int newProgress) {


}

/*

    *接收到一个新的图标时的回调方法

**/

@Override

    public void onReceivedIcon(WebView view, Bitmap icon) {}


@Override

    public void onReceivedTouchIconUrl(WebView view, String url,

       boolean precomposed) {


}


/*

    * 通知主应用程序,当前页面将可能显示一个自定义的view视图

**/

@Override

    public void onShowCustomView(View view, CustomViewCallback callback) {


}

/*

    * 通知主应用程序,当前页面可能将隐藏一个自定义的view视图

    *

**/

@Override

    public void onHideCustomView() {}


/*

    * 请求主应用程序创建新窗口

    * 该方法返回true表示响应这个请求,创建一个新webview插入视图中,并将resultMsg提交给他

    * 如果不需要响应则返回false

**/

@Override

    public boolean onCreateWindow(WebView view, boolean isDialog,

  boolean isUserGesture, Message resultMsg) {

return false;

}


@Override

    public void onRequestFocus(WebView view) {}


/*

    * 通知应用程序webview已经关闭,并在需要的时候从view中移除它

**/

@Override

    public void onCloseWindow(WebView window) {}


/*

    * 通知客户端去显示一个JS 的 alert弹框,如果方法返回true,webview认为客户端需要处理

    * 如果返回false,webview内核自行处理

**/

@Override

    public boolean onJsAlert(WebView view, String url, String message,

     JsResult result) {

return false;

}

/*

    * 通知客戶端需要显示个Confirm框,如果该方法返回true表示客户端会处理,并调用合适的JsResult处理方法

    * 如果返回false,内核默认自行处理

**/

@Override

    public boolean onJsConfirm(WebView view, String url, String message,

       JsResult result) {

return false;

}

/*

    * 通知客户端展示一个Prompt弹框给用户,如果该方法返回true,webview认为客户端会处理,并调用合适的

    * JsPromptResult方法,如果返回false,内核默认自行处理

**/

@Override

    public boolean onJsPrompt(WebView view, String url, String message,

      String defaultValue, JsPromptResult result) {

return false;

}

/*

    * 通知应用程序显示一个对话框,让用户选择是否离开当前页面,如果返回true

    * 表示客户端会处理,返回false,内核自行处理

**/

@Override

    public boolean onJsBeforeUnload(WebView view, String url, String message,

    JsResult result) {

return false;

}


/*

    * 通知应用程序,web content需要请求定位,主应用程序需要调用指定的回调实现定位状态处理

**/

@Override

    public void onGeolocationPermissionsShowPrompt(String origin,

   GeolocationPermissions.Callback callback) {}



@Override

    public void onGeolocationPermissionsHidePrompt() {}


/*

    * 权限请求时候的回调

**/

@Override

    public void onPermissionRequest(PermissionRequest request) {

request.deny();

}


/*

    * 取消权限请求时的回调

**/

@Override

    public void onPermissionRequestCanceled(PermissionRequest request) {}


/*

    * 通过该方法吧JS的调试信息提交给主应用程序,方便应用程序展示调试

**/

@Override

    public boolean onConsoleMessage(ConsoleMessage consoleMessage) {

// Call the old version of this function for backwards compatability.

onConsoleMessage(consoleMessage.message(), consoleMessage.lineNumber(),

consoleMessage.sourceId());

return false;

}


/*

    * HTML中的video在没有播放的时候会有一个默认的海报页面,是由HTML的video标签的poster属性指定

    * 如果HTML未指定,我们可以通过该函数指定默认的海报图片

**/

@Override

    public Bitmap getDefaultVideoPoster() {

return null;

}


/*

    * 播放视频前会有一段时间缓存,我们可以通过该方法在数据缓存期间显示一个view

    * 优化用户体验

**/

@Override

    public View getVideoLoadingProgressView() {

return null;

}


/*

    * 获取所有访问所有访问历史项,用于链接的着色

**/

@Override

    public void getVisitedHistory(ValueCallback<String[]> callback) {

}


};

[/code]

5.webview与javascript(实现简单的JS与Android互调传参)

5.1 主布局文件

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical" android:layout_width="match_parent"

android:layout_height="match_parent">


<WebView

android:layout_width="match_parent"

android:layout_height="0dp"

android:layout_weight="1"

android:id="@+id/webView02"

android:layout_gravity="center_horizontal" />

<LinearLayout

android:layout_width="match_parent"

android:layout_height="0dp"

android:layout_weight="1"

android:orientation="vertical"

>

<TextView

    android:id="@+id/js_info"

    android:text="JS显示文本"

android:layout_width="match_parent"

    android:layout_height="0dp"

    android:layout_weight="3"

    />

<Button

    android:layout_weight="1"

    android:id="@+id/call_js"

    android:text="调用Js"

android:layout_width="match_parent"

    android:layout_height="0dp"

    />

</LinearLayout>


</LinearLayout>

[/code]

5.2 主布局Java类

package com.example.webview;


import android.annotation.SuppressLint;

import android.os.Bundle;

import android.support.v7.app.AppCompatActivity;

import android.util.Log;

import android.view.View;

import android.webkit.JavascriptInterface;

import android.webkit.WebSettings;

import android.webkit.WebView;

import android.webkit.WebViewClient;

import android.widget.Button;

import android.widget.TextView;

import android.widget.Toast;


/**

* Created by elimy on 2016-12-20.

*/

public class JsAndAndroidActivity extends AppCompatActivity {


private WebView webView;

private Button call_Js;

private TextView js_info;


@SuppressLint("SetJavaScriptEnabled")

@Override

protected void onCreate(Bundle savedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.js_android_activity);


webView= (WebView) findViewById(R.id.webView02);

call_Js= (Button) findViewById(R.id.call_js);

js_info= (TextView) findViewById(R.id.js_info);


//重写WebViewClient的shouldOverrideUrlLoading方法,实现在webview内加载网页

final WebViewClient webViewClient = new WebViewClient(){

/*

    * 设置是否交由内置的webview来处理加载页面的操作

**/

@Override

public boolean shouldOverrideUrlLoading(WebView view,String url){

view.loadUrl(url);

return true;

}

};


webView.setWebViewClient(webViewClient);


WebSettings settings = webView.getSettings();

//开启JS的支持

settings.setJavaScriptEnabled(true);

webView.addJavascriptInterface(this,"client");


//加载网页

webView.loadUrl(" file:///android_asset/androidcalljs.html ");

//设置按钮监听

call_Js.setOnClickListener(new View.OnClickListener() {

@Override

    public void onClick(View v) {

//构造传递的参数

Log.d("TAG", "onClick: ");

//調用js中的javaUseJs()方法

webView.loadUrl("javascript:javaUseJs(" + "'hello JS'"+ ")");

}

});


}


/*

* 該方法提供给webview中的JS调用

**/

@JavascriptInterface

public void androidFunc(final String str){


Log.d("js_content",str);

runOnUiThread(new Runnable() {


@Override

    public void run() {

Toast.makeText(JsAndAndroidActivity.this,str,Toast.LENGTH_LONG).show();

js_info.setText("JS说:"+str);

}

});

}

}

[/code]

5.3 HTML页面

<!DOCTYPE html>

<html>

<head>

<meta http-equiv="content-type" content="text/html" charset="utf-8">

<title>Title of the document</title>

<script type="text/javascript">

function javaUseJs(str){

    document.getElementById("content").innerHTML +=

 ("<br\>"+str);

}


function jsUseJava(str){

    client.androidFunc(str);

}

</script>

</head>

<body  bgcolor="#7171C6">

<h1 align="center">你好呀,我是Webview中的HTML哟,你点点下面的链接试试看...</h1><br/>

<a onclick="jsUseJava('hello android')"   style="align-content: center;">点我点我</a><br/>

android说:

<div id="content"></div>

</body>

</html>

[/code]

5.4 效果截图





6.webview加载URL或本地网页

6.1 webview加载assets下的网页
前面案例中有使用,首先创建assets资源文件夹(提醒:注意与src同级,否则会出错),然后通过如下代码调用:

webview.loadUrl("file:///android_asset/htmlfilename.html")

[/code]

6.2 webview加载本地sdcard网页
要实现加载sdcard html文件首先将文件文件导入sdcard路径下,再通过如下代码访问:

webView.loadUrl("file:///mnt/sdcard/localsdcard.html");

[/code]

6.3 webview直接加载服务器网页链接

webView.loadUrl("http://www.baidu.com");


[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息