今天的文章我要來寫寫關於WebView

WebView顧名思義就是一個在手機上顯示指定網頁的元件,而這個元件我記得很早很早就有了

記得當時我剛學Android的時候好像還是Android2還是3左右,那時候的WebView我只記得就是一個字

 

沒錯,就是鳥,超鳥的那種XD

我記得最早就只能純顯示網頁,然後頂多拿到載入回調,就沒了( ͡ಠ ʖ̯ ͡ಠ)

而後來遇到的專案其實也鮮少使用到WebView,有需要用到網頁端的話直接Intent跳轉過去就好,完全沒有這個View發揮的餘地

直到後來我在接到跟某個跟支付有關的案子之後,我發現這個WebView在對於那種跟金融有關的設定上特別好用Σ(°ロ°)

 

也因此,敝人我思前想後一番後,決定來寫寫一篇關於WebView的文章

那這篇文章呢~除了最簡單的WebView設置之外,我還會寫關於WebView如何透過JavaScript來跟網頁內容進行互動(交互)

總之,先來看功能吧!

然後Github

->點我


 

1. 設置介面

看了動圖也大概知道今天的內容了XD

總之大致就是兩個部分,其一為將WebView設置為外部網頁

其二的部分雖然有點難從動圖分辨出,但其實是讓程式顯示我寫在本地檔案中的網頁

 

那首先呢,要先能讓Android手機能夠「上網」,就得加入權限

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.WebViewExample"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <meta-data
                android:name="android.app.lib_name"
                android:value="" />
        </activity>
    </application>

</manifest>

 

然後是介面

截圖 2023-03-04 下午9.03.33

<?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:id="@+id/edittext_Input"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <WebView
        android:id="@+id/webView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/guideline"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.7" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.35" />

    <TextView
        android:id="@+id/textView_Status"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView"
        android:textStyle="bold"
        android:textSize="18dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/guideline2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guideline" />

    <Button
        android:id="@+id/button_MyPage"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        android:text="載入本地網頁"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/guideline2" />

    <Button
        android:id="@+id/button_Google"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:text="載入Google"
        app:layout_constraintBottom_toTopOf="@+id/button_MyPage"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/guideline2" />

    <EditText
        android:id="@+id/editText_Input"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="這人沒救了"
        android:hint="輸入內容"
        app:layout_constraintBottom_toTopOf="@+id/button_Google"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/guideline2"
        app:layout_constraintTop_toTopOf="@+id/guideline" />


</androidx.constraintlayout.widget.ConstraintLayout>

OK,基本設定就到這邊,接下來就是稍微有點複雜的部分了

 


 

2. 撰寫本地網頁

 在實裝WebView之前,我們必須寫一個本地的網頁

檔案位置的話,一般我們都會放在「assets」這隻資料夾內

而assets這個資料夾在預設裡面是沒有的,因此我們要自己創

以前要創assets的話,必須要自己手動新增檔案,後來Android studio有提供在他的列表中了,因此新增起來也是挺方便的

新增的方式如下

在app點右鍵->New->Folder->Assets Folder

截圖 2023-03-04 下午9.11.51

點下去之後,這一頁直接點選Finish即可

截圖 2023-03-04 下午9.13.24

接下來就會看到assets資料夾囉!

截圖 2023-03-04 下午9.16.17

 

再來,我要在這下面建立Web.html檔案

建立方法為

assets->右鍵->New->Flie

截圖 2023-03-04 下午9.17.42

然後輸入「Web.html」即可

截圖 2023-03-04 下午9.23.22

最後在裡面輸入以下程式碼

Web.html

<!DOCTYPE html>
<html>
<head>
<title>WebView Example</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
font-family: Arial, sans-serif;
font-size: 16px;
margin: 0;
padding: 0;
background-color: #F0F0F0;
}
 
header {
background-color: #333;
color: #fff;
padding: 10px;
text-align: center;
}
 
img {
display: block;
margin: 10px auto;
max-width: 80%;
}
 
h2{
display: block;
text-align: center;
}
 
p{
display: block;
margin: 20px auto;
text-align: center;
}
 
a {
color: #333;
display: block;
margin: 10px auto;
text-align: center;
text-decoration: none;
}
 
@media screen and (min-width: 600px) {
body {
font-size: 20px;
}
}
</style>
</head>
<body>
<header>
<h1>Hello WebView</h1>
</header>
<main>
<p >來讓神秘的Doge告訴你你何時脫單</p>
<img src="https://media-cldnry.s-nbcnews.com/image/upload/t_nbcnews-fp-1200-630,f_auto,q_auto:best/rockcms/2022-01/210602-doge-meme-nft-mb-1715-8afb7e.jpg" alt="Placeholder Image">
<p>Doge 説:</p>
<h2 id="says">完了這人沒救了</h2>
 
</main>
</body>
</html>

 

恩...從VSCode貼過來的雖然有彩色,不過沒有凸行...加減看吧XD

