* 增强型WebView组件(兼容Android 4.4+) * 特性: * 1. 全生命周期管理 * 2. 智能硬件加速 * 3. 链式配置API * 4. 安全下载管理 * 5. 全屏视频支持 * * * 说明: * ⑴ 智能加速方案: * ● API 21+:启用硬件加速层+渲染进程优化 * ● API <21:软件加速+缓存优化 * ● 自动异常回退机制 * ⑵生命周期管理: * ● 使用Application全局回调 * ● 自动解除注册 * ● 双重资源释放保障 * ⑶全屏处理增强: * ● 横竖屏自动切换 * ● 视图层级安全处理 * ● 支持JS控制全屏状态 * ⑷下载管理: * ● 动态权限申请 * ● 系统下载管理器集成 * ● 下载进度通知 * ⑸兼容性处理: * ● 支持Android 4.4+ * ● 自动处理混合内容 * ● 内存泄漏防护
封装的类的设计具有以下核心逻辑和优点:
核心逻辑分析
1. 继承体系 :
public class CustSupportFullWebView extends WebView {
// 继承Android原生WebView基础功能
}
2. 功能模块划分 :
-
全屏视频处理(通过 `FullScreenChromeClient` 实现)
-
下载管理(通过 `FileDownloadListener` 实现)
-
生命周期管理(通过Activity生命周期绑定)
-
视频控制接口(通过 `VideoControlInterface` 实现)
架构优点
1. 模块化设计 :
// 各功能通过内部类实现,高内聚低耦合
private class FullScreenChromeClient extends WebChromeClient { ... }
private class FileDownloadListener implements DownloadListener { ... }
2. 兼容性处理 :
自动检测API级别选择加速方案
public CustSupportFullWebView autoEnableHardwareAccel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
enableHardwareAccel(); // API 21+使用硬件加速
} else {
enableSoftwareAccel(); // 低版本回退方案
}
return this;
}
3. 链式调用设计 :
// 配置示例
new CustSupportFullWebView(context)
.configureWebSettings()
.autoEnableHardwareAccel()
.setDownloadHandler();
4.生命周期管理增强
1)双重销毁保障
private void releaseResources() {
// 1. 先移除父视图
if (getParent() instanceof ViewGroup) {
((ViewGroup)getParent()).removeView(this);
}
// 2. 检查窗口附着状态
if (mIsAttachedToWindow) {
onDetachedFromWindow();
}
// 3. 最后执行原生销毁
super.destroy();
}
2)全局生命周期监听 :
activity.getApplication().registerActivityLifecycleCallbacks(
new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityDestroyed(Activity activity) {
if (activity == mHostActivity) {
releaseResources();
}
}
// ... 其他生命周期方法 ...
}
);
性能优化点
1. 智能加速策略 :
-
硬件加速(API 21+)
-
软件加速(兼容方案)
-
自动异常回退机制
2. 资源管理 :
private void releaseResources() {
// 1. 先移除视图
if (getParent() instanceof ViewGroup) {
((ViewGroup) getParent()).removeView(this);
}
// 2. 再执行销毁
super.destroy();
}
扩展性设计亮点
1. 代理模式应用 :
private static class WebViewClientProxy extends WebViewClient {
// 合并外部和内部处理逻辑
}
2. 监听器接口 :
public interface FullscreenListener {
void onEnterFullscreen(Uri videoUri);
void onExitFullscreen();
}
3.JS桥接接口 :
@JavascriptInterface
public void onFullscreenVideo(final String src) {
mHostActivity.runOnUiThread(() -> {
if (mFullscreenListener != null) {
mFullscreenListener.onEnterFullscreen(Uri.parse(src));
}
});
}
4. DOM动态监听 :
new MutationObserver(mutations => {
mutations.forEach(mu => {
mu.addedNodes.forEach(node => {
if(node.nodeName === 'VIDEO') {
node.style.zIndex = 9999;
node.addEventListener('click', handleVideoClick);
}
});
});
}).observe(document.body, {childList: true, subtree: true});
该实现通过分层设计将复杂功能模块化,同时保持各模块间的低耦合度,是Android WebView定制开发的优秀实践。该设计同时也完美平衡了功能完整性和性能要求,通过模块化架构和兼容性处理,适用于复杂的WebView应用场景。
完整代码:
直接上代码:
public class CustSupportFullWebView extends WebView {
// 模块 成员变量
public Activity mHostActivity;
private View mFullscreenView;
private WebChromeClient.CustomViewCallback mFullscreenCallback;
private List<Uri> mVideoUris = new ArrayList<>(); //todo 页面视频地址(目前还未取到值)
// 暂存全屏播放前原始方向
private int mOriginalOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
// 记录全屏播放前滚动位置记录
private int mOriginalScrollX, mOriginalScrollY; // 保存进入全屏前的滚
/**
* 是否支持根据视频宽高自适应横屏竖屏选择。 默认不支持false
*/
private boolean supportChooseScreenWithWidthHeight = false;
private boolean mIsDestroyed = false; // 销毁状态标记
private boolean mIsAttachedToWindow = false; // 新增窗口附着状态
// end模块
// WebChromeClient代理
private FullScreenChromeClient mInternalChromeClient = new FullScreenChromeClient();
// 模块 构造函数
public CustSupportFullWebView(Context context) {
super(context);
init((Activity) context);
}
public CustSupportFullWebView(Context context, AttributeSet attrs) {
super(context, attrs);
init((Activity) context);
}
public CustSupportFullWebView(@NonNull Context context, @NonNull Activity hostActivity) {
super(context);
init(hostActivity);
}
// end模块
// 模块 初始化方法
@SuppressLint("SetJavaScriptEnabled")
public void init(Activity hostActivity) {
this.mHostActivity = hostActivity;
// 链式配置
configureWebSettings()
.appendUserAgentString("customApp") // 默认添加 customApp到UserAgent方便打开网页是H5获取值判断是不是customApp打开
.setChromeClient()
.setDownloadHandler()
.autoEnableHardwareAccel() // 自动选择加速方案
.injectStateObserver()
.setCustomWebClient();
// 绑定生命周期
bindActivityLifecycle(hostActivity);
}
// end模块
// 模块 链式配置方法
/**
* 基础配置入口(必须首先调用)
*/
public CustSupportFullWebView configureWebSettings() {
WebSettings settings = getSettings();
settings.setJavaScriptEnabled(true); //设置WebView属性,运行执行js脚本
settings.setDomStorageEnabled(true); //DOM Storage // 开启DOM缓存,开启LocalStorage存储(html5的本地存储方式)
settings.setMediaPlaybackRequiresUserGesture(false);
settings.setUseWideViewPort(true);
settings.setLoadWithOverviewMode(true);
// 确认字体文件路径和权限设置
settings.setAllowFileAccess(true); // 是否可访问Content Provider的资源,默认值 true
settings.setAllowContentAccess(true); // 是否可访问本地文件,默认值 true
// 如果网页内容来自网络,可能需要额外设置:
settings.setAllowFileAccessFromFileURLs(true);
settings.setAllowUniversalAccessFromFileURLs(true);
//针对 Android 5.8+ 需要额外配置
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
settings.setMixedContentMode(
WebSettings.MIXED_CONTENT_ALWAYS_ALLOW // 允许混合内容
);
}
return this;
}
/**
* <p>
* Description: [UserAgent里追加字符串]
* <p>
*
*
* @param appendStr
*
* @return CustSupportFullWebView
*
* ${tags}
*/
public CustSupportFullWebView appendUserAgentString(String appendStr) {
String originalUserAgent = getSettings().getUserAgentString();
String newUserAgent;
if(StringUtils.isBlank(originalUserAgent)) {
newUserAgent = appendStr;
} else {
newUserAgent = originalUserAgent + " " + appendStr;
}
getSettings().setUserAgentString(newUserAgent);
return this;
}
public boolean isSupportChooseScreenWithWidthHeight() {
return supportChooseScreenWithWidthHeight;
}
public void setSupportChooseScreenWithWidthHeight(boolean supportChooseScreenWithWidthHeight) {
this.supportChooseScreenWithWidthHeight = supportChooseScreenWithWidthHeight;
}
/**
* 设置缓存模式
* @param mode WebSettings.LOAD_* 常量
*/
public CustSupportFullWebView setCacheMode(int mode) {
getSettings().setCacheMode(mode);
return this;
}
/**
* 设置自定义Chrome客户端(全屏处理)
*/
public CustSupportFullWebView setChromeClient() {
setWebChromeClient(new ChromeClientProxy(null, mInternalChromeClient));
return this;
}
/**
* 设置文件下载处理器
*/
public CustSupportFullWebView setDownloadHandler() {
setDownloadListener(new FileDownloadListener(null));
return this;
}
/**
* 做修改,若用户已自定义实现了则采用自定义的,否则采用此处默认的通知显示下载
* @param listener
*/
@Override