赞
踩
https://github.com/linweimao/NDK-C-Java-
运行报错: CCallJava\ccalljava0
运行不会报错: CCallJava\app
ccalljava0:日志打印了,Toast奔了
日志打印了就说明(showToast)这个方法确实被调用了
报的错误是空指针异常(NullPointerException)
为什么会出错呢?
启动一个 Activity 是通过 startActivity 进行启动,通过 startActivity 启动的Activity 就有Activity 的生命周期,如果通过new的方式去new 一个 Activity ,那么Activity 没有生命周期,就是一个普通类。
那么因为反射的方式去把 MainActivity 这个类 new 出来,那么它就没有 Activity 的生命周期,那么同时就没有Activity的上下文,那么这里实例化的这个类(MainActivity.this)就不是上下文了
Toast.makeText(MainActivity.this, "showToast------", Toast.LENGTH_SHORT).show();
MainActivity 是一个 Activity 同时也是一个类,启动 startActivity,同时也可以new它(MainActivity ),new一个Activity (MainActivity)相当于把它当成普通类了。
原因就是在CCallJava中的反射实例化,把它 new 出来,new出来就不是上下文了 ,所以 Toast.makeText 去得到它的资源文件的时候就会空指针,因为它根本就不是一个上下文了
jclass jclazz = (*env)->FindClass(env, "com/lwm/ccalljava/MainActivity");
将 JNITest 类中的 callBackShowToast() 方法剪切至 MainActivity 中
/*
* 当执行这个方法的时候,让 C 代码调用 MainActivity 里面的
* public void showToast()方法
*
*/
public native void callBackShowToast();
调用该方法时相当于
public void CallBackShowtoast() {
//当我们调用 callbackAdd 方法,那么 callbackAdd 方法会通过C代码回调add方法
//jniTest.callBackShowToast();//不用这个了,而直接用下面的
MainActivity.this.callBackShowToast();
}
重新创建 callBackShowToast() 方法的头文件在 CCallJava 中
JNIEXPORT void JNICALL
Java_com_lwm_ccalljava_MainActivity_callBackShowToast(JNIEnv *env, jobject instance)
复制上面的4个步骤至 Java_com_lwm_ccalljava_MainActivity_callBackShowToast 下,并且不用第三步的实例化**(此时的 instance 的实例是 MainActivity.this )**
/* * * instance:谁调用了当前 Java_com_lwm_ccalljava_JNITest_callBackShowToast对应的Java接口, * 就是谁的实例:当前是 JNI.this(因为需要在 MainActivity中使用 jniTest.callBackShowToast()进行调用,此时为 jniTest 去调用,因此当前是 JNI.this) * 而现在的实例是 MainActivity.this * * (就相当于谁调用 JNITest 类中的callBackShowToast()方法,因为调用 callBackShowToast()方法才触发 Java_com_lwm_ccalljava_JNITest_callBackShowToast) */ //在 MainActivity 下不用实例化了,直接使用传过来的 instance void Java_com_lwm_ccalljava_MainActivity_callBackShowToast(JNIEnv *env, jobject instance) { //让 C 代码调用 MainActivity 里面的 public void showToast()方法 //1、得到字节码(字节码是用于实例化这个类) jclass jclazz = (*env)->FindClass(env, "com/lwm/ccalljava/MainActivity"); //2、得到方法 //GetMethodID()中最后一个参数是方法签名(这里需要MainActivity类的签名,调谁就用谁的签名,调用那个方法就用哪个方法中的类) //jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*); jmethodID jmethodIDs = (*env)->GetMethodID(env, jclazz, "showToast", "()V"); //3、实例化该类 //jobject (*AllocObject)(JNIEnv*, jclass); //jobject jobject1 = (*env)->AllocObject(env,jclazz); //4.调用方法 //void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...); (*env)->CallVoidMethod(env,instance,jmethodIDs); //成功调用了 public void showToast()方法 }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。