至於內容麻...我很懶所以是請AI幫我寫的哈哈,大家就自己加減看吧~

 


 

3. 撰寫內容

 

好,來到重點了。接下來就是關於View的控制方式

照慣例,先貼程式碼

MainActivity.java

public class MainActivity extends AppCompatActivity {

    private TextView tvStatus;
    private boolean isGoogle = true;
    @SuppressLint("SetJavaScriptEnabled")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvStatus = findViewById(R.id.textView_Status);
        EditText edInput = findViewById(R.id.editText_Input);
        WebView webView = findViewById(R.id.webView);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.loadUrl("https://www.google.com/");
        webView.setWebViewClient(new WebViewClient(){
            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                //取得Cookies
                String cook = CookieManager.getInstance().getCookie(url);
                if (cook!= null){
                    String[] cookies = cook.split(";");
                    for (String cookie:cookies) {
                        Log.d("TAG", "onPageFinished: "+cookie);
                    }
                }
                String javascript;
                if (isGoogle){
                    javascript = "document.getElementsByName('q')[0].value = '如何脫單';";
                }else{
                    javascript = "document.getElementById('says').innerHTML = '"
                            +edInput.getText()+"';";
                }
                view.evaluateJavascript(javascript, null);
            }
        });
        webView.setWebChromeClient(new WebChromeClient() {
            @SuppressLint("SetTextI18n")
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
                tvStatus.setText("進度:\n"+newProgress);
            }
        });

        (findViewById(R.id.button_Google)).setOnClickListener(view -> {
            isGoogle = true;
            webView.loadUrl("loadUrl('about:blank')");
            webView.clearCache(true);
            webView.loadUrl("https://www.google.com/");
        });
        (findViewById(R.id.button_MyPage)).setOnClickListener(view -> {
            isGoogle = false;
            webView.loadUrl("loadUrl('about:blank')");
            webView.clearCache(true);
            webView.loadUrl("file:///android_asset/Web.html");

        });
    }

}

WebView的設置大概就是如此,其實說難也不會很複雜

但有幾個重點我想抓出來講,首先是關於setWebViewClientsetWebChromeClient

這兩個真的是長得有夠像XD,我第一次接觸的時候老是看到眼花

不過基本上是這樣的,setWebViewClient他這邊的回調大概都跟在跑網頁時的過程相關,而setWebChromeClient多跟網頁JS內容有關

因此,像是偵測網頁開跑以及跑完的回調都是在setWebViewClient裡面,而跑進度條就是在setWebChromeClientonProgressChanged方法內

 

再來是關於向網頁丟資料的部分。很多時候我們使用WebView時都會希望自動幫使用者填入一些內容,小則像是帳號密碼之類的,比較大的例如token直接在網頁做登入等等

而這部分的資料我找了好一陣子,大部分人提供的方法都是直接把網頁原始碼嵌入到程式碼之中...

也不是不行啦,但是小網頁還可以,大網頁可是一點都不實用啊「(°ヘ°)

後來我發現WebView可以直接對網頁輸入JavaScript內容,因此這部分的內容就是綠色匡起來的部分了

String javascript;
if (isGoogle){
    javascript = "document.getElementsByName('q')[0].value = '如何脫單';";
}else{
    javascript = "document.getElementById('says').innerHTML = '"
            +edInput.getText()+"';";
}
view.evaluateJavascript(javascript, null);

也因此我們如果打開Google瀏覽器後,網頁會自動填入「如何脫單」的理由

P.s...找出這個標籤(Name)比研究如何填入還久囧

 

再來,網頁麻,經常會需要操作Cookie

因此我這邊也特別補上了取得Cookie的方法,如下

//取得Cookies
String cook = CookieManager.getInstance().getCookie(url);
if (cook!= null){
    String[] cookies = cook.split(";");
    for (String cookie:cookies) {
        Log.d("TAG", "onPageFinished: "+cookie);
    }
}

 

最後,想要清掉WebView的內容的話,在4.4以前有個clearView的方法

不過在現在的版本中,直接呼叫webView.loadUrl("loadUrl('about:blank')");就可以消除掉WebView的內容囉!

webView.loadUrl("loadUrl('about:blank')");

 


 

關於WebView的介紹大概就是到這邊,其他WebView還有非常非常多方法可以使用

可能也是因為是老牌元件吧,這部分的資料還是蠻多的,大家可以花點時間去看看這部分的文章哦!

像是這篇我覺得不錯

->https://blog.csdn.net/fengyuzhengfan/article/details/38326861

這篇雖然一看就知道大概只是翻譯Android文檔而已,不過我覺得還蠻多範例的

不妨也參考一下吧!

最後..

TK

arrow
arrow
    創作者介紹
    創作者 碼農日常 的頭像
    碼農日常

    碼農日常大小事

    碼農日常 發表在 痞客邦 留言(0) 人氣()