BLOG POSTS
Android WebView Example Tutorial

Android WebView Example Tutorial

Android WebView is a system component that allows your app to display web content directly within your application, essentially embedding a web browser into your Android app. It’s incredibly useful for hybrid app development, displaying remote content, integrating web-based features, or simply showing rich HTML content without launching the external browser. This tutorial will walk you through creating, configuring, and optimizing WebView implementations, covering everything from basic setup to advanced customization and performance optimization strategies.

How Android WebView Works

WebView is essentially a wrapper around the Chromium rendering engine that comes bundled with Android. Since Android 5.0 (API level 21), WebView has been updatable through Google Play, meaning the underlying browser engine stays current with security patches and feature updates regardless of the Android version.

The WebView component creates a sandboxed browser environment within your app’s process. It handles HTML parsing, CSS rendering, JavaScript execution, and network requests while providing APIs to interact between your native Android code and web content through JavaScript bridges.

Here’s what happens under the hood:

  • Your app creates a WebView instance and loads it with content (URL, HTML string, or local file)
  • The Chromium engine parses and renders the content
  • JavaScript execution happens in a separate thread with V8 engine
  • Network requests go through the system’s HTTP stack (can be intercepted)
  • Rendered content is displayed in your app’s UI hierarchy

Basic WebView Implementation

Let’s start with a simple WebView setup. First, add the internet permission to your AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />

Create a basic layout with WebView:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <WebView
        android:id="@+id/webview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

Now implement the basic WebView functionality in your Activity:

public class MainActivity extends AppCompatActivity {
    private WebView webView;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        webView = findViewById(R.id.webview);
        
        // Enable JavaScript (disabled by default)
        WebSettings webSettings = webView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        
        // Set WebViewClient to handle page navigation
        webView.setWebViewClient(new WebViewClient());
        
        // Load a webpage
        webView.loadUrl("https://www.example.com");
    }
    
    @Override
    public void onBackPressed() {
        // Handle back navigation in WebView
        if (webView.canGoBack()) {
            webView.goBack();
        } else {
            super.onBackPressed();
        }
    }
}

Advanced WebView Configuration

The real power of WebView comes from proper configuration. Here’s a more comprehensive setup with commonly needed settings:

private void configureWebView() {
    WebSettings settings = webView.getSettings();
    
    // JavaScript and DOM storage
    settings.setJavaScriptEnabled(true);
    settings.setDomStorageEnabled(true);
    settings.setDatabaseEnabled(true);
    
    // Caching strategy
    settings.setCacheMode(WebSettings.LOAD_DEFAULT);
    settings.setAppCacheEnabled(true);
    
    // Viewport and zoom
    settings.setUseWideViewPort(true);
    settings.setLoadWithOverviewMode(true);
    settings.setSupportZoom(true);
    settings.setBuiltInZoomControls(true);
    settings.setDisplayZoomControls(false); // Hide zoom buttons
    
    // File access (be careful with security implications)
    settings.setAllowFileAccess(true);
    settings.setAllowContentAccess(true);
    
    // Mixed content (HTTPS pages loading HTTP resources)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        settings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
    }
    
    // User agent customization
    String userAgent = settings.getUserAgentString();
    settings.setUserAgentString(userAgent + " MyApp/1.0");
}

Implementing WebView Clients

WebViewClient and WebChromeClient are essential for controlling WebView behavior. Here’s how to implement them effectively:

webView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
        String url = request.getUrl().toString();
        
        // Handle specific URLs differently
        if (url.startsWith("mailto:")) {
            Intent intent = new Intent(Intent.ACTION_SENDTO);
            intent.setData(Uri.parse(url));
            startActivity(intent);
            return true;
        }
        
        // Load internal URLs in WebView, external ones in browser
        if (url.contains("yourdomain.com")) {
            return false; // Load in WebView
        } else {
            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            startActivity(intent);
            return true; // Don't load in WebView
        }
    }
    
    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) {
        super.onPageStarted(view, url, favicon);
        // Show loading indicator
        progressBar.setVisibility(View.VISIBLE);
    }
    
    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        // Hide loading indicator
        progressBar.setVisibility(View.GONE);
    }
    
    @Override
    public void onReceivedError(WebView view, WebResourceRequest request, 
                               WebResourceError error) {
        super.onReceivedError(view, request, error);
        // Handle errors gracefully
        if (request.isForMainFrame()) {
            loadErrorPage();
        }
    }
});

