Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Receive all unicode characters from SoftInput when using android NativeActivity

I have an OpenGL application which uses NativeActivity. When I ask the name of the user, I call a java method via JNI to open a software keyboard for me. The game shows its own native text input dialog inside the OpenGL context. All unicode characters should be usable in the name.

public static void JNI_keyboardShow() {
    InputMethodManager imm = (InputMethodManager)Main.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.showSoftInput(m_window.getDecorView(), InputMethodManager.SHOW_IMPLICIT);
}

My java class extends KeyEvent.Callback so I receive keyboard input via overriden onKeyDown(int keyCode, KeyEvent event) and onKeyMultiple(int keyCode, int count, KeyEvent event) methods. I then pass the received input to my C++ application via JNI.

My problem is the handling of the non-ascii unicode characters in onKeyMultiple method. It looks like this:

@Override
public boolean onKeyMultiple (int keyCode, int count, KeyEvent event) {
    int unicode = event.getUnicodeChar();
    Log.e(TAG, "Unicode: " + unicode);

    String text = null;
    if(event.getAction() == KeyEvent.ACTION_MULTIPLE && keyCode == KeyEvent.KEYCODE_UNKNOWN) {
        text = event.getCharacters();
    }

    Log.e(TAG, "Text: " + text);
    if(text != null) {
        //call native function and pass string to it
        nativeOnKeyDown(text);
    }
    return true;
} 

For example when I enter a "laughing smiley" character on the keyboard the text is always interpreted as a "White vertical rectangle" - it should be shown as 😅. It is even shown as a rectangle when I examine the contents of the string in the debugger in Android Studio.

If I parse the text into bytes with text.GetBytes(Charset.forName("UTF-8")) I see that the byte representation differs with different unicode characters. However, if I pass the resulting byte array to C++ and parse it back to C++ string, the outcome is the same. The unicode character is shown as garbage.

The method event.getUnicodeChar() return always 0 in these cases.

My question is, how I can receive all keyboard presses from the soft keyboard? I really don't care how it is done, only that my C++ string receives the right unicode characters and then I can render them into screen.

Receive complete android unicode input in C/C++ is almost (but not quite) the same question. The difference is that I'd like to handle the keyboard input in Java side and only send the resulting characters back to C++ side. Also the code given in the answer faces the same problem: not all keyboard inputs result a right unicode character.

android - getting soft keyboard key presses discusses about this as well. It warns that the Official Android Page says that you never should rely on receiving key events for any key on a soft input method (an on-screen keyboard). The suggestion is to use TextWatcher interface to observe characters pressed on the software keyboard. If this is the way to go, I'd like to get some pointers how to implement this in my class which extends NativeActivity. I do not have any editable text fields in the application, only an OpenGL window.

For example, is it possible to put some transparent window/view/dialog on top of my OpenGL context and get the correct unicode characters from software keyboard that way?

like image 498
Scam Avatar asked Nov 08 '22 19:11

Scam


1 Answers

This seems to be a problem of Android Studio, which is not able to render UTF-8 characters in its debug console or debugger. If I start adb logging from the command line, correct UTF-8 characters appear in the logs.

Like I stated in the question, the byte representation differs with different unicode characters. And that is all that matters. If you pass the string to C++ (as a bytearray or as a string), all characters are correctly there.

I also changed the program to implement the TextWatcher interface instead of KeyEvent.Callback, but that's mostly because official Android documentation recommends to do so. But for the question it does not matter which interface/class you use to read the software keyboard.

like image 174
Scam Avatar answered Nov 14 '22 21:11

Scam