[Android Software Development] praetorian droid:
I see... Well, the hack below should do what you want, but for some reason it doesn't.

public class WebActivity extends Activity {

private static final String TAG = "WebActivity";

WebView webView;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

webView = (WebView) findViewById(R.id.webview);
webView.setWebViewClient(new HelloWebViewClient());
webView.getSettings().setJavaScriptEnabled(true);
webView.setOnKeyListener(onKeyListener);
webView.addJavascriptInterface(new JavaScriptInterface(), "Android"); // this is for debug only
webView.loadUrl("http://htmlfive.appspot.com/static/gifter.html");
// webView.loadUrl("file:///android_asset/gifter.html");
}

// This is for debug - redirect Android.log() javascript calls to Log.d().
// 'Android' here - is an 'interfaceName argument' of addJavascriptInterface() call above
public class JavaScriptInterface {
public void log(String message) {
Log.d(TAG, message);
}
}

private void simulateKeyEvent(String key, int code, boolean keyDown) {
Log.d(TAG, "simulateKeyEvent('" + key + "', " + code + ", " + keyDown + ")");
webView.loadUrl("javascript:(function(){var e=document.createEvent('KeyboardEvent');e.initKeyboardEvent('" + (keyDown ? "keydown" : "keyup" ) + "',true,true,null,'" + key + "',0,0,0," + code + ",0);document.body.dispatchEvent(e);})()");
}

OnKeyListener onKeyListener = new OnKeyListener() {

@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
Log.d(TAG, ".onKey(): keyCode = " + keyCode + ", action = " + event.getAction());
int code;
String key;
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_DPAD_LEFT:
code = 37; // JavaScript KeyboardEvent.keyCode value for left arrow
key = "Left";
break;
case KeyEvent.KEYCODE_DPAD_UP:
code = 38; // ...
key = "Up";
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
code = 39;
key = "Right";
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
code = 40;
key = "Down";
break;

default:
Log.d(TAG, "Unknown key");
return false;
}

boolean keyDown;
switch (event.getAction()) {
case KeyEvent.ACTION_DOWN:
keyDown = true;
break;
case KeyEvent.ACTION_UP:
keyDown = false;
break;

default:
Log.d(TAG, "Unknown action");
return false;
}

simulateKeyEvent(key, code, keyDown);
return true;
}
};

private class HelloWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}

}

Looks like the problem is in the implementation of initKeyboardEvent() in WebKit (or V8?). It always produces KeyboardEvent object with 0 values of keyCode and keyChar. So this code doesn't working in my Chrome too: event is dispatched, appropriate handler is called, but keyCode is 0.

Probably there is some other way to simulate keyboard event for JavaScript running within WebView. Or maybe there is some way to redefine KeyEvent processing by WebView. I think you should look for something like this.

This is interesting subject. If you'll find a solution, please write here about it.

References:

http://developer.android.com/resources/tutorials/views/hello-webview.html - basics of WebView usage

http://developer.android.com/reference/android/webkit/WebView.html - WebView in more details

http://lexandera.com/2009/01/injecting-javascript-into-a-webview/ - about interacting with JavaScript from WebView

http://stackoverflow.com/questions/1897333/firing-a-keyboard-event-on-chrome (and many other topics) - about problems with simulating keyboard events on WebKit