本文主要实现了,点击按钮,运行C中的方法,该C方法会调用java中的Toast
这是我的MainActivity:
package com.ctojava;
import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity {
static{
System.loadLibrary("ctojava");
}
private native void recall();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void start(String msg) {
System.out.println("toast已经被调用");
Toast.makeText(MainActivity.this, msg, 1).show();
}
public void click(View v) {
runOnUiThread(new Runnable() {
public void run() {
recall();
System.out.println("recall已经被调用");
}
});
}
}
这是系统生成.c文件后,自己编写的c代码:
#include <jni.h>
#include <android/log.h>
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
JNIEXPORT void JNICALL Java_com_ctojava_MainActivity_recall
(JNIEnv *env, jobject obj){
char* msg={"调用C"};
jclass class=(**env).FindClass(env,"com/ctojava/MainActivity");
LOGI("找到了类\n");
jmethodID id=(**env).GetMethodID(env,class,"start","(Ljava/lang/String;)V");
LOGI("找到了id\n");
(**env).CallVoidMethod(env, obj,id,(*env)->NewStringUTF(env,msg));
LOGI("调用了类\n");
}
在该文件中我添加了打印log的工具方法,这里不多叙述。
现在主要说明.c文件中是如何调用MainActivity中方法的:
1.
jclass class=(**env).FindClass(env,"com/ctojava/MainActivity");
FindClass方法的作用是找到调用方法的所属类。
参数1:拿到指针env
参数2:该类的路径。
2.
jmethodID id=(**env).GetMethodID(env,class,"start","(Ljava/lang/String;)V");
GetMethodID方法的作用是找到调用方法的id。
参数1:拿到指针env
参数2:1中找到的所属类(class)
参数3:该类中需调用方法的名字
参数4:该类中需调用方法的签名,想知道一个方法的签名,你必须在window控制台中 /进入到当前工程的 classes目录下, javah -s 包名.类,即可看到该类中所有方法的签 //名,这是我的签名显示:
GetMethodID方法的作用是找到调用方法的id。
参数1:拿到指针env
参数2:1中找到的所属类(class)
参数3:该类中需调用方法的名字
参数4:该类中需调用方法的签名,想知道一个方法的签名,你必须在window控制台中 /进入到当前工程的 classes目录下, javah -s 包名.类,即可看到该类中所有方法的签 //名,这是我的签名显示:
3.
(**env).CallVoidMethod(env, obj,id,(*env)->NewStringUTF(env,msg));
该方法的作用是开始调用Mainactivity中的start方法
参数1:拿到指针env
参数2:拿到执行此JNI操作的类实例引用
参数3:该类中需调用方法的id
参数4:你想传递的参数,这里需要调用NewStringUTF的方法,将C中char*类型的msg,转换成java中的String类型
注意:如果你C传递的数据是中文的,那么你的.c文件编码方式需要改为utf-8,否则会出错,方法如下(eclipse):右键.h文件 点击properties,选择编码方式为utf-8,注意点击apply保存