整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Android WebView開發(一)

          .前言

          目前很多公司的 App 就只使用一個 WebView 作為整體框架, App 中的所有內容全部使用 HTML5 進行展示,這樣只需要寫一次 HTML5 代碼,就可以在 Android 和 iOS 平臺上運行,這就是所謂的「 跨平臺 」。隨著 HTML5 的普及,很多 App 都會內嵌 WebView 來加載 HTML5 頁面,即 Native 和 HTML5 共存,這就是當下最流行的「 混合開發 」。HTML5 除了開發簡單,還有一個優勢就是迭代方便, 只需要修改服務端的 HTML5 頁面,App 會同步更新,無論是做活動推廣 App 還是及時修復 Bug 都帶來的極大的便利。不過 HTML5 劣勢也很明顯,受制于國內的網速限制。 雖然國內已經普及了 4g 網絡,但是網速還是不盡如人意。HTML5 加載受限于網絡,沒有原生控件流暢,用戶體驗相對較差, 所以目前完全使用 HTML5 開發 App 并沒有成為主流。我所在的項目組也使用HTML5開發比較頻繁,這個時候了解WebView使用就變得尤為重要了,而WebView的坑也是非常的多,我在開發中就遇到了許多莫名其妙的問題。 所以準備寫幾篇文章總結一下,文章按照類來進行分類。WebView開發常用的類是 WebView , WebSettings , WebViewClient , WebChromeClient。
          這里是WebView開發第一篇: WebView 的使用介紹;

          1. Android WebView 簡介
            ==
            我們先來看一下官方對Android WebView的介紹

          A View that displays web pages. This class is the basis upon which you can roll your own web browser or simply display some online content within your Activity. It uses the WebKit rendering engine to display web pages and includes methods to navigate forward and backward through a history, zoom in and out, perform text searches and more.

          總結起來就是:WebView是一個基于WebKit引擎的,并且可以在activity展現Web頁面的控件。

          1. 簡單使用
            ==
            3.1、添加網絡權限
          <uses-permission android:name="android.permission.INTERNET" />
          

          3.2 添加布局頁面
          這里介紹另外一種方式,通過addView添加進去
          1.在布局頁面添加布局

            <FrameLayout
                  android:id="@+id/webViewWrap"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:visibility="visible" />
          

          2.實體化webview并添加到布局中

          		webViewWrap = findViewById(R.id.webViewWrap); //上面的FrameLayout
                  webView = new WebView(MyApplication.getAppContext()); //使用應用上下文,可以防止內存泄露,如果傳入activity的上下文,需要將webview remove掉。下面有講解。
                  webViewWrap.addView(webView);
          

          3.加載頁面

          //方式1. 加載一個網頁:
            webView.loadUrl("http://www.google.com/");
          
            //方式2:加載apk包中的html頁面
            webView.loadUrl("file:///android_asset/test.html");
          
            //方式3:加載手機本地的html頁面
             webView.loadUrl("content://com.android.htmlfileprovider/sdcard/test.html");
          
             // 方式4: 加載 HTML 頁面的一小段內容
            WebView.loadData(String data, String mimeType, String encoding)
          // 參數說明:
          // 參數1:一段HTML代碼
          // 參數2:展示內容的類型
          // 參數3:字節碼
          

          到這一步我們就能夠展示一個WebView頁面了,不過是通過外部瀏覽器打開的。但是還有許多優化的地方。

          4.WebView的狀態

          //激活WebView為活躍狀態,能正常執行網頁的響應,可以在activity 的回調方法中調用
          webView.onResume() ;
          
          //當頁面被失去焦點被切換到后臺不可見狀態,需要執行onPause,可以在activity 的回調方法中調用
          //通過onPause動作通知內核暫停所有的動作,比如DOM的解析、plugin的執行、JavaScript執行。
          webView.onPause();
          
          //當應用程序(存在webview)被切換到后臺時,這個方法不僅僅針對當前的webview而是全局的全應用程序的webview
          //它會暫停所有webview的layout,parsing,javascripttimer。降低CPU功耗。
          webView.pauseTimers()
          
          //恢復pauseTimers狀態
          webView.resumeTimers();
          
          //銷毀Webview
          //在關閉了Activity時,如果Webview的音樂或視頻,還在播放。就必須銷毀Webview
          //但是注意:webview調用destory時,webview仍綁定在Activity上
          //這是由于自定義webview構建時傳入了該Activity的context對象
          //因此需要先從父容器中移除webview,然后再銷毀webview:
          ViewParent parent = mWebView.getParent();
                  if (parent != null) {
                      ((ViewGroup) parent).removeView(mWebView);// 防止內存泄露
                  } 
          webView.destroy();
          
          1. 關于前進 / 后退網頁
            ==
          //是否可以后退
          Webview.canGoBack() 
          //后退網頁
          Webview.goBack()
          
          //是否可以前進                     
          Webview.canGoForward()
          //前進網頁
          Webview.goForward()
          
          //以當前的index為起始點前進或者后退到歷史記錄中指定的steps
          //如果steps為負數則為后退,正數則為前進
          Webview.goBackOrForward(intsteps)
          

          常見用法:Back鍵控制網頁后退

          問題:在不做任何處理前提下 ,瀏覽網頁時點擊系統的“Back”鍵,整個 Browser 會調用 finish()而結束自身
          目標:點擊返回后,是網頁回退而不是
          推出瀏覽器
          解決方案:在當前Activity中處理并消費掉該 Back 事件

          1. 清除緩存數據
            ==
          //清除網頁訪問留下的緩存
          //由于內核緩存是全局的因此這個方法不僅僅針對webview而是針對整個應用程序.
          Webview.clearCache(true);
          
          //清除當前webview訪問的歷史記錄
          //只會webview訪問歷史記錄里的所有記錄除了當前訪問記錄
          Webview.clearHistory();
          
          //這個api僅僅清除自動完成填充的表單數據,并不會清除WebView存儲到本地的數據
          Webview.clearFormData();
          

          WebView 的使用介紹就先到這里了,下一篇將會講解WebSettings的使用。

          年做了大量的 HTML5 項目,遇到了很多坑。在這個過程中學到了一些之前不具備的知識,所以這篇文章就簡單分享一下這方面的話題。

          傳統的MPA

          首先,說一個比較古老的東西,叫做 MPA。

          MPA 的全稱是 Multi-page Application,意思是整個應用(站點)由多個完整的 html 構成。用戶在頁面 1 點擊跳轉,需要向服務端請求頁面 2,請求成功后渲染。而用戶返回時,相當于是點擊了瀏覽器的返回,頁面退回到之前的歷史記錄,并重新加載出來。

          在這樣的模式下,頁面間切換慢、不流暢的問題比較突出,尤其是在移動端。

          同時,它還產生了幾個小問題:

          • 跳轉動畫:頁面間的跳轉無法實現轉場動畫效果。
          • 如果前一個頁比較長,用戶滑動到頁面比較靠下方的位置后點擊,返回時,頁面無法默認停留在原位置。
          • iOS 右滑返回產生問題,從頁面 1 跳轉到頁面 2,再從頁面 2 跳轉到頁面 3,右滑返回,會直接回到頁面 1 前的頁。

          SPA

          隨著對移動端體驗需求的提高以及技術的進步,另一種模式 SPA(Single-page Application)逐漸成為主流。

          SPA 簡單來說,就是原來在 MPA 中的多個 html,現在被放在了一個 html 中,并被分成若干個片段。跳轉、返回的本質變成了分段的「隱藏」與「顯示」。跳轉不需要反復對服務端進行請求,從而使得頁面與頁面之間切換更加快速流暢。

          在這樣的機制下,跳轉與返回完全由代碼控制,所以可以通過代碼定義頁面轉場的效果、返回。

          在設計轉場動畫時,我們需要留意的是導航欄是 Native 的還是 HTML5 的。如果導航欄是 Native 的,那 HTML5 頁面不包括導航欄,它相當于是網頁外的元素,不在轉場效果的設計范圍內。

          WebView

          說 HTML5 的跳轉,就不得不說 WebView。簡單來說,WebView 是在 App 中用于顯示 web 內容的容器。上文提到的 MPA 和 SPA,都裝在了這個叫做 WebView 的容器中。

          用戶點擊頁面中的元素進行跳轉,除了前面的兩種方式外,還有第三種:新打開 WebView 的方式。在這樣的方式下,跳轉的本質是 HTML5「告訴」Native,由 Native 執行打開新 WebView,并在新 WebView 中加載頁面。

          因為 Native 的機制,打開新 WebView 的同時,之前的 WebView 會被自然、完整地保留。所以這時,之前的幾個問題就變為:

          • 跳轉動畫:頁面間的跳轉動畫由 WebView 之間的跳轉動畫來決定。
          • 返回后頁面停留在原位置:完美支持。
          • iOS 右滑返回:完美支持。

          不過需要注意的地方是,打開新 WebView 是一個資源消耗比較大的操作。如果我們在設計一個流程時,需要比較多的連續使用這種方式,需要和研發同學進行充分的溝通。

          比較特殊的Replace

          前述的三種跳轉,都會產生歷史記錄。MPA、SPA 的歷史記錄是在 HTML5 中產生,新開 WebView 中的記錄是在 Native 中產生。

          在 MPA 或 SPA 中,如果跳轉時使用 Replace 方法,它會用新頁面替換之前的頁面,歷史記錄中沒有之前頁面的記錄。

          這是一種特殊的跳轉方式,在設計一些不可逆的流程時可考慮使用。

          多頁面回退

          了解了上述的幾種機制后,我們來看一個小的應用場景──多頁面回退。

          我們在實際業務中,經常會有這樣的需求。假設我們有 1、2、3 三個頁組成的一個流程,在頁面 3 上有個「完成」按鈕點擊回到頁面 1。在不同的交互模式下,實現這樣的跳轉有著不同的機制。

          1. SPA模式下的正常跳轉

          這種模式是 3 個頁面都在一個 WebView 中。點擊頁面 3 中的「完成」按鈕,回退 -2 ,即回退 2 步歷史記錄,到頁面 1。

          2. 新打開WebView

          打開新 WebView 又分三種方式。

          如果我們把 3 個頁面,拆分到 2 個 WebView 中,如下圖,點擊完成按鈕,即關閉自身所在的 WebView。

          同樣是打開新的 WebView,如果我們按如下圖的方法拆分會稍微復雜。這時點擊完成按鈕,首先關閉自身所在的 WebView,當頁面 2「意識」到自己重新被展現時,自動退回 1 步到頁面 1。

          每次打開新的 WebView,這時點擊完成,回退的本質是 HTML5「告訴」Native 關閉多個 WebView。需要特別注意的是,HTML5 中實現這種方式不是天然具備的,它需要 Native 具有一次關閉多個 WebView 的能力。所以我們在設計方案時,需要了解清楚自家的 Native 是否有這樣的能力。

          總結

          以上,簡單說了幾種 HTML5 的跳轉方式。這些跳轉方式,沒有絕對的對與錯,我們在設計方案時,需要根據實際的業務需求與技術的限制,來整體考慮解決方案。

          根據個人經驗,也有幾點小帖士分享給大家:

          • 前后邏輯交織不復雜的單個頁面,可以考慮使用新 WebView 打開跳轉。
          • 如果是一個任務型的流程,可以考慮將一個任務流包在一個 WebView 中,在任務內使用 SPA 跳轉。不同的任務使用不同的 WebView。保持任務之間的關系清晰明了。
          • 設計上需要著重表現頁面間轉場動畫的效果,優先考慮使用 SPA 跳轉。
          • 為防止流程過于復雜,盡量不要自定義關閉、返回的行為。保持關閉為默認的關閉行為,保持返回為默認的返回行為。

          言:

          根據Google公布的Android 各個系統版本市場占有率(Google Android dashboards), Android 4.0及其以上系統將近90%左右,發展趨勢必將是未來市面上幾乎是Android 4.0以上系統。本文主要關注Android 4.0及以上系統WebView的實現,從Android WebView實現的Framework層大致可以分為三段Android 4.0系列,Android 4.1---4.3系列,Android 4.4及其以上系列。

          WebView差異

          WebView是Android系統提供能顯示網頁的系統控件,它是一個特殊的View,同時它也是一個ViewGroup可以有很多其他子View。在Android 4.4以下(不包含4.4)系統WebView底層實現是采用WebKit(http://www.webkit.org/)內核,而在Android 4.4及其以上Google 采用了chromium(http://www.chromium.org/)作為系統WebView的底層內核支持。在這一變化中Android 提供的WebView相關API并沒有發生大變化,在4.4上也兼容低版本的API并且引進了少部分API。這里簡單介紹下基于Chromium 的Webview和基于Webkit webview的差異,基于Chromium Webview提供更廣的HTML5,CSS3,Javascript支持,在目前最新Android 系統版本5.0上基于chromium 37,Webview提供絕大多數的HTML5特性支持。Webkit JavaScript引起采用WebCore Javascript 在Android 4.4上換成了V8能直接提升JavaScript性能。另外Chromium 支持遠程調試(Chrome DevTools)。

          WebKit for WebView VS Chromium for WebView性能比對(測試環境 小米2. CM Browser. Android 4.1.1 VS 4.4.3)

          Webkit for WebviewChromium for Webview備注
          HTML5278434http://html5test.com/
          遠程調試不支持支持Android 4.4及以上支持
          內存占用相差20-30M左右
          WebAudio不支持支持Android 5.0及以上支持
          WebGL不支持支持Android 5.0及以上支持
          WebRTC不支持支持Android 5.0及以上支持

          Android 4.0 WebView結構

          Android WebView API層主要提供給我們應用程序的接口,為了兼容向下版本Android在高版本中也是對這一層的API進行支持,因此如果底層發生變化,這些API接口層也不會發生太大變化。Android 平臺不僅提供應用層編程接口也提供native層編程。下面介紹上圖中的三個部分:

          1)Android Framework:Android WebView是個特殊控件實現的支持需要Framework的代碼主要在./frameworks/base/core/java/android/webkit目錄下,在Android 4.0實現主要是在WebViewCore.java,BrowserFrame.java等文件。

          2) Android JNI:需要有Native代碼支持,因此需要有JNI層實現,Android WebView 4.0的JNI層實現WebView相關代碼在./external/webkit/Source/WebKit/android/jni/目錄下,這一層起到承上啟下的作用,鏈接Framework層以及WebKit層的橋梁,比如相關的一些實現在WebviewCore.cpp,WebCoreFrameBridge.cpp等。

          3) WebKit: WebKit內核,其核心主要是解析W3C標準以及渲染排版網頁,他是一個跨平臺的內核引擎,那么需要支持各個平臺,需要我們的平臺實現層,在Android 4.0系統這一部分相關代碼主要在./external/webkit/Source/WebKit/android/WebCoreSupport/目錄下,比如FrameLoaderClientAndroid.cpp,ChromeClientAndroid.cpp,這一層負責WebCore與系統平臺的橋接,具體在不同平臺會有不同的實現。實現網頁的解析排版及渲染由WebCore來實現在Android 4.0源碼當中代碼位于./external/webkit/Source/WebCore/下,下面有WebCore實現的各個模塊功能支持的相關代碼,比如頁面視圖部分在page目錄的chrome.cpp,比如加載頁面需要的資源的loader中得FrameLoader.cpp等,這里不在繼續深入詳解,有興趣的朋友可以下載Android 4.0源碼閱讀。

          Android 4.1--4.3 WebView結構

          Android 4.1--4.3版本WebView內核實現還是基于WebKit,但在WebView的Framework層發生了變化,引入了工廠模式,目地是為了將內核與上層API接口分離開來,分離的意義不僅僅是抽象接口,更重要的是將來能替換內核部分的實現。 在4.1--4.3這一系列版本native結構基本與4.0版本相同,下圖呈現新的變化:

          Android 4.0--4.3 渲染

          盡管之前4.0,與4.1--4.3是在不同的結構系列,其兩者之間的差異主要是集中的Framework上的變化,這種變化更多體現在Framework層結構上的變化,WebKit內核極其在Android上的表現機制并沒有發生很大變化,他們的渲染機制是相同的。下面介紹Android 4.0--4.3的渲染機制:

          在Android 4.0上已經默認開啟硬件加速,因此WebView的渲染默認是基于硬件渲染的,通過本人分析其在WebView被隱藏的那一幀是采用軟件渲染,目的是減少硬件占用,讓其他UI能及時的響應。在硬件渲染情況下WebView通過onDraw方法傳遞Canvas 并將其轉行為HardwareCanvas ,并生成native的 DrawGLFunction指針,通知native做渲染。在軟件模式下,WebView通過傳遞的Canvas 通知內核webkitDraw將內核的一幀生成picture傳輸到Canvas中,執行Canvas draw bitmap。

          Android 4.4 WebView結構

          在Android 4.4系統上 Google已經將系統默認的Webkit內核替換成自己的開源項目chromium,通過之前的版本分析,我們可以看到Android 對WebView的Framework 結構進行調整使其更抽象,更重要的目的還是集成自己的開源chromium。下面我們來看看WebView的結構發生了什么樣的變化:

          目錄:

          ./frameworks/base/core/java/android/webkit

          ./frameworks/webview/chromium/java/com/android/webview/chromium

          ./external/chromium_org/android_webview

          ./external/chromium_org/content

          為了將chromium項目集成到Android 中,chromium項目抽象出Android webview這一層,之前的接口抽離這時候已經變得很明顯,Android Webview基于chromium content API這一層,第三方瀏覽器廠商也可以采用這種方式,目前所了解的廠商有Opera使用這種方式。Android 4.4WebView的渲染核心目前也沒有發生太大變化,還是基于WebView的Canvas,將Chromium composit 結構繪制到WebView Canvas上。接入chromium內核,WebView瀏覽性能大幅度提升,但是和chrome for Android還是有些不同,主要體現在一下幾點:

          1. chrome瀏覽器是多進程架構,Chromium for Android Webview 是單進程架構。

          2. chrome瀏覽器 內存占用比 Android WebView大的多。

          3. chrome支持更多的HTML5 feature。

          Android WebView展望:

          Chromium項目編譯"android_webview_apk“ 目前實現是基于Android SurfaceView,其渲染性能高于Android WebView的Canvas,歷史遺留問題以及Android 系統WebView的作用特點,這一塊隨著Chromium 和 Android項目的整合,相信值得大家期待將來的Android WebView 的渲染性能會再次大幅提升。

          本博客會持續更新Android WebView后續版本的變化,敬請關注 謝謝!

          Android 5.0 Lollipop WebView

          Lollipop版本中WebView的內核實現采用Chromium 37版本,這個版本帶來更多的安全性和穩定性。這個版本解決Android 4.4版本網頁當中請求訪問打開本地文件選擇器問題,引入新的回調接口,onShowFileChooser方法,需要此功能的可以在5.0上接上這個回調接口,并實現功能。另外這個版本提供安全許可給用戶選擇,當網頁需要訪問特殊資源時,會通知我們的應用程序,請求允許,回調接口為onPermissionRequest。之前我們也提到這個版本使得WebView默認支持WebAudio,WebGL,WebRTC等標準。

          另外Google Android 還將webview做為一個能動態更新的app,能不更新Android版本情況下,更新WebView內核。Android 5.0 Webview默認提供減少內存占用支持,并且智能選擇需要繪制的HTML document部門來提供性能。 當然開發者可以在自己應用程序需要時關閉這個選項(enableSlowWholeDocumentDraw)。


          主站蜘蛛池模板: 熟女少妇丰满一区二区| 亚洲熟女www一区二区三区| 色妞色视频一区二区三区四区| 97精品国产一区二区三区| 亚洲综合色一区二区三区小说| 国产精品一区二区四区| 久99精品视频在线观看婷亚洲片国产一区一级在线 | 日韩一区二区在线免费观看| 成人区人妻精品一区二区不卡网站| 日韩免费无码视频一区二区三区 | 无码国产精品一区二区免费3p| 中文乱码字幕高清一区二区| 亚洲av无码一区二区三区人妖| 日韩视频在线一区| 高清一区二区三区日本久| 国产香蕉一区二区在线网站| 岛国精品一区免费视频在线观看| 亚洲日本中文字幕一区二区三区| 中文字幕人妻第一区| 亚洲AV无码一区二区三区系列| 日韩人妻无码一区二区三区久久 | 中文字幕精品无码一区二区| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 秋霞鲁丝片一区二区三区| 久久精品午夜一区二区福利 | 中文字幕日韩精品一区二区三区| 亚洲一区电影在线观看| 亚洲第一区视频在线观看| 怡红院一区二区三区| 久久久久人妻一区精品| 91视频一区二区三区| 一级毛片完整版免费播放一区| 亚欧在线精品免费观看一区| 国产Av一区二区精品久久| 成人精品一区二区三区不卡免费看| 性色A码一区二区三区天美传媒 | 福利国产微拍广场一区视频在线 | 高清在线一区二区| 老熟妇仑乱一区二区视頻| 精品国产一区二区三区久久久狼| 国产日韩AV免费无码一区二区|