gpt4 book ai didi

java - Android:从 NativeActivity 使用 JNI

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:57:56 27 4
gpt4 key购买 nike

我们正在使用 NativeActivity 在 Android 上开发一个 OpenGL 游戏类(class)。到目前为止一切顺利,但现在我们需要访问一些似乎只能从 Java 获得的功能。

还有更多,但我们认为第一个有用的是访问显示 DPI。如所述here Java 代码如下所示:

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);

这里是不幸的对应 C++ 代码:

// My checking routine.
#define JNI_ASSERT(jni, cond) { \
if (!(cond)) {\
std::stringstream ss; \
ss << __FILE__ << ":" << __LINE__; \
throw std::runtime_error(ss.str()); \
} \
if (jni->ExceptionCheck()) { \
std::stringstream ss; \
ss << __FILE__ << ":" << __LINE__; \
throw std::runtime_error("Exception: " + ss.str()); \
} \
}

void print_dpi(android_app* app) {
JNIEnv* jni;
app->activity->vm->AttachCurrentThread(&jni, NULL);

jclass activityClass = jni->FindClass("android/app/NativeActivity");
JNI_ASSERT(jni, activityClass);

jmethodID getWindowManager = jni->GetMethodID
( activityClass
, "getWindowManager"
, "()Landroid/view/WindowManager;");
JNI_ASSERT(jni, getWindowManager);

jobject wm = jni->CallObjectMethod(app->activity->clazz, getWindowManager);
JNI_ASSERT(jni, wm);

jclass windowManagerClass = jni->FindClass("android/view/WindowManager");
JNI_ASSERT(jni, windowManagerClass);

jmethodID getDefaultDisplay = jni->GetMethodID( windowManagerClass
, "getDefaultDisplay"
, "()Landroid/view/Display;");
JNI_ASSERT(jni, getDefaultDisplay);

jobject display = jni->CallObjectMethod(wm, getDefaultDisplay);
JNI_ASSERT(jni, display);

jclass displayClass = jni->FindClass("android/view/Display");
JNI_ASSERT(jni, displayClass);

// Check if everything is OK so far, it is, the values it prints
// are sensible.
{
jmethodID getWidth = jni->GetMethodID(displayClass, "getWidth", "()I");
JNI_ASSERT(jni, getWidth);

jmethodID getHeight = jni->GetMethodID(displayClass, "getHeight", "()I");
JNI_ASSERT(jni, getHeight);

int width = jni->CallIntMethod(display, getWidth);
JNI_ASSERT(jni, true);
log("Width: ", width); // Width: 320

int height = jni->CallIntMethod(display, getHeight);
JNI_ASSERT(jni, true);
log("Height: ", height); // Height: 480
}

jclass displayMetricsClass = jni->FindClass("android/util/DisplayMetrics");
JNI_ASSERT(jni, displayMetricsClass);

jmethodID displayMetricsConstructor = jni->GetMethodID( displayMetricsClass
, "<init>", "()V");
JNI_ASSERT(jni, displayMetricsConstructor);

jobject displayMetrics = jni->NewObject( displayMetricsClass
, displayMetricsConstructor);
JNI_ASSERT(jni, displayMetrics);

jmethodID getMetrics = jni->GetMethodID( displayClass
, "getMetrics"
, "(Landroid/util/DisplayMetrics;)V");
JNI_ASSERT(jni, getMetrics);

jni->CallVoidMethod(display, getMetrics, displayMetrics);
JNI_ASSERT(jni, true);

{
jfieldID xdpi_id = jni->GetFieldID(displayMetricsClass, "xdpi", "F");
JNI_ASSERT(jni, xdpi_id);

float xdpi = jni->GetFloatField(displayMetricsClass, xdpi_id);
JNI_ASSERT(jni, true);

log("XDPI: ", xdpi); // XDPI: 0
}

{
jfieldID height_id = jni->GetFieldID( displayMetricsClass
, "heightPixels", "I");
JNI_ASSERT(jni, height_id);

int height = jni->GetIntField(displayMetricsClass, height_id);
JNI_ASSERT(jni, true);

log("Height: ", height); // Height: 0
}
// TODO: Delete objects here.
app->activity->vm->DetachCurrentThread();
}

代码输出:

Width: 320
Height: 480
XDPI: 0
Height: 0

好像 displayMetrics 对象没有在调用中设置

jni->CallVoidMethod(display, getMetrics, displayMetrics);

是不是 JNI 不允许我使用参数作为返回值?如果是这样,鉴于我们使用的是 NativeActivity 胶水,我们如何绕过它。

最佳答案

哎呀,我已经盯着代码看了几个小时了,但没看到。然后离开办公 table ,回来发现它是:

代替这两行

float xdpi = jni->GetFloatField(displayMetricsClass, xdpi_id);
int height = jni->GetIntField(displayMetricsClass, height_id);

我应该使用:

float xdpi = jni->GetFloatField(displayMetrics, xdpi_id);
int height = jni->GetIntField(displayMetrics, height_id);

杜:)

(至少它可以作为一个例子,如果有人想通过艰难的方式获得 DPI :))

关于java - Android:从 NativeActivity 使用 JNI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13249164/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com