還在用Android自帶的WebView組件?太Out了!
由于公司的一個產品,可能需要在APK內部內嵌WebView,以顯示HTML內容,因此花了一點時間做了一些技術方面的小嘗試。本文主要針對這個過程做一些簡單的記錄。
一、為何不直接使用內置的WebView組件?
用Android自帶的WebView組件,做過一些較復雜應用的人應該都會發現,這個自帶的組件很多時候真是讓人無力吐嘈,主要理由有二:
- Android中的WebView組件,內存泄漏的問題一直沒有非常有效的解決方案,讓程序猿們痛不欲生。
- Android中的WebView組件,在4.4以前的版本是WebKit的內核,4.4以后才換成chromium的內核,同時鑒于Google版本帝的風格,因此也導致各個版本之間的運行效率參差不齊。而且即使是chromium內核的版本,也因為要考慮兼容以前的版本,而變得不是那么美好。
也正因為如此,考慮到為了更好的體驗,以及避免后續可能帶來的更多麻煩,所以我試圖站在巨人的肩膀上,尋找一個第三方可靠的WebView組件。
二、Crosswalk與TBS服務
Crosswalk:據說各種流暢、強大,且Cordova在新的版本當中也將默認支持Crosswalk。具體的介紹可以參考: 如何輕松搞定Crosswalk之嵌入模式
TBS服務:由騰訊QQ瀏覽器團隊出品。支持“共享X5內核模式”和“獨立下載X5內核模式”。具體可參考 TBS騰訊瀏覽服務
在結合我的實際需求,綜合比較了上述兩套解決方案之后,最終我還是選擇了TBS服務,一是因為我不希望最終的APP體積突然增多了20M(Crosswalk需要整體打包進APP),另一方面是小馬哥的微信、手機QQ等APP在國內的裝機量實在是太高了,而且能夠支持以共享X5內核的方式,在自己的APP里面直接調用微信或手機QQ的瀏覽服務,我認為未嘗不是一種好的解決方案。
三、最終實現
好吧,必須承認我很久沒有碰過Android了,所以因為一時的心血來潮,我選擇了Google主推的Android Studio來體驗,而不是以前習慣的Eclipse。這一下,就給自己找了個大麻煩,說多了都是淚……也只能自我安慰,我這是跟著時代與時俱進的成長了……
首先要說明的,Android Studio采用的是Gradle來構建項目,因此每一個項目都需要在國外的官網上下載對應版本的Gradle,由于眾所周知的原因,這個過程那真是相當之漫長。最可悲的是我一開始不知道,苦苦守候了半個多小時,界面一直卡在這一步,如下圖所示:
1.png
解決的方法很簡單,網上也有很多,例如換V*N、代理之類的,我采用了最簡單粗暴的方式。根據Android Studio的運行原理,每一個新建的項目,都會在C:\Users\Administrator.gradle\wrapper\dists\gradle-2.2.1-all目錄下創建一個加碼的文件夾,如下圖所示:
2.png
找到時間最接近的這個文件夾,然后將適先下載好的、對應版本的gradle文件放里面、并解壓,最終效果如下圖所示:
3.png
最后強制結束Android Studio并重啟,恭喜你,不出意外的話,這個時候項目文件就可以順利并加載了!呃……如果要是出了意外的話,那……就只好繼續Google了……(別告訴我你不會KX上網~)
解決了上述問題之后,我們就可以正式開始進入編碼階段了。這里推薦大家可以參考TBS提供的官方示例,如果嫌麻煩的話,可以簡單參考我下面的示例。
第一步,下載jar包,并加載到項目中,下載地址 TBS——SDK下載 。
第二步,在xml布局中加入騰訊自定義的WebView。
<com.tencent.smtt.sdk.WebView
android:id="@+id/tbsContent"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
第三步,申請騰訊X5所需權限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
第四步,在Activity代碼文件中使用:
package net.ltpower.tbsapp;
import android.graphics.PixelFormat;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.tencent.smtt.sdk.QbSdk;
import com.tencent.smtt.sdk.WebSettings;
import com.tencent.smtt.sdk.WebView;
import com.tencent.smtt.sdk.WebViewClient;
public class MainActivity extends ActionBarActivity {
com.tencent.smtt.sdk.WebView tbsContent;
private String url = "http://www.91suke.com/s/b9271044";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getWindow().setFormat(PixelFormat.TRANSLUCENT);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
initView();
}
private void initView() {
tbsContent = (com.tencent.smtt.sdk.WebView)findViewById(R.id.tbsContent);
tbsContent.loadUrl(url);
WebSettings webSettings = tbsContent.getSettings();
webSettings.setJavaScriptEnabled(true);
tbsContent.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && tbsContent.canGoBack()) {
tbsContent.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
好了,到這一步,連接真機,運行你的Android程序,應該就可以看到如下效果了:
4.png
那么最關鍵的問題是,如何判斷已經成功接入了騰訊的X5內核瀏覽服務呢?辨別是否使用x5webview的方法:
顯示網頁文字時,可通過長按選擇文字的標識判斷,如下水滴狀選擇效果是x5webview 的標志:
當然,上述的代碼僅僅只是一個簡單的測試案例,實際的生產使用環境中還有很多需要考慮的地方,例如APP切換到后臺運行的資源的釋放等等。具體的實現方式,建議大家可以參考TBS官方的示例。
來自:http://www.jianshu.com/p/d3ef9c62b6c8