Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handle arrow keys from D-pad on WebView Google Tv app

I have built an Android app which loads a html page in WebView, and it is working ok, except the fact that actions should happen on D-pad arrow keys won't work. If I change action for arrows with other keys, it works. Loading the html page in web browser works fine, PC keyboard arrow keys return correct actions, but in Android WebView, D-pad arrow keys aren't working.

This is how I tiger key pressed in js:

window.addEventListener('keydown', keyDownHandler, true);
function keyDownHandler(evt){
var keyCode=evt.keyCode;
alert(keyCode);
}

Except arrow keys, pressing any other key returns the key code, but arrows won't.

This might be duplicate as here: android WebView: Handle arrow keys in JavaScript but didn't find a solution to work.

Is there any way I can get the D-pad arrow keys codes in Android WebView?

like image 803
MariusR Avatar asked Oct 31 '13 21:10

MariusR


1 Answers

There is an example app on the Google TV samples called WebAppNativePlayback: https://code.google.com/p/googletv-android-samples/source/browse/#git%2FWebAppNativePlayback

Essentially the d-pad is consumed by the native application, so you need to handle that, if you using a fullscreen WebView you can pass the relevant keys to the WebView by injecting it into JS.

The main pieces of code to pay attention to are:

In the Activity, consume key events and pass down:

/**
 * This method will check if the key press should be handled by the system
 * or if we have chosen to override it to pass to the WebView. In
 * development builds of the application, the R key is used refresh the page
 * (required to ensure cached versions of the page are not used)
 */
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if (mIsDevelopmentBuild && event.getKeyCode() == KeyEvent.KEYCODE_R) {
        mWebViewFragment.refresh();
    }

    int eventKeyCode = event.getKeyCode();
    for (int i = 0; i < mOverrideKeyCodes.length; i++) {
        if (eventKeyCode == mOverrideKeyCodes[i]) {
            if (event.getAction() == KeyEvent.ACTION_UP) {
                mWebViewFragment.handleKeyInjection(eventKeyCode);
            }
            return true;
        }
    }

    return super.dispatchKeyEvent(event);
}

Where the override keys are:

mOverrideKeyCodes = new int[] {
                KeyEvent.KEYCODE_DPAD_CENTER,
                KeyEvent.KEYCODE_DPAD_UP,
                KeyEvent.KEYCODE_DPAD_LEFT,
                KeyEvent.KEYCODE_DPAD_DOWN,
                KeyEvent.KEYCODE_DPAD_RIGHT
        };

In the Fragment where the webview lives (although this may be in your activity):

/**
 * Given a key code, this method will pass it into the web view to handle
 * accordingly
 * 
 * @param keycode Native Android KeyCode
 */
public void handleKeyInjection(int keycode) {
    String jsSend = "javascript:androidKeyHandler.handleUri('nativewebsample://KEY_EVENT;"
            + keycode + ";');";
    loadJavascriptAction(jsSend);
}

loadJavascriptAction is simply

mWebView.loadUrl(jsSend);

Then in your web page, you need to set an accessible method or object - in this case the app sets an object window.androidKeyHandler

/**
* This method will set up any additional key handling (i.e. Android key handling)
* @function
*/
IndexPage.prototype.setUpKeyHandling = function () {
    if(this.isEmbedded()) {
        // We want the native app to access this
        window.androidKeyHandler = new AndroidKeyHandler(this.getFocusController());
    }
};

Which than handles the keys like so:

/**
* Handle a keypress directly from the native app
* @function
* @param {int} keyCode The native Android key code
*/
AndroidKeyHandler.prototype.handleNativeKeyPress = function (keyCode) {
    var focusController = this.getFocusController();
    switch(parseInt(keyCode, 10)) {
        case 23:
            // DPAD Center
            console.log("Native Enter");
            if(focusController.getCurrentlyFocusedItem()) {
                focusController.getCurrentlyFocusedItem().onItemClick();
            }
            break;
        case 20:
            // DPAD Down
            console.log("Native Down Pressed");
            focusController.moveFocus({x: 0, y: -1});
            break;
        case 21:
            // DPAD Left
            console.log("Native Left Pressed");
            focusController.moveFocus({x: -1, y: 0});
            break;
        case 22:
            // DPAD Right
            console.log("Native RIGHT Pressed");
            focusController.moveFocus({x: 1, y: 0});
            break;
        case 19:
            // DPAD Up
            console.log("Native UP Pressed");
            focusController.moveFocus({x: 0, y: 1});
            break;
        default:
            console.log("Keycode not registered");
            break;
    }
};

This example is probably far more complex than it needs to be, but if you get work through each piece above and try it out, you should get there without too much hassle

like image 90
Matt Gaunt Avatar answered Nov 06 '22 13:11

Matt Gaunt