首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android WebView 開機直達指定網頁完整實作:載入進度、JS 支援、縮放、錯誤處理

     編輯:程式設計綜合問答

需求:App 啟動直接載入指定網址 (如 https://www.baidu.com),無需使用者手動輸入,並提供載入進度條、JS 支援、雙擊縮放、錯誤頁面友善提示。本文提供生產級 WebView 封裝代碼,涵蓋 WebViewClient、WebChromeClient、生命週期管理、權限配置全細節。

Manifest 權限與配置

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

<application
    android:usesCleartextTraffic="true"  <!-- HTTP 明文流量 (API 28+) -->
    ...>
    <activity android:name=".MainActivity">...</activity>
</application>

佈局檔 (res/layout/activity_main.xml)

<FrameLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

    <!-- 載入指示器 -->
    <ProgressBar
        android:id="@+id/progress_bar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="3dp"
        android:max="100"
        android:progress="0"
        android:visibility="gone" />

    <TextView
        android:id="@+id/loading_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="載入中..."
        android:visibility="gone" />
</FrameLayout>

核心 Activity 代碼 (Kotlin)

class MainActivity : AppCompatActivity() {

    private lateinit var webView: WebView
    private lateinit var progressBar: ProgressBar
    private lateinit var loadingText: TextView

    private val targetUrl = "https://www.baidu.com"  // 可從 Intent/設定讀取

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        webView = findViewById(R.id.webview)
        progressBar = findViewById(R.id.progress_bar)
        loadingText = findViewById(R.id.loading_text)

        initWebView()
        loadUrl(targetUrl)
    }

    private fun initWebView() {
        val settings = webView.settings.apply {
            javaScriptEnabled = true                    // 1. 啟用 JS
            domStorageEnabled = true                    // 2. LocalStorage
            databaseEnabled = true
            useWideViewPort = true                      // 3. 支援 viewport
            loadWithOverviewMode = true
            builtInZoomControls = true                  // 4. 內建縮放控制
            displayZoomControls = false                 // 隱藏縮放按鈕
            supportZoom = true
            mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW // HTTP/HTTPS 混合
            cacheMode = WebSettings.LOAD_DEFAULT
        }

        // 5. 客製化 WebViewClient:攔截連結、錯誤處理
        webView.webViewClient = object : WebViewClient() {
            override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
                view.loadUrl(request.url.toString())
                return true
            }

            override fun onReceivedError(view: WebView, request: WebResourceRequest, error: WebResourceError) {
                showErrorPage(error.description.toString())
            }

            override fun onPageFinished(view: WebView, url: String) {
                loadingText.visibility = View.GONE
                progressBar.visibility = View.GONE
            }
        }

        // 6. 客製化 WebChromeClient:進度條
        webView.webChromeClient = object : WebChromeClient() {
            override fun onProgressChanged(view: WebView, newProgress: Int) {
                progressBar.progress = newProgress
                if (newProgress < 100) {
                    progressBar.visibility = View.VISIBLE
                    loadingText.visibility = View.VISIBLE
                } else {
                    progressBar.visibility = View.GONE
                    loadingText.visibility = View.GONE
                }
            }
        }
    }

    private fun loadUrl(url: String) {
        webView.loadUrl(url)
    }

    private fun showErrorPage(msg: String) {
        webView.loadDataWithBaseURL(null,
            "<html><body><h1>載入失敗</h1><p>$msg</p></body></html>",
            "text/html", "UTF-8", null)
    }

    // 7. 生命週期:釋放資源
    override fun onDestroy() {
        webView.loadUrl("about:blank")
        webView.stopLoading()
        webView.webViewClient = null
        webView.webChromeClient = null
        webView.destroy()
        super.onDestroy()
    }

    // 8. 返回鍵處理:優先網頁後退
    override fun onBackPressed() {
        if (webView.canGoBack()) webView.goBack()
        else super.onBackPressed()
    }
}

Java 版關鍵片段 (WebSettings 設定)

WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setUseWideViewPort(true);
settings.setLoadWithOverviewMode(true);
settings.setBuiltInZoomControls(true);
settings.setDisplayZoomControls(false);
settings.setSupportZoom(true);
settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
settings.setDomStorageEnabled(true);

常見坑點與解決

問題原因解決
網頁空白/白屏未開啟 JS、HTTP 明文被阻擋javaScriptEnabled=true + usesCleartextTraffic=true
點擊連結跳出系統瀏覽器未覆寫 shouldOverrideUrlLoading回傳 true 並 view.loadUrl(url)
進度條不消失未在 onPageFinished 隱藏正確實作 WebChromeClient.onProgressChanged
記憶體洩漏Activity 銷毀未清理 WebViewonDestroy 中完整釋放

進階擴充:FileProvider、Cookie 同步、UserAgent 客製

// Cookie 同步 (登入態共享)
CookieManager.getInstance().setAcceptCookie(true);
CookieManager.getInstance().setAcceptThirdPartyCookies(webView, true);

// 自訂 UserAgent
settings.setUserAgentString(settings.getUserAgentString() + " MyApp/1.0");

總結

一個生產可用的 WebView 封裝需涵蓋:權限配置、JS/儲存/縮放/混合內容啟用、WebViewClient 處理導航與錯誤、WebChromeClient 進度回報、生命週期釋放、返回鍵攔截。上述 Kotlin/Java 完整代碼可直接整合至專案,並作為進一步客製化 (如 JSBridge、離線快取、影音播放) 的基礎骨架。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved