溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

android 4.0以上WebView不能全屏播放視頻的解決辦法

發(fā)布時(shí)間:2021-11-26 15:35:45 來(lái)源:億速云 閱讀:190 作者:柒染 欄目:移動(dòng)開(kāi)發(fā)

android 4.0以上WebView不能全屏播放視頻的解決辦法,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。

上次鄙人做了一個(gè)簡(jiǎn)單的利用webView實(shí)現(xiàn)的一個(gè)瀏覽器!其中遇到了兩個(gè)問(wèn)題,一個(gè)是將瀏覽器中需要下載的內(nèi)容托管到系統(tǒng)默認(rèn)的下載程序進(jìn)行下載,這個(gè)比較簡(jiǎn)單就不在這里討論了;另一個(gè)問(wèn)題就是我們的Android設(shè)備版本是4.0.3,不能像Android2.3那樣支持全屏播放視頻,這個(gè)問(wèn)題比較糾結(jié),但是經(jīng)過(guò)不斷的摸索,終于解決了這個(gè)問(wèn)題。在這里和大家分享一下解決方法:

1、首先定義一個(gè)VideoEnabledWebView繼承自WebView,復(fù)寫(xiě)其中的loadData,loadDataWithBaseURL,loadUrl方法,道理很簡(jiǎn)單就是在加載url或者js的時(shí)候初始化一些內(nèi)容。見(jiàn)代碼:

