As someone who develops native apps for a living, I am not a big fan of web views. If you are not familiar with the concept, a web view is essentially an embedded browser that displays HTML within an app. It’s not that I dislike HTML per se — HTML 5 can be quite impressive — but in my experience, web pages embedded within a native app usually look like…well, web pages embedded within an app.

In particular, if you are working on an app where you don’t have control of the HTML being displayed in the web view, you often run into an issue where the HTML served up from the external URL sticks out like a sore thumb. After all, chances are it wasn’t designed specifically for your app. There is nothing more frustrating to a mobile developer than to spend months creating a brilliant user experience only to have to throw a web view into the middle of it.

I find that by injecting JavaScript into the web view at runtime I can make these fairly static web views more dynamic. This tutorial demonstrates how to seek out an element by id within a web view and replace its content after the page successfully loads. Follow the step-by-step walk-through or download and import the entire project directly into Eclipse.

1. Create a new Android project in Eclipse targeting Android 2.3 (Gingerbread) or better.

2. In the /assets folder, create a static file called index.html to simulate remote content served up from a web server.

index.html

Hello World!

3. In the /res/layout folder, create our layout. We want a simple linear layout with an edit text field, a button, and a web view. I’ve used a layout weight to flow the web view over the majority of the device display.

activity_main.xml

4. Fill in our ActivityMain.java file in the /src folder. The on create override does most of the work and, in particular, the anonymous inner class that overrides on page finished in the web view client. As long as you remember to enable JavaScript on your web view client and set the web Chrome client, your custom web view client can insert and execute just about any JavaScript you can dream up.

MainAcitivity.java package com.authorwjf.javascriptinjection; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.webkit.WebChromeClient; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.EditText; import android.annotation.SuppressLint; import android.app.Activity; public class MainActivity extends Activity implements OnClickListener { private static final String URL = "file:///android_asset/index.html"; private WebView mWebView; @SuppressLint("SetJavaScriptEnabled") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mWebView = (WebView) findViewById(R.id.webview); mWebView.getSettings().setJavaScriptEnabled(true); mWebView.setWebChromeClient(new WebChromeClient()); mWebView.setWebViewClient(new WebViewClient(){ @Override public void onPageFinished(WebView view, String url) { String user = ((EditText) findViewById(R.id.edit_text)).getText().toString(); if (user.isEmpty()) { user = "World"; } String javascript="javascript: document.getElementById(‘msg’).innerHTML=’Hello "+user+"!’;"; view.loadUrl(javascript); } }); refreshWebView(); findViewById(R.id.button).setOnClickListener(this); } private void refreshWebView() { mWebView.loadUrl(URL); } @Override public void onClick(View v) { refreshWebView(); } }

In this example, the JavaScript will customize the “hello” message based on the contents of the edit text. Give it a try!