Keywords: Android | WebView | HTML5 Video Playback
Abstract: This article provides an in-depth exploration of common issues and solutions for playing HTML5 video elements within Android WebView. By analyzing the core code implementation from the best answer and incorporating supplementary suggestions, it details how to configure WebView settings, implement WebChromeClient callback methods, handle video playback lifecycle, and resolve the technical challenge of videos playing only once. The article offers complete code examples and implementation logic to help developers achieve stable and reliable WebView video playback functionality.
Problem Background and Challenges
In Android application development, the WebView component is commonly used to embed web content. However, when pages contain HTML5 <video> elements, developers often encounter issues with video playback. Unlike native browsers, WebView does not support video playback by default and requires special configuration and handling by developers.
Core Configuration Steps
To implement HTML5 video playback in WebView, proper initialization configuration is essential:
WebView mWebView = (WebView) findViewById(R.id.webview);
mWebView.setWebChromeClient(new CustomWebChromeClient());
mWebView.setWebViewClient(new WebViewClient());
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setPluginState(PluginState.ON);
mWebView.loadUrl("http://example.com/video-page");
Key configurations include enabling JavaScript, setting plugin state to ON, and configuring WebChromeClient to handle video-related events.
WebChromeClient Implementation
The onShowCustomView method in WebChromeClient is central to handling full-screen video playback:
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
super.onShowCustomView(view, callback);
if (view instanceof FrameLayout) {
FrameLayout frame = (FrameLayout) view;
if (frame.getFocusedChild() instanceof VideoView) {
VideoView video = (VideoView) frame.getFocusedChild();
frame.removeView(video);
// Add video view to activity's root layout
activity.setContentView(video);
// Set video listeners
video.setOnCompletionListener(this);
video.setOnErrorListener(this);
video.start();
// Save callback reference for future use
this.customViewCallback = callback;
this.currentVideoView = video;
}
}
}
Video Playback Lifecycle Management
Proper handling of video completion and error events is crucial:
@Override
public void onCompletion(MediaPlayer mp) {
// Video playback completed
if (currentVideoView != null) {
currentVideoView.stopPlayback(); // Release MediaPlayer resources
}
// Restore WebView display
activity.setContentView(R.layout.main_layout);
// Notify WebView that custom view is hidden
if (customViewCallback != null) {
customViewCallback.onCustomViewHidden();
}
// Reset references
currentVideoView = null;
customViewCallback = null;
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// Handle video playback errors
Log.e(TAG, "Video playback error: " + what + ", " + extra);
// Clean up resources and restore WebView
if (currentVideoView != null) {
currentVideoView.stopPlayback();
}
activity.setContentView(R.layout.main_layout);
if (customViewCallback != null) {
customViewCallback.onCustomViewHidden();
}
currentVideoView = null;
customViewCallback = null;
return true;
}
Solving the Single-Playback Issue
Based on supplementary answers, the common reason videos play only once is improper resource release:
- Call stopPlayback() method: After video completion, the VideoView's stopPlayback() method must be called to release MediaPlayer resources.
- Properly call onCustomViewHidden(): Ensure the saved CustomViewCallback's onCustomViewHidden() method is called when hiding the custom view.
- Resource reference management: Clear references to VideoView and CustomViewCallback promptly to avoid memory leaks.
Advanced Implementation Approach
For more complex scenarios, consider implementing a custom HTML5WebView class:
public class HTML5WebView extends WebView {
private FrameLayout customViewContainer;
private View customView;
private CustomViewCallback customViewCallback;
// Initialization method
private void init(Context context) {
// Create layout containing WebView and custom view container
FrameLayout mainLayout = new FrameLayout(context);
customViewContainer = new FrameLayout(context);
customViewContainer.setVisibility(View.GONE);
mainLayout.addView(customViewContainer,
new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
// Configure WebView settings
WebSettings settings = getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
settings.setPluginState(PluginState.ON);
// Set custom WebChromeClient
setWebChromeClient(new CustomWebChromeClient());
}
// Custom WebChromeClient implementation
private class CustomWebChromeClient extends WebChromeClient {
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
if (customView != null) {
callback.onCustomViewHidden();
return;
}
HTML5WebView.this.setVisibility(View.GONE);
customViewContainer.addView(view);
customView = view;
customViewCallback = callback;
customViewContainer.setVisibility(View.VISIBLE);
}
@Override
public void onHideCustomView() {
if (customView == null) return;
customView.setVisibility(View.GONE);
customViewContainer.removeView(customView);
customView = null;
customViewContainer.setVisibility(View.GONE);
customViewCallback.onCustomViewHidden();
HTML5WebView.this.setVisibility(View.VISIBLE);
}
}
}
Best Practice Recommendations
- Video encoding formats: Ensure use of WebView-supported video encoding formats such as H.264.
- Memory management: Release video playback resources promptly to avoid memory leaks.
- Error handling: Implement comprehensive error handling mechanisms with user-friendly error messages.
- Compatibility considerations: Account for compatibility across different Android versions with appropriate version detection and handling.
- User experience: Provide video loading progress indicators to enhance user experience.
Conclusion
By properly configuring WebView settings, implementing WebChromeClient callback methods, and carefully managing video playback lifecycle, developers can successfully implement HTML5 video playback in Android WebView. Key aspects include enabling JavaScript and plugin support, correctly handling onShowCustomView and onHideCustomView callbacks, and promptly releasing MediaPlayer resources to avoid the single-playback issue. The solutions presented in this article have been validated through practice and can help developers overcome common obstacles in WebView video playback.