package com.danielme.android.webviewdemo;  import java.util.Map; import android.annotation.SuppressLint; import android.content.Context; import android.os.Handler; import android.os.Looper; import android.util.AttributeSet; import android.webkit.WebChromeClient; import android.webkit.WebView;  public class VideoEnabledWebView extends WebView {     public interface ToggledFullscreenCallback     {         public void toggledFullscreen(boolean fullscreen);     }         private VideoEnabledWebChromeClient videoEnabledWebChromeClient;     private boolean addedJavascriptInterface;        public VideoEnabledWebView(Context context)     {         super(context);         addedJavascriptInterface = false;     }        public VideoEnabledWebView(Context context, AttributeSet attrs)     {         super(context, attrs);         addedJavascriptInterface = false;     }        public VideoEnabledWebView(Context context, AttributeSet attrs, int defStyle)     {         super(context, attrs, defStyle);         addedJavascriptInterface = false;     }         /**      * Pass only a VideoEnabledWebChromeClient instance.      */     @Override     @SuppressLint ("SetJavaScriptEnabled")     public void setWebChromeClient(WebChromeClient client)     {         getSettings().setJavaScriptEnabled(true);          if (client instanceof VideoEnabledWebChromeClient)         {             this.videoEnabledWebChromeClient = (VideoEnabledWebChromeClient) client;         }          super.setWebChromeClient(client);     }         @Override     public void loadData(String data, String mimeType, String encoding)     {         addJavascriptInterface();         super.loadData(data, mimeType, encoding);     }         @Override     public void loadDataWithBaseURL(String baseUrl, String data,                                     String mimeType, String encoding,                                     String historyUrl)     {         addJavascriptInterface();         super.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);     }         @Override     public void loadUrl(String url)     {         addJavascriptInterface();         super.loadUrl(url);     }         @Override     public void loadUrl(String url, Map<String, String> additionalHttpHeaders)     {         addJavascriptInterface();         super.loadUrl(url, additionalHttpHeaders);     }         private void addJavascriptInterface()     {         System.out.println(addedJavascriptInterface);         if (!addedJavascriptInterface)         {             // Add javascript interface to be called when the video ends (must be done before page load)             addJavascriptInterface(new Object()             {             }, "_VideoEnabledWebView"); // Must match Javascript interface name of VideoEnabledWebChromeClient                         addedJavascriptInterface = true;         }     }    }

其中addJavascriptInterface方法是將一個(gè)當(dāng)前的java對(duì)象綁定到一個(gè)javascript上面,使用如下方法

webv.addJavascriptInterface(this,  "_VideoEnabledWebView");//this為當(dāng)前對(duì)象,綁定到j(luò)s的_VideoEnabledWebView上面,主要_VideoEnabledWebView的作用域是全局的。這個(gè)部分的內(nèi)容我不是很懂,提供鏈接給大家學(xué)習(xí)下,希望看懂的朋友能教教這個(gè)步驟是干嘛的?。╤ttp://www.oschina.net/code/snippet_232612_8531)

2、定義一個(gè)類VideoEnabledWebChromeClient繼承自WebChromeClient,這個(gè)WebChromeClient中的onShowCustomView方法就是播放網(wǎng)絡(luò)視頻時(shí)會(huì)被調(diào)用的方法,onHideCustomView方法就是視頻播放完成會(huì)被調(diào)用的。其中有個(gè)構(gòu)造函數(shù)需要提出來(lái):

public VideoEnabledWebChromeClient(View activityNonVideoView, ViewGroup activityVideoView, View loadingView, VideoEnabledWebView webView)     {         this.activityNonVideoView = activityNonVideoView;         this.activityVideoView = activityVideoView;         this.loadingView = loadingView;         this.webView = webView;         this.isVideoFullscreen = false;     }

這個(gè)構(gòu)造函數(shù)中的參數(shù),***個(gè)是webView的父布局,activityVideoView是另外的一個(gè)占滿整個(gè)屏幕的布局,loadingView是播放器的那個(gè)顯示緩沖狀態(tài)的view,webView就是webView啦!

見(jiàn)activity_main.xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout_height="match_parent"     tools:context=".MainActivity" >     <RelativeLayout         android:id="@+id/nonVideoLayout"         android:layout_width="match_parent"         android:layout_height="match_parent" >         <com.danielme.android.webviewdemo.VideoEnabledWebView             android:id="@+id/webView"             android:layout_width="match_parent"             android:layout_height="match_parent" />     </RelativeLayout>     <FrameLayout         android:id="@+id/videoLayout"         android:layout_width="match_parent"         android:layout_height="match_parent" >     </FrameLayout> </RelativeLayout>

不多說(shuō)了,直接貼代碼VideoEnabledWebChromeClient.java代碼。

package com.danielme.android.webviewdemo;  import android.app.ActionBar.LayoutParams; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnErrorListener; import android.media.MediaPlayer.OnPreparedListener; import android.view.View; import android.view.ViewGroup; import android.webkit.WebChromeClient; import android.widget.FrameLayout; import android.widget.VideoView;  public class VideoEnabledWebChromeClient extends WebChromeClient implements OnPreparedListener, OnCompletionListener, OnErrorListener {     public interface ToggledFullscreenCallback     {         public void toggledFullscreen(boolean fullscreen);     }     private View activityNonVideoView;     private ViewGroup activityVideoView;     private View loadingView;     private VideoEnabledWebView webView;     private boolean isVideoFullscreen; // Indicates if the video is being displayed using a custom view (typically full-screen)     private FrameLayout videoViewContainer;     private CustomViewCallback videoViewCallback;     private ToggledFullscreenCallback toggledFullscreenCallback;     /**      * Never use this constructor alone.      * This constructor allows this class to be defined as an inline inner class in which the user can override methods      */     public VideoEnabledWebChromeClient()     {     }     /**      * Builds a video enabled WebChromeClient.      * @param activityNonVideoView A View in the activity's layout that contains every other view that should be hidden when the video goes full-screen.      * @param activityVideoView A ViewGroup in the activity's layout that will display the video. Typically you would like this to fill the whole layout.      */     public VideoEnabledWebChromeClient(View activityNonVideoView, ViewGroup activityVideoView)     {         this.activityNonVideoView = activityNonVideoView;         this.activityVideoView = activityVideoView;         this.loadingView = null;         this.webView = null;         this.isVideoFullscreen = false;     }     /**      * Builds a video enabled WebChromeClient.      * @param activityNonVideoView A View in the activity's layout that contains every other view that should be hidden when the video goes full-screen.      * @param activityVideoView A ViewGroup in the activity's layout that will display the video. Typically you would like this to fill the whole layout.      * @param loadingView A View to be shown while the video is loading (typically only used in API level <11). Must be already inflated and without a parent view.      */     public VideoEnabledWebChromeClient(View activityNonVideoView, ViewGroup activityVideoView, View loadingView)     {         this.activityNonVideoView = activityNonVideoView;         this.activityVideoView = activityVideoView;         this.loadingView = loadingView;         this.webView = null;         this.isVideoFullscreen = false;     }     /**      * Builds a video enabled WebChromeClient.      * @param activityNonVideoView A View in the activity's layout that contains every other view that should be hidden when the video goes full-screen.      * @param activityVideoView A ViewGroup in the activity's layout that will display the video. Typically you would like this to fill the whole layout.      * @param loadingView A View to be shown while the video is loading (typically only used in API level <11). Must be already inflated and without a parent view.      * @param webView The owner VideoEnabledWebView. Passing it will enable the VideoEnabledWebChromeClient to detect the HTML5 video ended event and exit full-screen.      * Note: The web page must only contain one video tag in order for the HTML5 video ended event to work. This could be improved if needed (see Javascript code).      */     public VideoEnabledWebChromeClient(View activityNonVideoView, ViewGroup activityVideoView, View loadingView, VideoEnabledWebView webView)     {         this.activityNonVideoView = activityNonVideoView;         this.activityVideoView = activityVideoView;         this.loadingView = loadingView;         this.webView = webView;         this.isVideoFullscreen = false;     }     /**      * Indicates if the video is being displayed using a custom view (typically full-screen)      * @return true it the video is being displayed using a custom view (typically full-screen)      */     public boolean isVideoFullscreen()     {         return isVideoFullscreen;     }     /**      * Set a callback that will be fired when the video starts or finishes displaying using a custom view (typically full-screen)      * @param callback A VideoEnabledWebChromeClient.ToggledFullscreenCallback callback      */     public void setOnToggledFullscreen(ToggledFullscreenCallback callback)     {         this.toggledFullscreenCallback = callback;     }     @Override     public void onShowCustomView(View view, CustomViewCallback callback)     {         if (view instanceof FrameLayout)         {             // A video wants to be shown             FrameLayout frameLayout = (FrameLayout) view;             View focusedChild = frameLayout.getFocusedChild();             // Save video related variables             this.isVideoFullscreen = true;             this.videoViewContainer = frameLayout;             this.videoViewCallback = callback;             // Hide the non-video view, add the video view, and show it             activityNonVideoView.setVisibility(View.GONE);                         activityVideoView.addView(videoViewContainer, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));             activityVideoView.setVisibility(View.VISIBLE);             if (focusedChild instanceof VideoView)             {                 // VideoView (typically API level <11)                 VideoView videoView = (VideoView) focusedChild;                 // Handle all the required events                 videoView.setOnPreparedListener(this);                 videoView.setOnCompletionListener(this);                 videoView.setOnErrorListener(this);             }             else // Usually android.webkit.HTML5VideoFullScreen$VideoSurfaceView, sometimes android.webkit.HTML5VideoFullScreen$VideoTextureView             {                 // HTML5VideoFullScreen (typically API level 11+)                 // Handle HTML5 video ended event                 if (webView != null && webView.getSettings().getJavaScriptEnabled())                 {                     // Run javascript code that detects the video end and notifies the interface                     String js = "javascript:";                     js += "_ytrp_html5_video = document.getElementsByTagName('video')[0];";                     js += "if (_ytrp_html5_video !== undefined) {";                     {                         js += "function _ytrp_html5_video_ended() {";                         {                             js += "_ytrp_html5_video.removeEventListener('ended', _ytrp_html5_video_ended);";                             js += "_VideoEnabledWebView.notifyVideoEnd();"; // Must match Javascript interface name and method of VideoEnableWebView                         }                         js += "}";                         js += "_ytrp_html5_video.addEventListener('ended', _ytrp_html5_video_ended);";                     }                     js += "}";                     webView.loadUrl(js);                 }             }              // Notify full-screen change             if (toggledFullscreenCallback != null)             {                 toggledFullscreenCallback.toggledFullscreen(true);             }         }     }     @Override     public void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback) // Only available in API level 14+     {         onShowCustomView(view, callback);     }     @Override     public void onHideCustomView()     {         // This method must be manually (internally) called on video end in the case of VideoView (typically API level <11)         // This method must be manually (internally) called on video end in the case of HTML5VideoFullScreen (typically API level 11+) because it's not always called automatically         // This method must be manually (internally) called on back key press (from this class' onBackPressed() method)         if (isVideoFullscreen)         {             // Hide the video view, remove it, and show the non-video view             activityVideoView.setVisibility(View.GONE);//播放視頻的             activityVideoView.removeView(videoViewContainer);             activityNonVideoView.setVisibility(View.VISIBLE);              // Call back             if (videoViewCallback != null) videoViewCallback.onCustomViewHidden();              // Reset video related variables             isVideoFullscreen = false;             videoViewContainer = null;             videoViewCallback = null;              // Notify full-screen change             if (toggledFullscreenCallback != null)             {                 toggledFullscreenCallback.toggledFullscreen(false);             }         }     }     @Override     public View getVideoLoadingProgressView() // Video will start loading, only called in the case of VideoView (typically API level <11)     {         if (loadingView != null)         {             loadingView.setVisibility(View.VISIBLE);             return loadingView;         }         else         {             return super.getVideoLoadingProgressView();         }     }     @Override     public void onPrepared(MediaPlayer mp) // Video will start playing, only called in the case of VideoView (typically API level <11)     {         if (loadingView != null)         {             loadingView.setVisibility(View.GONE);         }     }      @Override     public void onCompletion(MediaPlayer mp) // Video finished playing, only called in the case of VideoView (typically API level <11)     {         onHideCustomView();     }     @Override     public boolean onError(MediaPlayer mp, int what, int extra) // Error while playing video, only called in the case of VideoView (typically API level <11)     {         return false; // By returning false, onCompletion() will be called     }     /**      * Notifies the class that the back key has been pressed by the user.      * This must be called from the Activity's onBackPressed(), and if it returns false, the activity itself should handle it. Otherwise don't do anything.      * @return Returns true if the event was handled, and false if it is not (video view is not visible)      */     public boolean onBackPressed()     {         if (isVideoFullscreen)         {             onHideCustomView();             return true;         }         else         {             return false;         }     }     }

主要是onShowCustomView方法中,當(dāng)這個(gè)方法被調(diào)用,將含有webView的那個(gè)父布局隱藏掉(GONE),然后將***個(gè)參數(shù)view加到布局中。獲取***個(gè)參數(shù)view的子控件childView,進(jìn)行判斷childView是否屬于VideoView(Android  4.0之前是VideoView),如果是Android  4.0之后,則會(huì)執(zhí)行else中的代碼,新建String類型js代碼,然后調(diào)用loadUrl(js)就可以進(jìn)行視頻播放了。其中我個(gè)人不知道它是如何通過(guò)js來(lái)播放視頻的,我覺(jué)得和之前的addJavascriptInterface這個(gè)方法有一定關(guān)系,希望知道如何實(shí)現(xiàn)的能夠指導(dǎo)一下本人。其它的函數(shù)就很好理解了。

看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝您對(duì)億速云的支持。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI