webview 載入h5頁面,播放視訊+全屏,實現簡單封裝
前段時間專案中用到了h5。從目前的市場來看,原生和h5的結合受到很多公司的歡迎,剛好最近微信也推出了它自己的“小程式”,這在Android程式設計師之間也掀起了波瀾,引起大家討論。
個人覺得Google提供的webview有很多的坑,我這次就踩了不少,比如在某些版本的系統上某個方法不會執行,或者執行的順序不一樣,有的方法會多執行一次,說白了就是相容性做的很差,究其主要原因,是Android4.4前後webview 的核心發生了變化。那麼Google難道沒有發現這個問題?Google肯定發現了,那為什麼還做的這麼差勁呢,個人覺得有這麼一個原因吧,Google想大力推廣自己的Android,如果webview做的很好了,h5的應用勢必會越來越廣泛,勢必會有很多不大的公司在一個app中更多的選擇使用h5。因為它開發方便,維護成本更低,有了問題不用版本迭代,在後臺直接就改了(這些是現在原生app面臨的一大問題,但是有解決辦法)。
下面就來說說我在這次webview開發中遇到的問題,和對webview的一個簡單的封裝。
首先上效果圖:
下面主要說下實現的方法:
先需要一個webview,這個webview用來載入h5的頁面,在半屏播放的時候也用這個webview,全屏的時候用一個framelayout,此時需要把webview隱藏了,xml的大概佈局如下:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <FrameLayout android:id="@+id/video_view" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" > </FrameLayout> <WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>
這兒其實還可以自定義一個404顯示的view,在沒網或者url載入失敗的時候去顯示,這樣使用者的體驗效果要好一點。
接下來就是webview和fragmentlayout的獲取
videoview = (FrameLayout) findViewById(R.id.video_view);
webview = (WebView) findViewById(R.id.webview);
下面就是webview的setting的一個設定了,在這裡沒什麼好說的,建議大家一定要開啟快取。本人在這兒做的時候,在程式碼中通過判斷sdk的版本,開啟了硬體加速的功能,但是導致的原因是隻有聲音,沒有影象,不設定webview的硬體加速就沒問題,個人感覺主要和h5有很大的關係。
其次為了提高渲染的速度,建議大家可以開啟gpu的渲染
getWindow().setFlags(//強制開啟GPU渲染
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
接下來就是設定webview的檢視
webview.setWebViewClient(new CustomWebViewClient());
我們在程式碼中自定義一個類CustomWebViewClient,主要實現其幾個方法,實現對webview開始載入,載入完成,載入失敗回撥的處理
private final class CustomWebViewClient extends WebViewClient {
//url載入失敗
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
<span style="white-space:pre"> </span> //做自己的一些處理,比如載入我們自定義的view或者給使用者一個提示
}
<span style="white-space:pre"> </span>//頁面載入完成的時候呼叫
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@SuppressLint("NewApi")
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
<span style="white-space:pre"> </span> //可以做一些載入完成的處理,比如隱藏正在載入的動畫
}
<span style="white-space:pre"> </span>//頁面開始載入的時候呼叫
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
<pre name="code" class="java" style="font-size: 18px;"><span style="white-space:pre"> </span> //可以做一些載入完成的處理,比如顯示正在載入的動畫
} }
最後就到視訊播放了,視訊全屏播放的時候需要用到一個類WebChromeClient,我們只要自定義一個類,去實現它裡面的2個方法即可
/**
* 處理Javascript的對話方塊、網站圖示、網站標題以及網頁載入進度等
*
* @author
*/
public class xWebChromeClient extends WebChromeClient {
private Bitmap xdefaltvideo;
private View xprogressvideo;
@Override
// 播放網路視訊時全屏會被呼叫的方法
public void onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
if(a!=null){
a.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
if(webview!=null){
webview.setVisibility(View.GONE);
}
// 如果一個檢視已經存在,那麼立刻終止並新建一個
if (xCustomView != null&&callback!=null) {
callback.onCustomViewHidden();
return;
}
if (view != null&&videoview!=null) {
videoview.addView(view);
xCustomView = view;
}
if(xCustomViewCallback!=null){
xCustomViewCallback = callback;
}
if(videoview!=null){
videoview.setVisibility(View.VISIBLE);
}
}
@SuppressLint("NewApi")
@Override
// 視訊播放退出全屏會被呼叫的
public void onHideCustomView() {
if (xCustomView == null||videoview==null)// 不是全屏播放狀態
return;
videoview.removeView(xCustomView);
if(a!=null){
a.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
xCustomView.setVisibility(View.GONE);
xCustomView = null;
videoview.setVisibility(View.GONE);
if(xCustomViewCallback!=null){
xCustomViewCallback.onCustomViewHidden();
}
if(webview!=null){
webview.setVisibility(View.VISIBLE);
}
if(setting!=null){
setting.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);// 排版適應螢幕
}
}
// 視訊載入新增預設圖示
@Override
public Bitmap getDefaultVideoPoster() {
if (xdefaltvideo == null) {
xdefaltvideo = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
}
return xdefaltvideo;
}
// 視訊載入時程序loading
@SuppressLint("InflateParams")
@Override
public View getVideoLoadingProgressView() {
if (xprogressvideo == null) {
LayoutInflater inflater = LayoutInflater.from(a);
xprogressvideo = inflater.inflate(R.layout.video_loading_progress, null);
}
return xprogressvideo;
}
// 網頁標題
@Override
public void onReceivedTitle(WebView view, String title) {
// a.setTitle(title)
//view.getSettings().setBlockNetworkImage(false);
}
@Override
// 當WebView進度改變時更新視窗進度
public void onProgressChanged(WebView view, int newProgress) {
a.getWindow().setFeatureInt(Window.FEATURE_PROGRESS, newProgress * 100);
}
}
提示:在全屏播放的activity上一定要加上android:configChanges="orientation|keyboardHidden|screenSize"
到這兒視訊播放也就差不多了,但是相容性還是大問題,這兒就需要我們自己慢慢調了。在這兒我給大家推薦一個相容性很好的webview框架,就是騰訊X5,我自己也下載的demo然後跑了一下,確實要比Google的webview牛掰了很多,目前在微信,QQ,QQ瀏覽器中解析h5都用的X5,這是他們自己寫的核心,在相容性,安全性,美觀性上都有很大的提升。