1、在C++层创建Java对象
在C++中获取到对应的Java对象,并通过setIntField()方法,对width属性进行赋值
//1、根据传入的包名获取到clazz对象(传入参数的为完整包名)
jclass clazz = env -> FindClass("java/util/date")
//2、根据clazz对象我们可以获取到构造方法
jmethodID construcotr = env -> GetMethodId(clazz,"<init>","()V");
//3、根据获取到的构造方法可以获取到对象
jobject obj = env -> NewObject(clazz, construcotr);
//根据clazz对象获取到对应方法
jmethodID getWidthId = env -> GetMethodId(clazz,"getWidth","()I");
//根据clazz对象我们还可以获取到mWidth这个属性
jfieldID widthId = env -> GetFieldID(clazz,"mWidth","I");
//使用setIntField方法对mWidth这个属性赋值
env -> setIntField(obj,widthId,outImage.width());
GetMethodID能够取得构造防范的jmethodID, 如果传入的要取得的方法名称设为“<init>”就能够取得构造方法,构造方法的方法返回值的签名始终为void
java类型 | 字段描述符 |
boolean | Z |
byte | B |
char | C |
short | S |
int | I |
long | L |
float | F |
double | D |
void | V |
2、在C++其它线程里回调到Java层
在C++对应的Native方法中:
//定义全局变量
JavaVM *g_VM;
jobject g_obj;
(在Native方法中)
//javaVM是虚拟机在JNI中的表示,等下其它线程回调到Java层会用到
env -> GetJava(&g_VM);
//生成一个全局引用保留下来,以便回调
//instance 是native方法传入的参数env后面那个参数jobject instance
//注:当native方法为静态方法时,instance代表native方法所属类的对象
//当native方法为非静态方法时,instance代表native方法所属的对象
env -> NewGlobalRef(instance)
(C++其它线程中)
JNIEnv *env;
bool hasAttached;
//获取当前native线程是否被附加到jvm环境中
jint getEnvState = g_VM -> GetEnv((void**)&env, JNI_VERSION_1_6);
//如果没有则主动附加到jvm环境中,获取到env
if(getEnvState<0){
if(g_VM -> AttachCurrentThread(&env, NULL)!=0){
return;
}else{
hasAttached = true;
}
}
//通过全局变量g_obj获取到要回调的类
jclass javaClass = env -> GetObjectClass(g_obj);
if(javaClass == 0){
g_VM -> DetachCurrentThread();
return;
}
//获取到要回调的方法ID
jmethodID javaCallbackId = env -> GetMethodID(javaClass, "onTestCallback", "(Ljava/lang/String;)v");
if(javaCallbackId == null){
LOGE("Unable to find Method:onTsetCallback");
return;
}
//执行回调
//msg.c_str():就是我们要在java中回调打出来的信息
env -> CallVoidMethod(g_obj, javaCallbackId, env->NewStringUTF(msg.c_str()));
//释放当前线程
if(hasAttached){
g_VM -> DetachCurrentThread();
}
env = null;
Java层对应的方法(同一个类中)
//total:就是C++中回调过来的 msg.c_str()
private void onTestCallback(String total){
//C++层回调后执行的操作
Log.e(TAG, total);
}