Search code examples
androidjava-native-interface

Send MotionEvent from Java to JNI


Is it possible to send MotionEvent from Java to C++ through JNI?

I have a method in C++ that should receive a pointer to AInputEvent to send it to the Game class:

JNIEXPORT void JNICALL
Java_com_game_ActivityMain_onTouch(JNIEnv *jenv, jclass obj,jobject event) {
    AInputEvent* inputEvent=(AInputEvent*)event;
    game->OnInput(inputEvent);
    }
};

in Java I declared the native method as:

public static native void onTouch(MotionEvent event);

but the application crashes when I tab on the screen.

Edit:

I guess this can't be done since Java TouchEvent and JNI AInputEnvent is not the same type. so what should I do?

Edit 2: I created a struct in JNI side and fill its fields by calling methods, is this the best scenario?

jclass eventClss=jenv->GetObjectClass(event);
jmethodID methodId = jenv->GetMethodID(eventClss, "getX", "()F");
float x = jenv->CallFloatMethod(event, methodId);

Solution

  • I understood both AInputEvent and MotionEvent are different type and can't be cast to each other, so I send MotionEvent as jobject and accessed its method and fields using the JNI Environment.

    JNIEXPORT void JNICALL
    Java_com_game_ActivityMain_onTouch(JNIEnv *jenv, jclass obj,jobject motionEvent) {
        jclass motionEventClass=jenv->GetObjectClass(motionEvent);
    
        jmethodID pointersCountMethodId = jenv->GetMethodID(motionEventClass,"getPointerCount", "()I");
        int pointersCount = jenv->CallIntMethod(motionEvent, pointersCountMethodId);
        jmethodID getActionMethodId = jenv->GetMethodID(motionEventClass, "getAction", "()I");
        int32_t action = jenv->CallIntMethod(motionEvent, getActionMethodId);
    
        jmethodID getXMethodId = jenv->GetMethodID(motionEventClass, "getX", "(I)F");
        float x0 = jenv->CallFloatMethod(motionEvent, getXMethodId,0);
    
        jmethodID getYMethodId = jenv->GetMethodID(motionEventClass, "getY", "(I)F");
        float y0 = jenv->CallFloatMethod(motionEvent, getYMethodId,0);
    
        float x1=0;
        float y1=0;
        if(pointersCount>1){
            x1 = jenv->CallFloatMethod(motionEvent, getXMethodId,1);
            y1 = jenv->CallFloatMethod(motionEvent, getYMethodId,1);
        }
    
        States::MotionEvent inputEvent;
        inputEvent.PointersCount=pointersCount;
        inputEvent.Action=action;
        inputEvent.X0=x0;
        inputEvent.Y0=y0;
        inputEvent.X1=x1;
        inputEvent.Y1=y1;
        game->OnMotionEvent(inputEvent);
    }