webView.setWebChromeClient(new WebChromeClient() {
    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        super.onProgressChanged(view, newProgress);
        progressBar.setProgress(newProgress);
    }
    
    @Override
    public boolean onJsAlert(WebView view, String url, String message, 
                            JsResult result) {
        // Handle JavaScript alerts
        new AlertDialog.Builder(MainActivity.this)
            .setMessage(message)
            .setPositiveButton("OK", (dialog, which) -> result.confirm())
            .show();
        return true;
    }
    
    @Override
    public void onPermissionRequest(PermissionRequest request) {
        // Handle web permissions (camera, microphone, etc.)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            request.grant(request.getResources());
        }
    }
});

JavaScript Bridge Implementation

One of WebView’s most powerful features is the ability to create a bridge between JavaScript and native Android code. Here’s how to implement it:

public class WebAppInterface {
    Context context;
    
    WebAppInterface(Context c) {
        context = c;
    }
    
    @JavascriptInterface
    public void showToast(String toast) {
        Toast.makeText(context, toast, Toast.LENGTH_SHORT).show();
    }
    
    @JavascriptInterface
    public String getDeviceInfo() {
        return Build.MODEL + " (" + Build.VERSION.RELEASE + ")";
    }
    
    @JavascriptInterface
    public void openNativeActivity(String activityName) {
        Intent intent = new Intent(context, getActivityClass(activityName));
        context.startActivity(intent);
    }
}

// In your Activity
webView.addJavascriptInterface(new WebAppInterface(this), "Android");

// JavaScript can now call:
// Android.showToast("Hello from web!");
// var deviceInfo = Android.getDeviceInfo();

To call JavaScript from Android:

// For API 19+
webView.evaluateJavascript("javascript:updateData('" + jsonData + "')", 
    new ValueCallback<String>() {
        @Override
        public void onReceiveValue(String value) {
            // Handle return value from JavaScript
        }
    });

// Legacy method (still works)
webView.loadUrl("javascript:updateData('" + jsonData + "')");

Loading Different Content Types

WebView can load content from various sources. Here are the common approaches:

// Load remote URL
webView.loadUrl("https://www.example.com");

// Load local HTML file from assets
webView.loadUrl("file:///android_asset/index.html");

// Load HTML string directly
String htmlData = "<html><body><h1>Hello World</h1></body></html>";
webView.loadData(htmlData, "text/html", "UTF-8");

// Load HTML with base URL (useful for relative links)
webView.loadDataWithBaseURL("file:///android_asset/", htmlData, 
                           "text/html", "UTF-8", null);

// POST request with data
String postData = "param1=value1¶m2=value2";
webView.postUrl("https://api.example.com/submit", postData.getBytes());

Performance Optimization Strategies

WebView performance can significantly impact user experience. Here are key optimization techniques:

Optimization Implementation Impact
Hardware Acceleration android:hardwareAccelerated=”true” 30-50% rendering improvement
Cache Strategy LOAD_CACHE_ELSE_NETWORK Reduces network requests by 60-80%
Image Loading setBlockNetworkImage(true) initially Faster initial page load
JavaScript Optimization Lazy loading of JS interfaces Reduces memory usage by 20-30%
// Performance optimization setup
private void optimizeWebViewPerformance() {
    WebSettings settings = webView.getSettings();
    
    // Caching
    settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
    settings.setAppCacheEnabled(true);
    settings.setAppCachePath(getCacheDir().getAbsolutePath());
    
    // Reduce memory usage
    settings.setPluginState(WebSettings.PluginState.OFF);
    settings.setGeolocationEnabled(false);
    settings.setSaveFormData(false);
    settings.setSavePassword(false);
    
    // Improve rendering
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG);
        settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING);
    }
    
    // Load images after main content
    settings.setBlockNetworkImage(true);
    webView.setWebViewClient(new WebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            settings.setBlockNetworkImage(false);
        }
    });
}

Security Best Practices

WebView security requires careful consideration, especially when loading external content or implementing JavaScript bridges:

