转载请注明出处:WebView使用详解、H5网页视频全屏播放 、网页跳转空白_fragment webview全屏播放视频_Mr_Leixiansheng的博客-CSDN博客
内容:介绍webview的使用方法,介绍WebViewClient、WebChromeClient,H5网页视频全屏播放,网页跳转空白问题
最近做项目老爱和H5打交道,遇到了很多问题也踩了许多坑,今天在这儿总结下,方便后人乘凉。
关于安卓和H5交互可参考我之前的文章:原生与H5交互介绍
WebView基础设置
private void initWebView() {
mWebView.setWebViewClient(new MyWebViewClient()); //设置在WebView中打开链接,不设置则调用自带浏览器。主要针对View进行拦截处理
mWebView.setWebChromeClient(new MyWebChromeClient());
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true); //支持JS
webSettings.setDomStorageEnabled(true); //启用dom内存,防止js加载失败
webSettings.setAllowFileAccess(true); //允许访问文件
webSettings.setSupportZoom(true); //支持缩放
webSettings.setLoadWithOverviewMode(true); //是否启动概述模式浏览界面,当页面宽度超过WebView显示宽度时,缩小页面适应WebView。默认false
webSettings.setGeolocationEnabled(false); //是否允许定位
webSettings.setLoadsImagesAutomatically(true); //是否加载图片
// webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); //设置缓存模式
// webSettings.setDefaultTextEncodingName("UTF-8"); //设置页面的编码格式,默认UTF-8
}
WebViewClient主要是对view一系列操作进行监听拦截。包括:网页加载开始、网页加载完成、错误拦截处理。(代码中注释会详解,再次不多做介绍)
WebChromeClient主要是对浏览器进行监听。例如弹窗、是否显示支持全屏播放等。(代码中注释会详解,再次不多做介绍)
网页加载空白问题,我只在7.0及以上遇到,貌似是说证书错误,可能越往上安全性越高吧,按照下面处理下就行了
/**
* HTTPS通信的网址(以https://开头的网站)出现错误时
* 证书错误拦截处理
* 安卓7.0需要
*/
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
if(error.getPrimaryError() == android.net.http.SslError.SSL_INVALID ){// 校验过程遇到了bug
handler.proceed(); //忽略错误继续加载
}else{
handler.cancel(); //取消加载
}
}
视频全屏播放:安卓不像IOS一样可以直接全屏播放,需要在WebChromeClient对其进行设置,相当于是new 一个Fragment让其来进行全屏播放
/*** 视频播放相关的方法 **/
@Override
public View getVideoLoadingProgressView() {
FrameLayout frameLayout = new FrameLayout(MainActivity.this);
frameLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
return frameLayout;
}
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
showCustomView(view, callback);
}
@Override
public void onHideCustomView() {
hideCustomView();
}
代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btn_load"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="LOAD"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/web_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
</WebView>
<ProgressBar
android:id="@+id/pb_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:visibility="gone"/>
</RelativeLayout>
</LinearLayout>
package com.example.leixiansheng.webviewtest;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.SslErrorHandler;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import com.tbruyelle.rxpermissions2.Permission;
import com.tbruyelle.rxpermissions2.RxPermissions;
import java.util.function.Consumer;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends AppCompatActivity {
@BindView(R.id.btn_load)
Button mBtnLoad;
@BindView(R.id.web_view)
WebView mWebView;
@BindView(R.id.pb_loading)
ProgressBar mPbLoading;
/** 视频全屏参数 */
protected static final FrameLayout.LayoutParams COVER_SCREEN_PARAMS = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
private View customView;
private FrameLayout fullscreenContainer;
private WebChromeClient.CustomViewCallback customViewCallback;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initWebView();
}
private void initWebView() {
mWebView.setWebViewClient(new MyWebViewClient()); //设置在WebView中打开链接,不设置则调用自带浏览器。主要针对View进行拦截处理
mWebView.setWebChromeClient(new MyWebChromeClient());
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true); //支持JS
webSettings.setDomStorageEnabled(true); //启用dom内存,防止js加载失败
webSettings.setAllowFileAccess(true); //允许访问文件
webSettings.setSupportZoom(true); //支持缩放
webSettings.setLoadWithOverviewMode(true); //是否启动概述模式浏览界面,当页面宽度超过WebView显示宽度时,缩小页面适应WebView。默认false
webSettings.setGeolocationEnabled(false); //是否允许定位
webSettings.setLoadsImagesAutomatically(true); //是否加载图片
// webSettings.setCacheMode(WebSettings.LOAD_DEFAULT); //设置缓存模式
// webSettings.setDefaultTextEncodingName("UTF-8"); //设置页面的编码格式,默认UTF-8
}
@OnClick(R.id.btn_load)
public void onViewClicked() {
mWebView.loadUrl("http://www.baidu.com");
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
//优先退出全屏播放
if (customView != null) {
hideCustomView();
return true;
} else {
if (mWebView.canGoBack()) {
mWebView.goBack(); //返回上个页面
return true;
} else {
System.exit(0); //退出程序
}
}
}
return super.onKeyDown(keyCode, event);
}
/**
* 针对网页进行拦截处理
*/
public class MyWebViewClient extends WebViewClient{
/**
*可以实现对网页中超链接的拦截
*/
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//例:拦截电话网址,直接调用本地电话
if (url.contains("tel:")){
startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(url)));
return true;
}
if (url.startsWith("http:") || url.startsWith("https:")) {
view.loadUrl(url);
return true;
}
/* WebView.HitTestResult hitTestResult = view.getHitTestResult();
//hitTestResult==null解决重定向问题
if (!TextUtils.isEmpty(url) && hitTestResult == null) {
view.loadUrl(url);
return true;
}*/
return super.shouldOverrideUrlLoading(view, url);
}
/**
*开始加载
*/
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
mPbLoading.setVisibility(View.VISIBLE);
}
/**
* 结束加载
*/
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
mPbLoading.setVisibility(View.GONE);
}
/**
* 加载错误的时候会产生这个回调
*/
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
//TODO
}
/**
* HTTPS通信的网址(以https://开头的网站)出现错误时
* 证书错误拦截处理
* 安卓7.0需要
*/
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
if(error.getPrimaryError() == android.net.http.SslError.SSL_INVALID ){// 校验过程遇到了bug
handler.proceed(); //忽略错误继续加载
}else{
handler.cancel(); //取消加载
}
}
}
/**
* 针对浏览器拦截处理
*/
public class MyWebChromeClient extends WebChromeClient{
/**
* 弹窗拦截
*/
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
return super.onJsAlert(view, url, message, result);
}
/**
* 弹窗拦截
*/
@Override
public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
return super.onJsConfirm(view, url, message, result);
}
/**
* 弹窗拦截
*/
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
return super.onJsPrompt(view, url, message, defaultValue, result);
}
/**
* 加载进度拦截
*/
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
}
/**
* 文件选择
*/
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
selectImage();
return super.onShowFileChooser(webView, filePathCallback, fileChooserParams);
}
/*** 视频播放相关的方法 **/
@Override
public View getVideoLoadingProgressView() {
FrameLayout frameLayout = new FrameLayout(MainActivity.this);
frameLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
return frameLayout;
}
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
showCustomView(view, callback);
}
@Override
public void onHideCustomView() {
hideCustomView();
}
}
/**
* 图片选择
*/
private void selectImage() {
//TODO
}
/**
* 视频播放全屏
*/
private void showCustomView(View view, WebChromeClient.CustomViewCallback callback) {
// if a view already exists then immediately terminate the new one
if (customView != null) {
callback.onCustomViewHidden();
return;
}
getWindow().getDecorView();
//获取虚拟按键高度,防止遮挡
if(ScreenUtils.hasNavBar(this)){
COVER_SCREEN_PARAMS.setMargins(0,0,0,ScreenUtils.getNavigationBarHeight(this));
}
FrameLayout decor = (FrameLayout) getWindow().getDecorView();
fullscreenContainer = new FullscreenHolder(this);
fullscreenContainer.addView(view, COVER_SCREEN_PARAMS);
decor.addView(fullscreenContainer, COVER_SCREEN_PARAMS);
customView = view;
setStatusBarVisibility(false);
customViewCallback = callback;
}
/**
* 隐藏视频全屏
*/
private void hideCustomView() {
if (customView == null) {
return;
}
setStatusBarVisibility(true);
FrameLayout decor = (FrameLayout) getWindow().getDecorView();
decor.removeView(fullscreenContainer);
fullscreenContainer = null;
customView = null;
customViewCallback.onCustomViewHidden();
mWebView.setVisibility(View.VISIBLE);
}
/**
* 全屏容器界面
*/
static class FullscreenHolder extends FrameLayout {
public FullscreenHolder(Context ctx) {
super(ctx);
setBackgroundColor(ctx.getResources().getColor(android.R.color.black));
}
@Override
public boolean onTouchEvent(MotionEvent evt) {
return true;
}
}
private void setStatusBarVisibility(boolean visible) {
int flag = visible ? 0 : WindowManager.LayoutParams.FLAG_FULLSCREEN;
getWindow().setFlags(flag, WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
}