网站聚合优化,wordpress短代码下载按钮,jsp环保主题网站代做,wordpress 自定义查询一、引言 近期#xff0c;我发现电视家、火星直播等在线看电视直播的软件都已倒闭#xff0c;而我奶奶也再无法通过这些平台看电视了。她已六十多岁#xff0c;快七十岁啦。这些平台的倒下对我来说其实没有多大的影响#xff0c;但是对于文化不多的她而言#xff0c;生活中…一、引言 近期我发现电视家、火星直播等在线看电视直播的软件都已倒闭而我奶奶也再无法通过这些平台看电视了。她已六十多岁快七十岁啦。这些平台的倒下对我来说其实没有多大的影响但是对于文化不多的她而言生活中却是少了一大乐趣。因为自己学过编程所以我想帮她解决这个问题。她只听得懂白话又最爱看“广东珠江台”因此我通过Android的编程技术为她专门定制一款可以自动看广东珠江台的App打开即用免了点来点去的麻烦。虽说需求很小、只够她一人使用但实现起来却并不简单呀。通过两天时间的深入钻研最终我还是把这个小需求给实现了。为此编写一篇博客如果日后自己还需要解决这样的问题时我就直接ctrlc加ctrlv。当然也希望这篇博客能够为你提供一些指导和帮助。 二、访问网页视频自动播放的实现思路 由于许多的m3u8链接都已经失效现在看电视直播只能通过一些官方网页来实现比如央视网等等。那么访问网页的话是可以通过Android的WebView来实现实现的方法非常简单就是在Activity界面之中添加一个WebView空间然后通过下面的代码来访问网页
main_wv findViewById(R.id.main_wv);
main_wv.setWebViewClient(new WebViewClient());
main_wv.setWebChromeClient(new WebChromeClient());
main_wv.loadUrl(https://***.***); 但是这样的话最多也只能够竖屏中观看视频显示十分地有限而且还不会自动播放如图 所以这里先介绍实现网页访问自动播放的思路。WebView可以通过自定义的设置来控制它是否支持JavaScript脚本注入即通过js来实现网页视频的自动播放。第一步是对WebView进行设置而第二步是执行js自动播放视频的脚本代码如下 设置WebView支持js脚本
WebSettings settings main_wv.getSettings(); // main_wv为WebView控件
settings.setJavaScriptEnabled(true); 执行js自动播放视频的脚本
String js javascript:;
js var videos document.getElementsByTagName(video);;
js var video_last;;
js var video videos[videos.length-1];;
js if (video ! undefined video ! video_last) {;
{js video_last video;;js function video_start() {;{js _VideoEnabledWebView.notifyVideoStart();;}js };js video.addEventListener(play, video_start);;
}
js };
main_wv.loadUrl(js); // main_wv为WebView控件 忘了介绍该js脚本在什么时候执行了。这里补充一下为了使得页面自动播放视频需要重写一个WebViewClient类类名可以随你定义比如“MyWebViewClient”然后重写public void onPageFinished(WebView view, String url)方法如下
Override
public void onPageFinished(WebView view, String url) {super.onPageFinished(view, url);String js javascript:;js var videos document.getElementsByTagName(video);;js var video_last;;js var video videos[videos.length-1];;js if (video ! undefined video ! video_last) {;{js video_last video;;js function video_start() {;{js _VideoEnabledWebView.notifyVideoStart();;}js };js video.addEventListener(play, video_start);;}js };main_wv.loadUrl(js); // main_wv为WebView控件
} 至此还请记得改
main_wv.setWebViewClient(new WebViewClient()); // main_wv为WebView控件 为
main_wv.setWebViewClient(new MyWebViewClient()); // main_wv为WebView控件 这样在访问网页时视频就可以自动播放啦。 三、网页自动全屏思路 网页全屏的实现思路比较复杂因为Android开发者的初衷是使网页设计者无法通过js的方式直接全屏地播放视频。也就是说通过js注入的方式无法直接在WebView中实现网页的全屏播放。为什么呢根据其他人的说法这是因为Android开发者担心你的手机不小心访问到一个流氓网页然后该网页直接全屏使你的手机失控被它播放的视频霸占许久、不能退出。我想了想觉得这个理由倒是有些许合理的。因此执行js脚本注入无法直接在WebView中实现网页视频的全屏播放。 但是网页全屏的实现是完全没有问题的。大体的思路是重写WebChromeClient和WebView这两个类通过重写其中的内部方法在加载完网页后再调用js脚本注入进而触发视频的全屏播放。而触发视频的全屏播放的js脚本为
javascript:(
function() { var videos document.getElementsByTagName(video); var video videos[0]; if (!document.webkitFullScreen video.webkitEnterFullscreen) { video.webkitEnterFullscreen(); } })() 由于实现的细节很多再加上我只是简单地研究了一下所以没法更详细地展开说说了。请大家看后边“全部代码”的章节部分了解更多细节。 四、手机默认横屏思路 手机默认横屏的思路实现起来非常简单简单得不得了只需要在Manifest.xml这个清单文件中对指定的Activity声明相关的属性即可。例如用于播放的Activity为MainActivity那么就这样设置
activity android:name.MainActivityandroid:themeandroid:style/Theme.NoTitleBar.Fullscreenandroid:screenOrientationlandscapeandroid:configChangesorientation|screenSize|keyboardHiddenandroid:hardwareAcceleratedtrue
/activity 其中最关键的两行代码为
android:themeandroid:style/Theme.NoTitleBar.Fullscreen
android:screenOrientationlandscape 上面一行说的是让app在手机上运行时不显示标题栏(这个可以看你个人需求有的人喜欢留着有的人喜欢去掉)而下面一行则是实现横屏的开关landscape指的是风景意为通过手机横屏的方式欣赏图片中的风景以尽可能地使你更加清楚地目睹一张横向的风景图。 五、全部代码 项目的代码目录其中画横线部分是重点我从创建项目到生成可运行且有效果的App只改动过这些文件。下面我将每个框中的文件中的代码罗列出来。 AndroidManifest.xml
?xml version1.0 encodingutf-8?
manifest xmlns:androidhttp://schemas.android.com/apk/res/androidpackage***.***.******uses-permission android:nameandroid.permission.INTERNET /uses-permission android:nameandroid.permission.ACCESS_NETWORK_STATE/applicationandroid:allowBackuptrueandroid:iconmipmap/ic_launcherandroid:labelstring/app_nameandroid:roundIconmipmap/ic_launcher_roundandroid:supportsRtltrueandroid:themestyle/AppThemeactivity android:name.MainActivityandroid:hardwareAcceleratedtrueandroid:themeandroid:style/Theme.NoTitleBar.Fullscreenandroid:screenOrientationlandscapeintent-filteraction android:nameandroid.intent.action.MAIN /category android:nameandroid.intent.category.LAUNCHER //intent-filter/activity/application
/manifest MainActivity.java
package ***.***.***;import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.view.ViewGroup;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;public class MainActivity extends Activity {VideoEnabledWebView mainWebView;RelativeLayout mainNonVideoRelativeLayout;ViewGroup mainVideoLayout;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);initView(); // initialize ui componentssetWebView(); // set webviews settingsloadVideoUrl(); // load video url}private void initView() {setContentView(R.layout.activity_main);mainNonVideoRelativeLayout (RelativeLayout) findViewById(R.id.main_rl_non_video);mainVideoLayout (ViewGroup)findViewById(R.id.main_rl_video);}SuppressLint(SetJavaScriptEnabled)private void setWebView() {// create a webview instancemainWebView new VideoEnabledWebView(this);mainWebView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));// add the webview instance to the main layoutmainNonVideoRelativeLayout.addView(mainWebView);// set general settings of webviewWebSettings settings mainWebView.getSettings();settings.setAllowFileAccess(true);settings.setBuiltInZoomControls(false);settings.setJavaScriptEnabled(true);settings.setBuiltInZoomControls(false);// create a WebChromeClient instance and use it to set the webviewVideoEnabledWebChromeClient videoEnabledWebChromeClient new VideoEnabledWebChromeClient(mainNonVideoRelativeLayout, mainVideoLayout,null, mainWebView);mainWebView.setWebChromeClient(videoEnabledWebChromeClient);// create a WebViewClient for webviewmainWebView.setWebViewClient(new WebViewClient(){Overridepublic void onPageFinished(WebView view, String url) {super.onPageFinished(view, url);// execute a javascript to automatically play the videoString js javascript:;js var videos document.getElementsByTagName(video);;js var video_last;;js var video videos[videos.length-1];;js if (video ! undefined video ! video_last) {;{js video_last video;;js function video_start() {;{js _VideoEnabledWebView.notifyVideoStart();;}js };js video.addEventListener(play, video_start);;}js };mainWebView.loadUrl(js);}});}private void loadVideoUrl() {mainWebView.loadUrl(https://******); // your url that contains the video}
} activity_main.xml
?xml version1.0 encodingutf-8?
androidx.constraintlayout.widget.ConstraintLayout xmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:toolshttp://schemas.android.com/toolsandroid:layout_widthmatch_parentandroid:layout_heightmatch_parenttools:context.MainActivityRelativeLayoutandroid:idid/main_rl_non_videoandroid:layout_widthmatch_parentandroid:layout_heightmatch_parent /RelativeLayoutRelativeLayoutandroid:idid/main_rl_videoandroid:layout_widthmatch_parentandroid:layout_heightmatch_parent /RelativeLayout
/androidx.constraintlayout.widget.ConstraintLayout VideoEnabledWebChromeClient.java
package ***.***.***;import android.media.MediaPlayer;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebChromeClient;
import android.widget.FrameLayout;public class VideoEnabledWebChromeClient extends WebChromeClient implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener {public interface ToggledFullscreenCallback {void toggledFullscreen(boolean fullscreen);}private View activityNonVideoView;private ViewGroup activityVideoView;private View loadingView;private VideoEnabledWebView webView;// Indicates if the video is being displayed using a custom view (typically full-screen)private boolean isVideoFullscreen;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*/SuppressWarnings(unused)public VideoEnabledWebChromeClient() {}/*** Builds a video enabled WebChromeClient.* param activityNonVideoView A View in the activitys layout that contains every other view that should be hidden when the video goes full-screen.* param activityVideoView A ViewGroup in the activitys layout that will display the video. Typically you would like this to fill the whole layout.*/SuppressWarnings(unused)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 activitys layout that contains every other view that should be hidden when the video goes full-screen.* param activityVideoView A ViewGroup in the activitys 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 not attached to a parent view.*/SuppressWarnings(unused)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 activitys layout that contains every other view that should be hidden when the video goes full-screen.* param activityVideoView A ViewGroup in the activitys 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 not attached to 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).*/SuppressWarnings(unused)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*/SuppressWarnings(unused)public void setOnToggledFullscreen(ToggledFullscreenCallback callback) {this.toggledFullscreenCallback callback;}Overridepublic void onShowCustomView(View view, CustomViewCallback callback) {if (view instanceof FrameLayout) {// A video wants to be shownFrameLayout frameLayout (FrameLayout) view;View focusedChild frameLayout.getFocusedChild();// Save video related variablesthis.isVideoFullscreen true;this.videoViewContainer frameLayout;this.videoViewCallback callback;// Hide the non-video view, add the video view, and show itactivityNonVideoView.setVisibility(View.INVISIBLE);activityVideoView.addView(videoViewContainer, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));activityVideoView.setVisibility(View.VISIBLE);if (focusedChild instanceof android.widget.VideoView) {// android.widget.VideoView (typically API level 11)android.widget.VideoView videoView (android.widget.VideoView) focusedChild;// Handle all the required eventsvideoView.setOnPreparedListener(this);videoView.setOnCompletionListener(this);videoView.setOnErrorListener(this);} else {// Other classes, including:// - android.webkit.HTML5VideoFullScreen$VideoSurfaceView, which inherits from android.view.SurfaceView (typically API level 11-18)// - android.webkit.HTML5VideoFullScreen$VideoTextureView, which inherits from android.view.TextureView (typically API level 11-18)// - com.android.org.chromium.content.browser.ContentVideoView$VideoSurfaceView, which inherits from android.view.SurfaceView (typically API level 19)// Handle HTML5 video ended event only if the class is a SurfaceView// Test case: TextureView of Sony Xperia T API level 16 doesnt work fullscreen when loading the javascript belowif (webView ! null webView.getSettings().getJavaScriptEnabled() focusedChild instanceof SurfaceView) {// Run javascript code that detects the video end and notifies the Javascript interfaceString js javascript:;js var _ytrp_html5_video_last;;js var _ytrp_html5_video document.getElementsByTagName(video)[0];;js if (_ytrp_html5_video ! undefined _ytrp_html5_video ! _ytrp_html5_video_last) {;{js _ytrp_html5_video_last _ytrp_html5_video;;js function _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 changeif (toggledFullscreenCallback ! null) {toggledFullscreenCallback.toggledFullscreen(true);}}}Override// Available in API level 14, deprecated in API level 18public void onShowCustomView(View view, int requestedOrientation, CustomViewCallback callback) {onShowCustomView(view, callback);}Override// This method should be manually called on video end in all cases because its not always called automatically.// This method must be manually called on back key press (from this class onBackPressed() method).public void onHideCustomView() {if (isVideoFullscreen) {// Hide the video view, remove it, and show the non-video viewactivityVideoView.setVisibility(View.INVISIBLE);activityVideoView.removeView(videoViewContainer);activityNonVideoView.setVisibility(View.VISIBLE);// Call back (only in API level 19, because in API level 19 with chromium webview it crashes)if (videoViewCallback ! null !videoViewCallback.getClass().getName().contains(.chromium.)) {videoViewCallback.onCustomViewHidden();}// Reset video related variablesisVideoFullscreen false;videoViewContainer null;videoViewCallback null;// Notify full-screen changeif (toggledFullscreenCallback ! null) {toggledFullscreenCallback.toggledFullscreen(false);}}}Override// Video will start loadingpublic View getVideoLoadingProgressView() {if (loadingView ! null) {loadingView.setVisibility(View.VISIBLE);return loadingView;} else {return super.getVideoLoadingProgressView();}}Override// Video will start playing, only called in the case of android.widget.VideoView (typically API level 11)public void onPrepared(MediaPlayer mp) {if (loadingView ! null) {loadingView.setVisibility(View.GONE);}}Override// Video finished playing, only called in the case of android.widget.VideoView (typically API level 11)public void onCompletion(MediaPlayer mp) {onHideCustomView();}Override// Error while playing video, only called in the case of android.widget.VideoView (typically API level 11)public boolean onError(MediaPlayer mp, int what, int extra) {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 Activitys onBackPressed(), and if it returns false, the activity itself should handle it. Otherwise dont do anything.* return Returns true if the event was handled, and false if was not (video view is not visible)*/SuppressWarnings(unused)public boolean onBackPressed() {if (isVideoFullscreen) {onHideCustomView();return true;} else {return false;}}
} VideoEnabledWebView.java
package ***.***.***;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;import java.util.Map;public class VideoEnabledWebView extends WebView {public class JavascriptInterface {android.webkit.JavascriptInterfaceSuppressWarnings(unused)// Must match Javascript interface method of VideoEnabledWebChromeClientpublic void notifyVideoEnd() {// This code is not executed in the UI thread, so we must force that to happennew Handler(Looper.getMainLooper()).post(new Runnable() {Overridepublic void run() {if (videoEnabledWebChromeClient ! null) {videoEnabledWebChromeClient.onHideCustomView();}}});}android.webkit.JavascriptInterfaceSuppressWarnings(unused)// Must match Javascript interface method of VideoEnabledWebChromeClientpublic void notifyVideoStart() {// This code is not executed in the UI thread, so we must force that to happennew Handler(Looper.getMainLooper()).post(new Runnable() {Overridepublic void run() {loadUrl(javascript:( function() { var videos document.getElementsByTagName(video); var video videos[0]; if (!document.webkitFullScreen video.webkitEnterFullscreen) { video.webkitEnterFullscreen(); } })());}});}}private VideoEnabledWebChromeClient videoEnabledWebChromeClient;private boolean addedJavascriptInterface;SuppressWarnings(unused)public VideoEnabledWebView(Context context) {super(context);addedJavascriptInterface false;}SuppressWarnings(unused)public VideoEnabledWebView(Context context, AttributeSet attrs) {super(context, attrs);addedJavascriptInterface false;}SuppressWarnings(unused)public VideoEnabledWebView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);addedJavascriptInterface 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)*/SuppressWarnings(unused)public boolean isVideoFullscreen() {return videoEnabledWebChromeClient ! null videoEnabledWebChromeClient.isVideoFullscreen();}/*** Pass only a VideoEnabledWebChromeClient instance.*/OverrideSuppressLint(SetJavaScriptEnabled)public void setWebChromeClient(WebChromeClient client) {getSettings().setJavaScriptEnabled(true);if (client instanceof VideoEnabledWebChromeClient) {this.videoEnabledWebChromeClient (VideoEnabledWebChromeClient) client;}super.setWebChromeClient(client);}Overridepublic void loadData(String data, String mimeType, String encoding) {addJavascriptInterface();super.loadData(data, mimeType, encoding);}Overridepublic void loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl) {addJavascriptInterface();super.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);}Overridepublic void loadUrl(String url) {super.loadUrl(url);addJavascriptInterface();}Overridepublic void loadUrl(String url, MapString, String additionalHttpHeaders) {addJavascriptInterface();super.loadUrl(url, additionalHttpHeaders);}SuppressLint(AddJavascriptInterface)private void addJavascriptInterface() {if (!addedJavascriptInterface) {// Add javascript interface to be called when the video ends (must be done before page load)// Must match Javascript interface name of VideoEnabledWebChromeClientaddJavascriptInterface(new JavascriptInterface(), _VideoEnabledWebView);addedJavascriptInterface true;}}
} 六、效果 打开App之后经过2s的时间(对于个人而言2s是可接受的等待时间)直接视频全屏播放 但我发现url有时候不是特别稳定所以有时候看不了并建议使用电脑端访问。 七、参考资料
1.如何在android WebView中全屏播放HTML5视频
2.android webview播放视频自动全屏 八、声明
上述代码仅限个人的学习使用请勿用于商业用途请勿非法使用谢谢。