Are shift mappings of Android NDK keycodes standardized?

112 views
Skip to first unread message

Andreas Falkenhahn

unread,
Aug 21, 2016, 4:28:49 PM8/21/16
to andro...@googlegroups.com
I am wondering whether there is an official reference as to how certain keycodes are
passed through the Android NDK. Take the question mark (?) for example. AFAICS, there
is no AKEYCODE_XXX definition in keycodes.h for the question mark. I did some tests
and it looks like the question mark keycode is actually sent as AKEYCODE_SLASH with
shift on, i.e. AKeyEvent_getMetaState() has the AMETA_SHIFT_ON flag set.

The same can be observed for other keycodes, here are few examples:

- { is sent as AKEYCODE_LEFT_BRACKET with shift on
- } is sent as AKEYCODE_RIGHT_BRACKET with shift on
- : is sent as AKEYCODE_SEMICOLON with shift on
- > is sent as AKEYCODE_PERIOD with shift on
- < is sent as AKEYCODE_COMMA with shift on
etc.

It pretty much seems to conform to the mappings on a standard US keyboard. However, there
are some exceptions:

- on a US keyboard, the * is normally generated by pressing 8 plus shift; Android, however,
has its own AKEYCODE_STAR for the * character
- also, on a US keyboard the + is normally generated by pressing = plus shift; Android,
however, has its own AKEYCODE_PLUS definition here

To cut a long story short, I was wondering whether there is some official explanation of this
behaviour. Is this documented and standardized behaviour? Is there a table or something in
the official Android developer docs that shows how certain keycodes should be treated if shift
is on? I.e. is there a table in the Android docs that says that AKEYCODE_SEMICOLON has to be
treated as : if shift is on? Or is this all undocumented behaviour?

Furthermore, I'm interested if this behaviour is consistent across all Android versions and
locales, e.g. will the shift mapping described above also hold true on Chinese Android phones?

Finally, what about combining shift with keys which are already shift keys on a US keyboard?
e.g. AKEYCODE_STAR and AKEYCODE_PLUS. Can it also happen that those are sent with shift on and
do they have to be mapped to some other keys than as well?

I hope somebody can shed some light on this. Thanks!

--
Best regards,
Andreas Falkenhahn mailto:and...@falkenhahn.com

J Decker

unread,
Aug 21, 2016, 6:10:57 PM8/21/16
to andro...@googlegroups.com
1) what is the api you're using the get the key?

The key characters are given to you in an event; you don't need key translation stables... (for isntance select russian as your keyboard input, they still give the same keycodes, but there is a key value)

engine->key_text = AndroidGetKeyText( event );
err I guess that's my own JNI method from somewhere...



------------
extern "C" int AndroidGetKeyText( AInputEvent *event )
{
   int result = 0;
    // Attaches the current thread to the JVM. 
    jint lResult; 
    jint lFlags = 0; 

    JavaVM* lJavaVM = engine.app->activity->vm; 
    JNIEnv* lJNIEnv = engine.app->activity->env; 

    JavaVMAttachArgs lJavaVMAttachArgs; 
    lJavaVMAttachArgs.version = JNI_VERSION_1_6; 
    lJavaVMAttachArgs.name = "NativeThread"; 
    lJavaVMAttachArgs.group = NULL; 

    lResult=lJavaVM->AttachCurrentThread(&lJNIEnv, &lJavaVMAttachArgs);
    if (lResult == JNI_ERR) { 
        return 0;
    } 

    // Retrieves NativeActivity. 
    jobject lNativeActivity = engine.app->activity->clazz; 
jclass ClassNativeActivity = lJNIEnv->GetObjectClass(lNativeActivity);
jmethodID MethodSetFlags = lJNIEnv->GetMethodID(      ClassNativeActivity, "getKeyText", "(JJIIIIIII)I");
   lprintf( "..." );
if( MethodSetFlags )
result = lJNIEnv->CallIntMethod( lNativeActivity,  MethodSetFlags
, AKeyEvent_getDownTime(event)
, AKeyEvent_getEventTime(event)
, AKeyEvent_getAction(event)
, AKeyEvent_getKeyCode(event)
, AKeyEvent_getRepeatCount(event)
, AKeyEvent_getMetaState(event)
, AInputEvent_getDeviceId(event)
, AKeyEvent_getScanCode(event)
, AKeyEvent_getFlags(event)
);
else
{
         lprintf( "Failed to get method." );
result = 0;
}


// Finished with the JVM. 
lJavaVM->DetachCurrentThread();
      return result;
}

--------
The java code..


int prior_key; 
    public int getKeyText (long downTime, long eventTime, int action, int code, int repeat, int metaState, int deviceId, int scancode, int flags, int source) {
   KeyEvent key;
            Log.v( "org.d3x0r.sack.mynative", "got to having a key...." );
            key = new KeyEvent( downTime, eventTime, action, code, repeat, metaState, deviceId, scancode, flags, source );
   int result = key.getUnicodeChar();
            Log.v( "org.d3x0r.sack.karway.mynative", "key immediate result is " + result );
   String s_result = key.getCharacters();

            Log.v( "org.d3x0r.sack.mynative", "key immediate result is " + s_result );

            if( ( result &  KeyCharacterMap.COMBINING_ACCENT ) != 0 )
            {
            prior_key = result &  KeyCharacterMap.COMBINING_ACCENT_MASK;
                Log.v( "org.d3x0r.sack.mynative", "keeping key until next" );
                result = 0;
            }
            else
            {
                Log.v( "org.d3x0r.sack.mynative", "prior is " + prior_key );
           if( prior_key != 0 )
                    {
                      
              result = KeyCharacterMap.getDeadChar( prior_key, result );
                        prior_key = 0;
                    }
            }
            return result;
     }

-----------

but that didn't help for international methods.
Some several NDK versions ago (maybe from 10?)  

NativeActivity supports OnKeyDown

  public boolean onKeyDown(int keyCode, KeyEvent event)
  {
  Log.d( "MyNativeActivity", "Key down event!" + event.getUnicodeChar() );
        int keymod = event.getMetaState();
        keymod = ( ( keymod & ( KeyEvent.META_SHIFT_RIGHT_ON | KeyEvent.META_SHIFT_LEFT_ON | KeyEvent.META_SHIFT_ON ) ) != 0 ? 1 : 0 )
               | ( ( keymod & ( KeyEvent.META_CTRL_RIGHT_ON | KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON ) ) != 0 ? 2 : 0 )
               | ( ( keymod & ( KeyEvent.META_ALT_RIGHT_ON | KeyEvent.META_ALT_LEFT_ON | KeyEvent.META_ALT_ON ) ) != 0 ? 4 : 0 );
        String chars = String.valueOf((char)event.getUnicodeChar());
        
        NativeStaticLib.sendKeyEvent( 1, event.getKeyCode(), event.getScanCode(), keymod, chars );
        return true;
  }

which really boils down to just


  public boolean onKeyDown(int keyCode, KeyEvent event)
  {
        String chars = String.valueOf((char)event.getUnicodeChar());
       // post string as keybaord input
        return true;
  }

This will even return macro keys like '.com' or ':-)'

but then you don't get the keys in the normal native activity pipes....

AKeyEvent_getKeyCode   fails for unicode characters in C++ code side...



--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to android-ndk+unsubscribe@googlegroups.com.
To post to this group, send email to andro...@googlegroups.com.
Visit this group at https://groups.google.com/group/android-ndk.
To view this discussion on the web visit https://groups.google.com/d/msgid/android-ndk/1064050295.20160818113359%40falkenhahn.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages