Android里面有很多页面,是可以用网页来写的,通过我们学习的web,写成html网页,来充当安卓中的一个页面,其实在我们很多应用程序里都用到了WebView,例如我们的公众号,小程序,很多的页面都不是用安卓来写的,其实是加载了一个网页。
1.Android WebView在Android平台 上是一个特殊的View, 它能用来显示网页,这个WebView类可以被用来在app中仅仅显示一张在线的网页,当然还可以用来开发浏览器。
2.WebView内部实现是采用渲染引擎(WebKit)来展示view的内容,提供网页前进后退、网页放大、缩小、搜索等功能。
3.WebView是一个基于webKit引擎. 展现Web页面的控件, Androi d的WebView在低版本和高版本采用了不同的webKit版本内核。
4.Android的Webview在低版本和高版本采用了不同的webkit版本内核, 4.4后直接使用了Chrome.
WebView的优处
1.节省工作量,节约人力成本
打个比方,假设我们要写一个登录功能,对于不同系统ios和Android的话就要写两种登录方式,但是通过写一个网页然后再用webview来加载的话就只需要写一个登录界面,也就是说减少了一半的工作量
2.开发的内容可以动态修改
我们用安卓写的应用程序,安装在用户手机以后,那些控件就不能进行修改了,除非更新重新安装新的版本应用程序,但是我们的WebView,只需要修改网页上的内容,用户在下一次加载就可以更新页面内容,就例如我们在腾讯新闻,每天可以在同一个控件里却可以看到不同的新闻,
WebView的缺处
1.web网页的写法比安卓的写法慢(大概慢30%)
在mainifests里添加权限代码
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
在 布局文件中添加WebView控件 我们看这样一个例子 我们可以发现,我们的应用程序并没有加载网页,而是调用了系统的浏览器去加载这个网页 解决方法:我们可以通过重写shouldOverrideUrlLoading这个方法来使网页在程序内加载 这里因为是使用本地数据,所以传入的url需要做些处理,例如: 第一步,创建Assets文件夹 第三步,加载本地网页 第一步,复制之前assets文件的路径(按住ctrl+左键进入文件位置) 为什么要这样添加?因为复制粘贴没用,我试了嘿嘿 第三步,加载网页 我们用的比较多的本地加载页面通常是第二种方法,因为第一种方法会随着我们的apk一起打包给用户,而第二种方法是只有用户需要使用时,才会远程的去下载这个网页文件,所以比起第一种方法可以节省应用程序apk的内存大小 第一步,布局文件中添加按钮
该类作用:处理各种通知 & 请求事件 常见方法 onPageStarted(WebView view, String url, Bitmap favicon):WebView 开始加载页面时回调,一次Frame加载对应一次回调。 onPageFinished(WebView view, String url):WebView 完成加载页面时回调,一次Frame加载对应一次回 调。 onLoadResource(WebView view, String url):WebView 加载页面资源时会回调,每一个资源产生的一次网络加载,除非本地有当前 url 对应有缓存,否则就会加载。 shouldInterceptRequest(WebView view, String url):WebView 可以拦截某一次的 request 来返回我们自己加载的数据,这个方法在后面缓存会有很大作用。 shouldOverrideUrlLoading(WebView view, String url):是否在 WebView 内加载页面 onReceivedSslError(WebView view, SslErrorHandler handler, SslError error):WebView ssl onReceivedError(WebView view, int errorCode, String description, String failingUrl):WebView 访问 url 出错 这里重点讲下这几种方法 –所有加载的页面都会经过这个方法–可以用来拦截加载的网页 该类作用:辅助 WebView 处理 Javascript 的对话框,网站图标,网站标题等 常用方法 我们先添加一下新网页, 修改加载网页代码 运行 在监听方法中加入代码 ok 因为知识讲了挺多的,为了更好的消化,.本讲关于WebView的知识就先讲到这里啦,谢谢您的阅读,下一讲讲WebView的高级用法 android:usesCleartextTraffic="true"
第二步,添加控件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
第三步,获取网页
1.加载远程网页
1.一般网页
public class MainActivity extends AppCompatActivity {
WebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView=findViewById(R.id.webview);
mWebView.loadUrl("https://me.csdn.net/qq_46526828");
}
}
2.特殊网页(会调用系统浏览器)
public class MainActivity extends AppCompatActivity {
WebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView=findViewById(R.id.webview);
mWebView.loadUrl("http://jd.com");
mWebView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
}
}
2.加载本地网页
a.如果html文件存于assets:则加前缀:file:///android_asset/
b.如果html文件存于data/data/包名目录:则加前缀:file:///data/data/包名/1.assets目录
第二步,创建 test.html 页面文件
编写网页<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">//自适应屏幕
<title>Document</title>
</head>
<body>
<h1>标题1</h1>
<h2>标题2</h2>
<div>div content</div>
</body>
</html>
public class MainActivity extends AppCompatActivity {
WebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView=findViewById(R.id.webview);
mWebView.loadUrl("file:///android_asset/test.html");
}
}
2.data/data/包名目录
第二步,将文件上传到data/data/包名 目录
public class MainActivity extends AppCompatActivity {
WebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWebView=findViewById(R.id.webview);
mWebView.loadUrl("file:///data/data/com.c201801020224.myapplication/test.html");
}
}
3.WebView的进阶用法
1.前进返回按钮的实现
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
android:layout_marginLeft="10dp"
android:text="返回"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="10dp"/>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginRight="10dp"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="10dp"
android:text="前进"/>
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Button button=findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mWebView.goBack();//返回
}
});
Button button2=findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mWebView.goForward();//前进
}
});
mWebView.goBack();//跳到上个页面
mWebView.goForward();//跳到下个页面
mWebView.canGoBack();//是否可以跳到上一页(如果返回false,说明已经是第一页)
mWebView.canGoForward();//是否可以跳到下一页(如果返回false,说明已经是最后一页)
//以当前的index为起始点前进或者后退到历史记录中指定的steps
//如果steps为负数则为后退,正数则为前进
// mWebView.goBackOrForward(3);
// mWebView.goBackOrForward(-3);
mWebView.goBackOrForward(intsteps);
//重新加载当前请求
mWebView.reload();
2.清除缓存
//清除网页访问留下的缓存
//由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序.
mWebView.clearCache(true);
//清除当前webview访问的历史记录
//只会webview访问历史记录里的所有记录除了当前访问记录
mWebView.clearHistory();
//这个api仅仅清除自动完成填充的表单数据,并不会清除WebView存储到本地的数据
mWebView.clearFormData();
3.网页自适应屏幕,缩放
子类1-WebSettings类
WebSettings webSettings = mWebView.getSettings();
//如果访问的页面中要与Javascript交互,则webview必须设置支持Javascript
webSettings.setJavaScriptEnabled(true);//js开关默认不打开,网页中的所有js方法就无法执行,如果我们把这个方法设置为ture,网页中搞得js方法才可以执行
//设置自适应屏幕
webSettings.setUseWideViewPort(true); //将图片调整到适合webview的大小
webSettings.setLoadWithOverviewMode(false); // 缩放至屏幕的大小
//缩放操作
webSettings.setSupportZoom(false); //支持缩放,默认为true。是下面那个的前提。
webSettings.setBuiltInZoomControls(true); //设置内置的缩放控件。若为false,则该WebView不可缩放
webSettings.setDisplayZoomControls(false); //隐藏原生的缩放控件
//其他细节操作
//缓存模式如下:
//LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
//LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
//LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
//LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //webview缓存设置
webSettings.setAllowFileAccess(true); //设置可以访问文件
webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持通过JS打开新窗口
webSettings.setLoadsImagesAutomatically(true); //支持自动加载图片
webSettings.setDefaultTextEncodingName("utf-8");//设置编码格式
4.WebView的子类
1.子类1-WebSettings类
2.子类2-WebViewClient类
访问证书出错,handler.cancel()取消加载,handler.proceed()对然错误也继续加载。
1.onPageStarted和onPageFinished方法
–用于监控网页的开始和结束–可以适用于加载网页时的进度条
3.onReceivedError
–可以检测到加载异常的网络–从而可以返回一个我们自定义写好的错误界面,对用户体验会好很多
因为我的模拟器版本偏低,所以这里我用的旧版本写法
这里补充一下,新旧版本都兼容的写法: // 旧版本,会在新版本中也可能被调用,所以加上一个判断,防止重复显示
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
return;
}
// 在这里显示自定义错误页
}
// 新版本,只会在Android6及以上调用
@TargetApi(Build.VERSION_CODES.M)
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
super.onReceivedError(view, request, error);
if (request.isForMainFrame()){ // 或者: if(request.getUrl().toString() .equals(getUrl()))
// 在这里显示自定义错误页
}
}
3.子类3-WebChromeClient类
这里面有三个不同的弹框 -prompt,alert,confirm<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebView Study</title>
<script>
function clickPrompt() {
prompt("prompt");
}
function clickAlert() {
alert("alert");
}
function clicConfirm() {
confirm("Confirm");
}
</script>
</head>
<body>
<button type="button" onclick="clickPrompt()">Prompt调用</button>
<button type="button" onclick="clickAlert()">Alert调用</button>
<button type="button" onclick="clicConfirm()">Confirm调用</button>
</body>
</html>
mWebView.loadUrl("file:///android_asset/test.html");
1.对js按钮的监听
mWebView.setWebChromeClient(new WebChromeClient(){
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
Log.i("Main","------onJsAlert");
return super.onJsAlert(view, url, message, result);
}
@Override
public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
Log.i("Main","------onJsConfirm");
return super.onJsConfirm(view, url, message, result);
}
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
Log.i("Main","------onJsPrompt");
return super.onJsPrompt(view, url, message, defaultValue, result);
}
});
2.在js中自定义安卓弹框
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this)
.setIcon(R.mipmap.ic_launcher)
.setTitle("title")
.setMessage("message")
.setPositiveButton("确定",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Toast.makeText(MainActivity.this, "确定按钮", Toast.LENGTH_LONG).show();
}
}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Toast.makeText(MainActivity.this, "关闭按钮", Toast.LENGTH_LONG).show();
dialogInterface.dismiss();
}
});
builder.create().show();
return true;//屏蔽默认的js弹框
Android入门第八讲02-WebView的高级用法(Android调用 JS 代码( loadUrl 方法,案例练习),JS调用 Android 代码,流行框架总结,跨平台技术)