Complete Solution for HTML5 Video Playback in Android WebView

Dec 08, 2025 · Programming · 8 views · 7.8

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:

  1. Call stopPlayback() method: After video completion, the VideoView's stopPlayback() method must be called to release MediaPlayer resources.
  2. Properly call onCustomViewHidden(): Ensure the saved CustomViewCallback's onCustomViewHidden() method is called when hiding the custom view.
  3. 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

  1. Video encoding formats: Ensure use of WebView-supported video encoding formats such as H.264.
  2. Memory management: Release video playback resources promptly to avoid memory leaks.
  3. Error handling: Implement comprehensive error handling mechanisms with user-friendly error messages.
  4. Compatibility considerations: Account for compatibility across different Android versions with appropriate version detection and handling.
  5. 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.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.