Android 官方開始擁抱 WebView

前言

--

如果你是一名 Android 開發者,那麼你大概率經歷過這樣一個時代:WebView 經常被看成「套殼」「H5 頁面」「臨時方案」,甚至只要一個 App 裡用了大量 WebView,很多人就會下意識覺得它「不夠原生」。

老實說,淘寶 App 的糟糕使用體驗,我一直覺得就是 Web 沒有優化好導致的。

這次 Google I/O 上,官方明確表達了:Build native Android experiences for web apps using WebView

當然,它的主旨並不是「如何簡單地把網頁塞進 App 裡」。它真正討論的是:當你已經擁有一個成熟的 Web App,如何利用 Android WebView,把它逐步改造成一個更接近原生體驗的 Android 應用。

換句話說,這不是一條「WebView 套殼教學」,而是一條「如何讓 Web App 擁有 Android 原生能力」的工程路線。

000.png

WebView 的問題

很多 Android 開發者對 WebView 的第一印象,通常停留在:

kotlin 體驗AI代碼助手 代碼解讀複製代碼webView.loadUrl("https://example.com")

但這只是 WebView 最基礎的能力。真正難的地方,不是把網頁顯示出來,而是讓這個網頁在 Android App 裡「像一個真正的 App」。

一個普通網頁放進 WebView 之後,馬上會遇到很多體驗斷層,例如:

  • 檔案上傳是不是能自然呼叫系統相片選擇器?
  • 網頁觸發下載時,是否能交給 Android 的下載管理器?
  • 網頁需要通知使用者時,能不能觸發原生通知?
  • 網路不穩定時,能不能做快取和離線支援?
  • Web 程式碼和 Android 原生程式碼之間,能不能安全、穩定地雙向通訊?

這些問題,其實都有解法——JS Bridge。只要透過 JS 介面呼叫原生方法,理論上都能搞定。

但是!這樣做很麻煩。大部分開發者在開發 Web App 的時候,一定是先使用一大堆第三方函式庫或者 Web 打包工具才能完成開發。

不能開箱即用,才是問題的核心,而這,正是這次主題真正關心的重點。

Android 官方文件也強調,WebView 本質上是 Android View 的一個擴充,它預設只負責顯示網頁,並不包含完整瀏覽器的網址列、導覽控制等能力。

因此,一旦你想讓它承載一個完整的 Web App,就必須額外處理導覽、JavaScript、原生通訊、視窗管理等問題。

補齊原生體驗

2.png

Google 介紹了一個更貼近真實業務的範例:一個 Web 形態的筆記應用。

這個選擇其實很典型,因為筆記類應用看起來很簡單,但它剛好能涵蓋 WebView App 常見的幾個關鍵能力:通知、圖片選擇、檔案下載、快取、離線,以及 Web 與 Native 的互相呼叫。

Google 想用一個完整場景告訴你:如果你已經有一個 Web App,那麼可以透過 WebView 和 Android 原生能力,把它一步一步做得更像真正的 Android App。

一、互相通訊

3.png

一個 WebView App 想獲得原生能力,最重要的一步就是打通 Web 與 Native 的通訊。

否則網頁永遠只是網頁,Android 也只是外面那個殼。

在傳統 WebView 中,我們經常會看到 addJavascriptInterface() 這種方式:Android 向 WebView 注入一個物件,JavaScript 可以透過這個物件呼叫 Android 端的方法(上面提到的 JS Bridge)。

例如網頁裡點擊一個按鈕,然後讓 Android 端彈出 Toast、打開系統能力,或者執行某個原生邏輯。

但這裡有一個非常重要的安全前提:你必須清楚 WebView 中載入的內容是否可信。

Android 官方文件明確提醒,addJavascriptInterface() 可能帶來安全風險,因為它允許 JavaScript 控制 Android App 暴露出來的物件。

因此它更適合用在你完全控制 HTML 和 JavaScript 來源的場景中,而不適合讓使用者隨便打開第三方網頁。

這也正是 WebView 工程裡最容易被忽略的問題:WebView 不是瀏覽器。瀏覽器會幫你處理大量安全邊界,而當你把網頁放進自己的 App 時,很多邊界就需要你自己設計。

我在 15 - 17 年,有過很長一段時間的 Web App 開發經驗,我記得當時我們就是編寫了一個超級大的 JavascriptInterface,然後注入 WebView,裡面的 Web 也是我們本地的網頁(沒錯,本地的,定期會從伺服器下載新的網頁),現在想起來,搞不好那個已經具備了小程式的原型,只不過可惜技術方面沒有繼續往下探究了。因為 Web 體驗不好,無法無縫地嵌入到地圖中。

二、從 Web 觸發原生通知

5.png

Google 介紹了一個很關鍵的能力,是讓 Web 程式碼觸發原生 Android 通知。

這件事很能說明 WebView 的定位:Web 管業務邏輯和頁面,Android 管系統能力。

比如筆記應用裡,使用者在 Web 頁面建立了一個提醒,最終透過 Android 原生通知跳出來。這跟「網頁彈個 alert」完全是兩回事——它走的是 Android 的通知權限、通知頻道、系統通知樣式,是真正的系統級體驗。

邊界也很清楚:Web 發出意圖,Native 執行系統能力。誰也別越界。

三、原生的檔案能力

6.png

檔案選擇,尤其是圖片選擇,在 WebView 裡也是個老大難問題。

Web 裡一個 <input type="file"> 就搞定了,但放到 Android App 裡,彈出來的選擇器體驗千差萬別——有的 App 直接調起一個簡陋的檔案瀏覽器,有的甚至什麼都彈不出來。

我之前用過一些 App,上傳頭像的時候彈出來的選擇介面跟系統風格完全不搭,一眼就知道這是 WebView 裡硬塞進去的。Google 在講演裡給出的方案是接入 Android 系統的 PhotoPicker,體驗直接跟系統相簿拉齊。

說白了,WebView 不是讓 Web 脫離 Android 各玩各的,而是讓 Web 借用 Android 已經打磨好的系統能力。頭像、筆記圖片、商品圖片、留言配圖——這些都是高頻場景,處理得好不好,使用者一眼就能感知到。

四、原生的下載體驗

7.png

下載檔案也是 WebView App 裡繞不開的場景。

你肯定遇過這種情況:在某個 App 裡點了一個下載連結,進度條一閃而過,然後——沒了。

檔案去哪了?不知道。下載成功了嗎?不確定。去檔案管理器翻半天,才在某個角落找到。

Google 給出的做法是把下載交給系統的 DownloadManager。這樣一來,使用者在系統通知列裡就能看到下載進度,下載完了能在系統下載列表裡找到,體驗跟瀏覽器裡下載東西是一樣的。

思路跟前面一樣:Web 負責說「我要下載這個」,具體的下載體驗交給 Android 來做。PDF、報表、圖片、附件,這些場景太多了,如果每次都自己造輪子處理檔案流,既費勁又容易出問題。

一切,都是為了使用者體驗!

五、攔截網路請求

8.png

還有一個更偏工程實戰的點:攔截網路請求,做快取或離線支援。

很多人對 WebView 的理解就是「必須連網才能用」。但你想想真實場景——捷運、電梯、弱網、海外——如果 WebView 一斷網就白畫面,使用者根本不會給你第二次機會。

WebView 提供了攔截網路請求的能力,開發者可以在 Android 端對部分資源做快取,或者在斷網時返回本地內容。做到這一步,Web App 才真正不是一個「遠端網頁視窗」。

當然,快取這件事不是越多越好。你得想清楚哪些資源值得快取、哪些介面必須即時請求、使用者離線時該看到什麼、恢復網路後怎麼同步。這些問題沒有標準答案,得根據具體業務來定。

這麼看,我在 15 年左右做的工作還可以,當時對 Web App 做了版本管理,並且可以完全離線執行。

六、分頁導覽

9.png

最後說一個容易被低估的問題:導覽和分頁。

Web App 不是單頁那麼簡單。它可能會彈新視窗、跳外部連結、觸發登入頁、跳到第三方授權——如果這些行為沒處理好,使用者就會遇到各種糟心事:點了連結突然被甩到外部瀏覽器,按返回鍵不知道回到哪,登入完了頁面回不來。

這些事,正常瀏覽器都幫你幹了,但 WebView 預設只是個「顯示網頁的 View」,你得自己配置 WebViewClientWebChromeClient 來接管這些行為。

所以很多時候大家覺得 WebView 是個低成本方案,其實恰恰相反。loadUrl() 當然便宜,但要讓它像一個正經 App 一樣跑起來,需要處理的邊邊角角一點都不少。

WebView 的正確打開方式

看完整個講演,我覺得它表達的核心意思其實很簡單:WebView 不是原生的替代品,但也不是低品質方案。

它適合的場景很明確——你已經有成熟的 Web 體系、Web 團隊和 Web 迭代流程,現在想把這些能力帶到 Android 上。它不是讓你隨便寫個網頁然後套個殼就完事了。

所謂的「補齊原生體驗」,說白了就是:Web 和 Native 各有各的邊界,誰也別假裝能幹對方的活。Web 擅長業務頁面和快速迭代,Native 擅長系統能力——通知、檔案、下載、快取、導覽、安全這些。而 WebView 就是把這兩邊串起來的那根線。

4.png

Android 開發者關注什麼

對於 Android 開發者來說,我們可能過去一直有這樣一個認知:只要一個功能是 Web 做的,Android 端就只是「套殼」。

但現在越來越多產品會採用混合架構,Android 開發者需要負責的不只是寫原生頁面,還包括設計 Web 與 Native 的邊界。

比如:

  • 哪些能力應該留在 Web?
  • 哪些能力必須放在 Native?
  • JSBridge 如何設計才安全?
  • 檔案選擇、下載、通知如何接入系統?
  • WebView 的快取策略如何設計?
  • 返回鍵和頁面歷史如何統一?
  • WebView 生命週期如何管理?

這些問題如果處理得好,WebView App 就可能非常接近原生體驗;如果處理不好,它就會變成使用者熟悉的那種「套殼網頁」。

不要妖魔化 WebView

這次講演,它沒有把 WebView 描述成原生開發的替代品,也沒有把 WebView 當成低品質方案,而是將 WebView 視為將 Web 內容帶入 Android 生態的能力容器。

在國內,WebView 的名聲之所以不好,很大程度上是因為它被大量用在了「快速出活」的場景裡——不是為了給使用者更好的體驗,而是為了盡快滿足業務需求、完成 KPI。

結果就是,很多 App 裡的 WebView 頁面體驗粗糙、載入緩慢、互動生硬,久而久之,使用者和開發者都形成了「WebView 開發的 App 是次等品」的印象。

但這不是 WebView 的問題,而是使用方式的問題。

它適合內容變化快、業務迭代快、已有成熟 Web 體系的產品。

但它不適合所有場景,比如高度依賴複雜動畫、重圖形、低延遲互動、複雜背景任務、深度硬體能力的應用,純原生或者其他跨平台方案仍然可能更合適。

一點想法

WebView = 套殼」這個印象,可能還要持續很久。

但如果你看過這次講演就會發現,WebView 本身不背這個鍋。loadUrl() 一把梭當然會變成套殼,但如果你認真處理通知、檔案選擇、下載、快取、離線、導覽、JSBridge 和安全邊界,它完全可以成為 Web App 進入 Android 生態的一條正經路徑。

未來的 Android 應用,純 Native 或純 Web 的劃分會越來越模糊。業務層用 Web 保持快速迭代,系統體驗由 Native 補齊,二者透過 WebView 協作——這大概率會成為很多產品的常態。

Build native Android experiences for web apps using WebView
www.youtube.com/watch?v=4_S…


原文出處:https://juejin.cn/post/7642917750827008027


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝20   💬11   ❤️1
586
🥈
alicec
📝1   ❤️2
83
🥉
我愛JS
💬1  
4
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登