private void secureWebView() {
    WebSettings settings = webView.getSettings();
    
    // Disable potentially dangerous features
    settings.setAllowFileAccessFromFileURLs(false);
    settings.setAllowUniversalAccessFromFileURLs(false);
    settings.setJavaScriptCanOpenWindowsAutomatically(false);
    
    // Secure JavaScript interface
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        // Only add interfaces on API 17+ due to security vulnerabilities
        webView.addJavascriptInterface(new SecureWebInterface(), "Android");
    }
    
    // SSL error handling
    webView.setWebViewClient(new WebViewClient() {
        @Override
        public void onReceivedSslError(WebView view, SslErrorHandler handler, 
                                     SslError error) {
            // Don't ignore SSL errors in production
            handler.cancel();
            showSslErrorDialog(error);
        }
        
        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, 
                                                        WebResourceRequest request) {
            // Implement URL filtering/validation here
            String url = request.getUrl().toString();
            if (!isUrlAllowed(url)) {
                return new WebResourceResponse("text/plain", "UTF-8", 
                    new ByteArrayInputStream("Blocked".getBytes()));
            }
            return super.shouldInterceptRequest(view, request);
        }
    });
}

Common Issues and Troubleshooting

Here are the most frequent WebView problems and their solutions:

Issue 1: White screen or blank WebView

  • Check internet permission in manifest
  • Verify hardware acceleration is enabled
  • Ensure JavaScript is enabled if required
  • Check for SSL certificate issues

Issue 2: JavaScript not working

// Make sure JavaScript is enabled
webSettings.setJavaScriptEnabled(true);

// Check for console errors
webView.setWebChromeClient(new WebChromeClient() {
    @Override
    public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
        Log.d("WebView", consoleMessage.message() + " -- From line " +
               consoleMessage.lineNumber() + " of " + consoleMessage.sourceId());
        return super.onConsoleMessage(consoleMessage);
    }
});

Issue 3: Memory leaks

@Override
protected void onDestroy() {
    if (webView != null) {
        webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
        webView.clearCache(true);
        webView.clearHistory();
        webView.removeAllViews();
        webView.destroyDrawingCache();
        webView.destroy();
        webView = null;
    }
    super.onDestroy();
}

WebView vs Alternatives Comparison

Solution Pros Cons Best For
WebView Integrated, customizable, offline capable Performance overhead, security concerns Hybrid apps, embedded web content
Chrome Custom Tabs Better performance, auto-updates, shared sessions Less customization, requires Chrome External web content, authentication
External Browser Best performance, always updated Context switching, no integration Simple web links, full websites
Native Implementation Best performance, full control High development cost, maintenance Core app features, complex UI

Real-World Use Cases and Examples

E-commerce Product Gallery:

// Load product HTML with native checkout integration
webView.addJavascriptInterface(new CheckoutInterface(), "Checkout");
webView.loadUrl("file:///android_asset/product_gallery.html");

public class CheckoutInterface {
    @JavascriptInterface
    public void addToCart(String productId, int quantity) {
        // Handle cart logic natively
        CartManager.addItem(productId, quantity);
        runOnUiThread(() -> updateCartBadge());
    }
}

OAuth Authentication Flow:

webView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
        String url = request.getUrl().toString();
        if (url.startsWith("myapp://oauth-callback")) {
            // Extract token from URL and complete authentication
            String token = extractTokenFromUrl(url);
            completeAuthentication(token);
            return true;
        }
        return false;
    }
});

Offline-First Content Viewer:

private void setupOfflineContent() {
    webView.setWebViewClient(new WebViewClient() {
        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, 
                                                        WebResourceRequest request) {
            String url = request.getUrl().toString();
            
            // Check if resource exists in local cache
            File cachedFile = getCachedFile(url);
            if (cachedFile.exists()) {
                try {
                    return new WebResourceResponse(
                        getMimeType(cachedFile),
                        "UTF-8",
                        new FileInputStream(cachedFile)
                    );
                } catch (FileNotFoundException e) {
                    Log.e("WebView", "Cached file not found", e);
                }
            }
            
            return super.shouldInterceptRequest(view, request);
        }
    });
}

For comprehensive WebView documentation, check the official Android WebView documentation and the WebView development guide.

WebView remains one of the most versatile components in Android development, bridging the gap between web and native experiences. With proper implementation, security considerations, and performance optimization, it can provide seamless integration of web content into your Android applications while maintaining native app performance characteristics.



This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.

This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.

Leave a reply

Your email address will not be published. Required fields are marked