ndk遇到的坑
目录回调jobject时要注意
java->c 的时候传过来的jobject在方法调用完后就会没了
extern "C"
JNIEXPORT jlong JNICALL
Java_com_seekting_ndk2021_Clock_bind(JNIEnv *env, jobject thiz) {
if (!global_env) {
global_env = env;
}
Clock *clock = new Clock((intptr_t) &thiz, &onStateChange, &onClockChanged);//坑!这个对象会失效
LOGE("bind clock= %p,jobject= %p", clock, &thiz);
return (jlong) (clock);
}
如果想全局使用,可以借用NewGlobalRef来引用它
jobjectRef = env->NewGlobalRef(thiz);
env->DeleteGlobalRef(customObj);
异步线程无法使用JNIEnv
当*env传过来的时候,可以调用GetJavaVM把env存到g_jvm
JavaVM *g_jvm = NULL;
jobject g_obj = NULL;
void init(JNIEnv *env){
env->GetJavaVM(&g_jvm);
}
使用时 通过g_jvm->AttachCurrentThread
void onClockChanged(Clock *clock, string str) {
JNIEnv *env;
jclass cls;
jmethodID mid;
//Attach主线程
if(g_jvm->AttachCurrentThread(&env, NULL) != JNI_OK)
{
return;
}
异步线程无法FindClass
需要第一次传evn的时候提前find好,存成全局NewGlobalRef,方法Id也可以保存全局
jobject clockJClass;
jmethodID onStateChangeID;
jmethodID onClockChangedID;
void initClass(JNIEnv *env) {
jclass jclass = env->FindClass("com/seekting/ndk2021/Clock");
if (jclass == NULL) {
LOGE("#######not found class.\n");
return;
}
// 获取getLedId方法
onStateChangeID = env->GetMethodID(jclass, "onStateChange", "(JI)V");
if (onStateChangeID == NULL) {
LOGE("#######not found getLedId func.\n");
return;
}
// 获取getLedId方法
onClockChangedID = env->GetMethodID(jclass, "onClockChanged", "(JLjava/lang/String;)V");
if (onClockChangedID == NULL) {
LOGE("#######not found getLedId func.\n");
return;
}
clockJClass = env->NewGlobalRef(jclass);
}
使用时
void onClockChanged(Clock *clock, string str) {
JNIEnv *env;
//Attach主线程
if (g_jvm->AttachCurrentThread(&env, NULL) != JNI_OK) {
return;
}
jobject *jo = &(clock->object);//全局
long clock_jlong = reinterpret_cast<jlong>(clock);
// LOGE("clock=%p,jobject=%p,onStateChangeID=%p ", clock, jo, onClockChanged);
env->CallVoidMethod(*jo, onClockChangedID, clock_jlong,
env->NewStringUTF(str.c_str()));
}
函数指针实现方法回调
Clock(JNIEnv *env,jobject o, void (*onStateChange)(Clock *, int), void (*onClockChanged)(Clock *, string));
Clock::Clock(JNIEnv *env, jobject object, void(*onStateChange)(Clock *, int),
void(*onClockChanged)(Clock *, string)) {
}
不写方法返回还能编译通过
int test(){
//dosomething
}
以上代码能通过 run 编译通过;但是运行时就会报各种问题,但不会告诉你没有返回,你分析半天才知道没有返回
.c文件无法使用string
建议把文件改成.cpp