从 Java 发送 MotionEvent 到 JNI

问题描述 投票:0回答:2

是否可以通过JNI将

MotionEvent
从Java发送到C++?

我有一个 C++ 方法,应该接收指向 AInputEvent 的指针,并将其发送到 Game 类:

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

在Java中我将本机方法声明为:

public static native void onTouch(MotionEvent event);

但是当我在屏幕上点击选项卡时应用程序崩溃了。

编辑:

我想这是不可能的,因为 Java

TouchEvent
和 JNI
AInputEnvent
不是同一类型。那我该怎么办?

编辑2: 我在 JNI 端创建了一个结构体,并通过调用方法填充其字段,这是最好的场景吗?

jclass eventClss=jenv->GetObjectClass(event);
jmethodID methodId = jenv->GetMethodID(eventClss, "getX", "()F");
float x = jenv->CallFloatMethod(event, methodId);
android java-native-interface
2个回答
1
投票

我知道

AInputEvent
MotionEvent
是不同的类型,不能相互转换,所以我将
MotionEvent
作为
jobject
发送,并使用
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);
}

0
投票

通常您可以使用 AMotionEvent_fromJava,但它只能从 API 31 中使用。但是您可以尝试在 AMotionEvent_fromJava 函数内部执行相同的操作。 这里有一个解释:

MotionEvent.java 有原生 C++ 类 MotionEvent,可以在 MotionEvent.java 中的“private long mNativePtr”指向的地址访问。 C++类MotionEvent继承自AInputEvent 所以接下来的事情可以完成(就像它在 AMotionEvent_fromJava 函数中完成的那样)

// Given
JNIEnv *env;
jobject motionEventObj;
// Get AInputEvent* from motionEventObj
static jfieldID NativePtr = [&env]()
{
    auto clazz = env->FindClass("android/view/MotionEvent");
    assert(clazz);
    auto field = env->GetFieldID(clazz, "mNativePtr", "J");
    assert(field);
    return field;
}();
AInputEvent* event = reinterpret_cast<AInputEvent*>(env->GetLongField(eventObj, NativePtr));
© www.soinside.com 2019 - 2024. All rights reserved.