安卓APP承載網頁(WebView)- 用例程解析到位

東小東發表於2020-05-14

安卓APP自身如何開啟網頁,如何製作一個簡單的瀏覽器,WebView在其中將是一個重要的角色。WebView是一個基於WebKit引擎、展現Web頁面的控制元件。

Webview 是一個基於webkit引擎,可以解析DOM 元素,展示html頁面的控制元件,它和瀏覽器展示頁面的原理是相同的,所以可以把它當做瀏覽器看待。(chrome瀏覽器也是基於webkit引擎開發的,Mozilla瀏覽器是基於Gecko引擎開發的)

簡而言之,WebView可以實現安卓APP中承載網頁

 

手機瀏覽器:

國內手機的自帶瀏覽器不是chrome,主要是版權的原因,自帶的瀏覽器都是手機廠商基於國內主流的幾大瀏覽器自己定製,然後釋出在自己手機系統版本中.不過國內幾大瀏覽器廠商如QQ瀏覽器,UC瀏覽器、都是基於webkit引擎的,iphone的自帶瀏覽器是Safari,Safari瀏覽器的核心是webkit

 

使用WebView的好處:

  1. 使用核心都是webkit,所以APP中網頁展示的效果與主流瀏覽器差別無幾
  2. 這是一個BS架構即瀏覽器和伺服器的,所以在某些要經常改變的介面嵌入WebView,可以方便隨時在後臺修改其內容

載入一個網頁的方法

載入伺服器的網頁

//獲取到webview控制元件
WebView webv=findViewById(R.id.mywebview);
//載入網頁
webv.loadUrl("https://www.cnblogs.com/dongxiaodong/");

載入資原始檔(assets目錄)的網頁

assets目錄是Android的一種特殊目錄,用於放置APP所需的固定檔案,且該檔案被打包到APK中時,不會被編碼到二進位制檔案。

//獲取到webview控制元件
WebView webv=findViewById(R.id.mywebview);
//載入網頁
webv.loadUrl("file:///android_asset/androidt.html");

網頁載入時附加網頁程式碼

baseUrl表示基礎的網頁

data表示要載入的內容

mimeType表示載入網頁的型別

encoding表示編碼格式

historyUrl表示可用歷史記錄,可以為null值

webv.loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl))

網頁瀏覽器的基礎屬性

canGoBack()   是否可以後退

canGoForward() 是否可以前進

canGoBackOrForward(int step) 是否可以前進或者後退多少步,正數為前進,負數為後退

goBack() 後退

goBack() 前進

goBackOrForward(int step)前進或者後退多少步,正數為前進,負數為後退

reload() 重新載入或重新整理介面

stopLoading() 停止載入

實現:

 1 //後退函式實現
 2 public void But_back(View v){
 3     //查詢是否可以返回上一級
 4     boolean canx=webv.canGoBack();
 5     //返回上一級
 6     if(canx) webv.goBack();
 7     //不可返回
 8     else  Toast.makeText(MainActivity.this,"已經到達底端",Toast.LENGTH_SHORT).show();
 9 }
10 //前進函式實現
11 public void But_forward(View v){
12     boolean canx=webv.canGoForward();
13     //返回上一級
14     //查詢是否可以返回上一級
15     if(canx) webv.goForward();
16         //不可返回
17     else  Toast.makeText(MainActivity.this,"已經到達頂端",Toast.LENGTH_SHORT).show();
18 }
19 //重新整理頁面
20 public void But_reload(View v){
21     webv.reload();
22 }
23 //停止介面載入
24 public void But_stop(View v){
25     webv.stopLoading();
26 }

WebView配置類(WebSettings)

 1 WebSettings webSettings = webView.getSettings();
 2     //如果訪問的頁面中要與Javascript互動,則webview必須設定支援Javascript
 3     webSettings.setJavaScriptEnabled(true);
 4 
 5     //設定自適應螢幕,兩者合用
 6     webSettings.setUseWideViewPort(true); //將圖片調整到適合webview的大小
 7     webSettings.setLoadWithOverviewMode(true); // 縮放至螢幕的大小
 8 
 9     webSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); //支援內容重新佈局
10 
11     //縮放操作
12     webSettings.setSupportZoom(true); //支援縮放,預設為true。是下面那個的前提。
13     webSettings.setBuiltInZoomControls(true); //設定內建的縮放控制元件。若為false,則該WebView不可縮放
14     webSettings.setDisplayZoomControls(false); //隱藏原生的縮放控制元件
15     webSettings.setTextZoom(2);//設定文字的縮放倍數,預設為 100
16 
17     webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH);  //提高渲染的優先順序
18 
19     webSettings.setStandardFontFamily("");//設定 WebView 的字型,預設字型為 "sans-serif"
20     webSettings.setDefaultFontSize(20);//設定 WebView 字型的大小,預設大小為 16
21     webSettings.setMinimumFontSize(12);//設定 WebView 支援的最小字型大小,預設為 8
22 
23     // 5.1以上預設禁止了https和http混用,以下方式是開啟
24     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
25         webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
26     }
27 
28     //其他操作
29     webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //關閉webview中快取
30     webSettings.setAllowFileAccess(true); //設定可以訪問檔案
31     webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支援通過JS開啟新視窗
32     webSettings.setLoadsImagesAutomatically(true); //支援自動載入圖片
33     webSettings.setDefaultTextEncodingName("utf-8");//設定編碼格式
34     webSettings.setGeolocationEnabled(true);//允許網頁執行定位操作
35     webSettings.setUserAgentString("Mozilla/5.0 (Windows NT 10.0; WOW64; rv:50.0) Gecko/20100101 Firefox/50.0");//設定User-Agent
36 
37 
38     //不允許訪問本地檔案(不影響assets和resources資源的載入)
39     webSettings.setAllowFileAccess(false);
40     webSettings.setAllowFileAccessFromFileURLs(false);
41     webSettings.setAllowUniversalAccessFromFileURLs(false);

事件監聽

各種通知和請求事件(WebViewClient)

onPageStarted()   頁面載入時

onPageFinished():頁面載入完畢時呼叫。

shouldOverrideKeyEvent():重寫此方法才能處理瀏覽器中的按鍵事件。

shouldInterceptRequest():頁面每一次請求資源之前都會呼叫這個方法(非UI執行緒呼叫)。

onLoadResource():頁面載入資源時呼叫,每載入一個資源(比如圖片)就呼叫一次。

onReceivedError():載入頁面的伺服器出現錯誤(比如404)時回撥。

onReceivedSslError():重寫此方法可以讓webview處理https請求。

doUpdateVisitedHistory():更新歷史記錄。

onFormResubmission():應用程式重新請求網頁資料。

onReceivedHttpAuthRequest():獲取返回資訊授權請求。

onScaleChanged():WebView發生縮放改變時呼叫。

onUnhandledKeyEvent():Key事件未被載入時呼叫。

 

輔助 WebView 處理補充問題(WebChromeClient)

onProgressChanged():獲得網頁的載入進度並顯示。

onReceivedTitle():獲得網頁的標題時回撥。

onReceivedIcon():獲得網頁的圖示時回撥。

onCreateWindow():開啟新視窗時回撥。

onCloseWindow():關閉視窗時回撥。

onJsAlert():網頁彈出提示框時觸發此方法。

上例程

統一統一步驟:

第一步:

在AndroidManifest.xml下新增網路訪問許可權,如果需要外網訪問的情況下

<!--網路許可權-->
<uses-permission android:name="android.permission.INTERNET" />
<!--檔案讀寫許可權-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

第二步:

在xml下新增WebView控制元件

<WebView
    android:layout_width="match_parent"
    android:id="@+id/mywebview"
    android:layout_height="match_parent" />

載入可伺服器的網頁:

這裡將使用WebView開啟 部落格園 東小東 的部落格首頁

 第三步:

編寫邏輯程式

 1 import androidx.appcompat.app.AppCompatActivity;
 2 import android.os.Bundle;
 3 import android.view.KeyEvent;
 4 import android.webkit.WebView;
 5 import android.webkit.WebViewClient;
 6 public class MainActivity extends AppCompatActivity {
 7     private WebView webv=null;
 8     @Override
 9     protected void onCreate(Bundle savedInstanceState) {
10         super.onCreate(savedInstanceState);
11         setContentView(R.layout.activity_main);
12         //獲取到webview控制元件
13         webv=findViewById(R.id.mywebview);
14         //設定訪問的URL,此條將會觸發系統呼叫瀏覽器開啟,部落格園東小東
15         webv.loadUrl("https://www.cnblogs.com/dongxiaodong/");
16         //通過下面的程式碼阻止APP直接通過瀏覽器開啟網頁
17         webv.setWebViewClient(new WebViewClient(){
18             @Override
19             public boolean shouldOverrideUrlLoading(WebView view, String url) {
20                 //使用WebView載入URL內容
21                 view.loadUrl(url);
22                 return  true;
23             }
24         });
25     }
26     //監聽程式的返回事件
27     public boolean onKeyDown(int keyCode, KeyEvent event) {
28         //如果按下返回鍵且網頁有歷史記錄,可以返回上一級
29         if ((keyCode == KeyEvent.KEYCODE_BACK) && webv.canGoBack()) {
30             //返回上一級
31             webv.goBack();
32             return true;
33         }
34         //否則返回真實的按鍵資訊給系統,系統將將退出程式
35         return super.onKeyDown(keyCode, event);
36     }
37 }

載入資原始檔(assets目錄)的網頁

assets目錄是Android的一種特殊目錄,用於放置APP所需的固定檔案,且該檔案被打包到APK中時,不會被編碼到二進位制檔案。

  第三步:

編寫HTML程式碼,儲存到檔案androidt.html

 1 <!doctype html>
 2 <html>
 3 <head>
 4 <meta charset="utf-8">
 5 <title>這裡是網頁頭</title>
 6 </head>
 7 <body style="margin: 0 auto;text-align: center">
 8     <h1>我是網頁標題1</h1>
 9     <h3>(資原始檔方法)</h3>
10     <button onClick="showA()" style="width: 100%;height: 100px;">點我彈框</button>
11 </body>
12     <script>
13         function showA(){
14             alert("彈框內容,完成");
15         }
16     </script>
17 </html>

第四步

建立assets目錄

右鍵【app】-【New】-【Folder】-【Assets Folder】-【finish】

第五步

將HTML檔案拷貝到assets目錄下

第六步

 1 import androidx.appcompat.app.AppCompatActivity;
 2 import android.os.Bundle;
 3 import android.webkit.JsResult;
 4 import android.webkit.WebChromeClient;
 5 import android.webkit.WebSettings;
 6 import android.webkit.WebView;
 7 import android.webkit.WebViewClient;
 8 public class MainActivity extends AppCompatActivity {
 9     @Override
10     protected void onCreate(Bundle savedInstanceState) {
11         super.onCreate(savedInstanceState);
12         setContentView(R.layout.activity_main);
13         //獲取到webview控制元件
14         WebView webv=findViewById(R.id.mywebview);
15 
16         WebSettings webSettings = webv.getSettings();
17         webSettings.setJavaScriptEnabled(true);//設定支援Javascript
18         webSettings.setJavaScriptCanOpenWindowsAutomatically(true);//允許js彈出視窗
19 
20         //訪問本地資原始檔網頁
21         webv.loadUrl("file:///android_asset/androidt.html");
22 
23         //通過下面的程式碼阻止APP直接通過瀏覽器開啟網頁
24         webv.setWebViewClient(new WebViewClient(){
25             @Override
26             public boolean shouldOverrideUrlLoading(WebView view, String url) {
27                 //使用WebView載入URL內容
28                 view.loadUrl(url);
29                 return  true;
30             }
31         });
32         //如果要實習alert彈框,必須實現此監聽事件
33         webv.setWebChromeClient(new WebChromeClient() {
34             @Override
35             public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
36                 // TODO Auto-generated method stub
37                 return super.onJsAlert(view, url, message, result);
38             }
39         });
40     }
41 }

載入部分原始碼

直接寫一部分的HTML程式碼,可以直接顯示在WebView上

 第三步:

編寫邏輯程式

 1 package com.example.myapplication;
 2 
 3 import androidx.appcompat.app.AppCompatActivity;
 4 import android.os.Bundle;
 5 import android.view.KeyEvent;
 6 import android.webkit.WebSettings;
 7 import android.webkit.WebView;
 8 import android.webkit.WebViewClient;
 9 public class MainActivity extends AppCompatActivity {
10     private WebView webv=null;
11     @Override
12     protected void onCreate(Bundle savedInstanceState) {
13         super.onCreate(savedInstanceState);
14         setContentView(R.layout.activity_main);
15         //獲取到webview控制元件
16         webv=findViewById(R.id.mywebview);
17         WebSettings webSettings = webv.getSettings();
18 
19         //將網頁介面縮放至手機螢幕大小
20         webSettings.setUseWideViewPort(true); //將圖片調整到適合webview的大小
21         webSettings.setLoadWithOverviewMode(true); // 縮放至螢幕的大小
22 
23         //設定支援縮放操作
24         webSettings.setSupportZoom(true); //支援縮放,預設為true。是下面那個的前提。
25         webSettings.setBuiltInZoomControls(true); //設定內建的縮放控制元件。若為false,則該WebView不可縮放
26         webSettings.setDisplayZoomControls(false); //隱藏原生的縮放控制元件
27 
28         //編輯網頁程式碼
29         String myhtml="<h1 >東小東標題</h1>" +
30                       "<hr/>" +
31                       "<a href='https://www.cnblogs.com/dongxiaodong/'>去東小東部落格園看看<a/>" +
32                       "<h3 >網頁顯示小標題</h3>" +
33                       "<img style=\"width: 100%;\" src=\"https://img2018.cnblogs.com/blog/1485202/201811/1485202-20181116215233782-319594948.png\"/>";
34         //設定顯示
35         webv.loadDataWithBaseURL("",myhtml,"text/html", "utf-8",null);
36 
37         //通過下面的程式碼阻止APP直接通過瀏覽器開啟網頁
38         webv.setWebViewClient(new WebViewClient(){
39             @Override
40             public boolean shouldOverrideUrlLoading(WebView view, String url) {
41                 //使用WebView載入URL內容
42                 view.loadUrl(url);
43                 return  true;
44             }
45         });
46     }
47     //監聽程式的返回事件
48     public boolean onKeyDown(int keyCode, KeyEvent event) {
49         //如果按下返回鍵且網頁有歷史記錄,可以返回上一級
50         if ((keyCode == KeyEvent.KEYCODE_BACK) && webv.canGoBack()) {
51             //返回上一級
52             webv.goBack();
53             return true;
54         }
55         //否則返回真實的按鍵資訊給系統,系統將將退出程式
56         return super.onKeyDown(keyCode, event);
57     }
58 }

綜合案例

缺點:工程未實現網頁的音訊和視訊播放

實現功能:

l  標題顯示

l  網頁載入進度條顯示

l  後退、前進、重新整理、停止載入四大常用功能適配

l  連線跳轉,在APP本地開啟網頁

 

 

檢視原始碼

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:app="http://schemas.android.com/apk/res-auto"
 4     xmlns:tools="http://schemas.android.com/tools"
 5     android:layout_width="match_parent"
 6     android:layout_height="match_parent"
 7     tools:context=".MainActivity">
 8     <LinearLayout
 9         android:layout_width="match_parent"
10         android:layout_height="match_parent"
11         android:orientation="vertical">
12 
13      <TextView
14          android:layout_width="match_parent"
15          android:layout_height="wrap_content"
16          android:textSize="15dp"
17          android:id="@+id/show_text"
18          android:background="@color/colorPrimary"
19          android:text="標題顯示"/>
20     <ProgressBar
21         android:max="100"
22         android:progress="10"
23         android:id="@+id/show_progres"
24         style="?android:attr/progressBarStyleHorizontal"
25         android:background="@color/colorPrimary"
26         android:layout_width="match_parent"
27         android:layout_height="wrap_content"/>
28 
29     <WebView
30         android:layout_width="match_parent"
31         android:id="@+id/mywebview"
32         android:layout_height="match_parent" />
33     </LinearLayout>
34     <LinearLayout
35         android:layout_width="match_parent"
36         android:layout_height="wrap_content"
37         android:layout_gravity="bottom"
38         android:orientation="horizontal">
39 
40         <Button
41             android:layout_width="wrap_content"
42             android:layout_height="wrap_content"
43             android:layout_weight="1"
44             android:onClick="But_back"
45             android:text="後退"/>
46         <Button
47             android:layout_width="wrap_content"
48             android:layout_height="wrap_content"
49             android:onClick="But_forward"
50             android:layout_weight="1"
51             android:text="前進"/>
52         <Button
53             android:layout_width="wrap_content"
54             android:layout_height="wrap_content"
55             android:onClick="But_reload"
56             android:layout_weight="1"
57             android:text="重新整理"/>
58         <Button
59             android:layout_width="wrap_content"
60             android:layout_height="wrap_content"
61             android:onClick="But_stop"
62             android:layout_weight="1"
63             android:text="停止"/>
64 
65 
66     </LinearLayout>
67 
68 </FrameLayout>

邏輯原始碼

  1 import androidx.appcompat.app.AppCompatActivity;
  2 import android.os.Bundle;
  3 import android.view.KeyEvent;
  4 import android.view.View;
  5 import android.webkit.WebChromeClient;
  6 import android.webkit.WebSettings;
  7 import android.webkit.WebView;
  8 import android.webkit.WebViewClient;
  9 import android.widget.ProgressBar;
 10 import android.widget.TextView;
 11 import android.widget.Toast;
 12 
 13 public class MainActivity extends AppCompatActivity {
 14     private WebView webv=null;
 15     private TextView showtext=null;
 16     private ProgressBar showpro=null;
 17     @Override
 18     protected void onCreate(Bundle savedInstanceState) {
 19         super.onCreate(savedInstanceState);
 20         //隱藏狀態列
 21         getSupportActionBar().hide();
 22         setContentView(R.layout.activity_main);
 23         //獲取到webview控制元件
 24         webv=findViewById(R.id.mywebview);
 25         showtext=findViewById(R.id.show_text);
 26         showpro=findViewById(R.id.show_progres);
 27 
 28         WebSettings webSettings = webv.getSettings();
 29 
 30        webSettings .setAllowFileAccess(true);
 31         //設定支援縮放操作
 32         webSettings.setSupportZoom(true); //支援縮放,預設為true。是下面那個的前提。
 33         webSettings.setBuiltInZoomControls(true); //設定內建的縮放控制元件。若為false,則該WebView不可縮放
 34         webSettings.setDisplayZoomControls(false); //隱藏原生的縮放控制元件
 35 
 36         //編輯網頁程式碼
 37         String myhtml="<h1 >東小東標題</h1>" +
 38                 "<hr/>" +
 39                 "<h2><a href='https://www.cnblogs.com/dongxiaodong/'>去東小東部落格園看看<a/></h2>" +
 40                 "<h3 >網頁顯示小標題</h3>" +
 41                 "<img style=\"width: 300px;\" src=\"https://img2018.cnblogs.com/blog/1485202/201811/1485202-20181116215233782-319594948.png\"/>";
 42         //設定顯示
 43         webv.loadDataWithBaseURL("",myhtml,"text/html", "utf-8",null);
 44 
 45         //通過下面的程式碼阻止APP直接通過瀏覽器開啟網頁
 46         webv.setWebViewClient(new WebViewClient(){
 47             @Override
 48             public boolean shouldOverrideUrlLoading(WebView view, String url) {
 49                 //使用WebView載入URL內容
 50                 view.loadUrl(url);
 51                 return  true;
 52             }
 53         });
 54         webv.setWebChromeClient(new WebChromeClient() {
 55             @Override
 56             public void onReceivedTitle(WebView view, String title) {
 57                 //標題顯示
 58                 showtext.setText(title);
 59                 //Toast.makeText(MainActivity.this,title,Toast.LENGTH_SHORT).show();
 60             }
 61 
 62             @Override
 63             public void onProgressChanged(WebView view, int newProgress) {
 64                 super.onProgressChanged(view, newProgress);
 65                 //進度條顯示
 66                 showpro.setProgress(newProgress);
 67                 //Toast.makeText(MainActivity.this,newProgress+"",Toast.LENGTH_SHORT).show();
 68             }
 69         });
 70 
 71     }
 72     //監聽程式的返回事件
 73     public boolean onKeyDown(int keyCode, KeyEvent event) {
 74         //如果按下返回鍵且網頁有歷史記錄,可以返回上一級
 75         if ((keyCode == KeyEvent.KEYCODE_BACK) && webv.canGoBack()) {
 76             //返回上一級
 77             webv.goBack();
 78             return true;
 79         }
 80         //否則返回真實的按鍵資訊給系統,系統將將退出程式
 81         return super.onKeyDown(keyCode, event);
 82     }
 83 
 84     //後退函式實現
 85     public void But_back(View v){
 86         //查詢是否可以返回上一級
 87         boolean canx=webv.canGoBack();
 88         //返回上一級
 89         if(canx) webv.goBack();
 90         //不可返回
 91         else  Toast.makeText(MainActivity.this,"已經到達底端",Toast.LENGTH_SHORT).show();
 92     }
 93     //前進函式實現
 94     public void But_forward(View v){
 95         boolean canx=webv.canGoForward();
 96         //返回上一級
 97         //查詢是否可以返回上一級
 98         if(canx) webv.goForward();
 99             //不可返回
100         else  Toast.makeText(MainActivity.this,"已經到達頂端",Toast.LENGTH_SHORT).show();
101     }
102     //重新整理頁面
103     public void But_reload(View v){
104         webv.reload();
105     }
106     //停止介面載入
107     public void But_stop(View v){
108         webv.stopLoading();
109     }
110 }

參考:

https://blog.csdn.net/Jolting/article/details/81223904?utm_source=blogxgwz9

https://blog.csdn.net/weixin_40438421/article/details/85700109

https://www.jianshu.com/p/3e0136c9e748

 

相關文章