#include <stdio.h>
#include <jni.h>
#include <malloc.h>
#include <android/log.h>
#include "cn_zengfanheng_ccallinjava_DataProvider.h"
#include "cn_zengfanheng_ccallinjava_MainActivity.h"
#define LOG_TAG "System.out.c" //在LogCat上打印出来的Tag
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
//零、工具类:返回值 char* 这个代表char数组的首地址
//Jstring2CStr 把java中的jstring的类型转化成一个c语言中的char 字符串
char* Jstring2CStr(JNIEnv* env, jstring jstr) {
char* rtn = NULL;
jclass clsstring = (*env)->FindClass(env, "java/lang/String"); //String
jstring strencode = (*env)->NewStringUTF(env, "GB2312"); // 得到一个java字符串 "GB2312"
jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes",
"(Ljava/lang/String;)[B"); //[ String.getBytes("gb2312");
jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid,
strencode); // String .getByte("GB2312");
jsize alen = (*env)->GetArrayLength(env, barr); // byte数组的长度
jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);
if (alen > 0) {
rtn = (char*) malloc(alen + 1); //"\0"
memcpy(rtn, ba, alen);
rtn[alen] = 0;
}
(*env)->ReleaseByteArrayElements(env, barr, ba, 0); //
return rtn;
}
// 一、C调用java空方法,返回void , public void helloFromJava()
JNIEXPORT void JNICALL Java_cn_zengfanheng_ccallinjava_DataProvider_callMethodFromJava1
(JNIEnv *env, jobject obj) {
//调用过程类似java中的反射
//1、找到这个类
//jclass (*FindClass)(JNIEnv*, const char*);
jclass dpclazz = (*env)->FindClass(env,"cn/zengfanheng/ccallinjava/DataProvider");
if (dpclazz==0) {
LOGI("find class error");
return;
}
//2、找到java中要调用的方法的id (..方法名,方法签名)
// jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
jmethodID methodId1 = (*env)->GetMethodID(env,dpclazz,"helloFromJava", "()V");
if(methodId1==0){
LOGI("find method1 error");
return;
}
LOGI("find methodId1 success ");
//3、调用返回值为空的方法
//void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
(*env)->CallVoidMethod(env,obj,methodId1);
LOGI("callMethodFromJava1------------------------end");
}
// 二、C调用java中的带两个int参数的方法,然后返回一个int值 , public int addFromJava(int x, int y)
JNIEXPORT void JNICALL Java_cn_zengfanheng_ccallinjava_DataProvider_callMethodFromJava2
(JNIEnv * env, jobject obj) {
//1、找到这个类
// jclass (*FindClass)(JNIEnv*, const char*);
jclass dpclazz = (*env)->FindClass(env, "cn/zengfanheng/ccallinjava/DataProvider");
if (dpclazz==0) {
LOGI("find class error");
return;
}
//2、找到java中要调用的方法的id (env,jcalss,方法名,方法签名)
//jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
jmethodID methodId2 = (*env)->GetMethodID(env,dpclazz,"addFromJava","(II)I"); // (II)I int (int,int),其他查看jni.h的 union jvalue
//jmethodID methodId2 = (*env)->GetMethodID(env,dpclazz,"addFromJava"," (II)I");//注意:参数四,前面不要有空格
if(methodId2==0){
LOGI("find method2 error");
return;
}
LOGI("find methodId2 success ");
//3、调用返回值为int的方法
//jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
int x = 3,y = 5;
jint addresult = (*env)->CallIntMethod(env,obj,methodId2,x,y);
LOGI("%d+%d=%d",x,y,addresult);
LOGI("callMethodFromJava2------------------------end");
}
// 三、C调用java中参数为string的方法,返回void , public void printStringFromJava(String s)
JNIEXPORT void JNICALL Java_cn_zengfanheng_ccallinjava_DataProvider_callMethodFromJava3
(JNIEnv *env, jobject obj) {
//1、找到这个类
//jclass (*FindClass)(JNIEnv*, const char*);
jclass dpclazz = (*env)->FindClass(env, "cn/zengfanheng/ccallinjava/DataProvider");
if (dpclazz==0) {
LOGI("find class error");
return;
}
//2、找到java中要调用的方法的id (..方法名,方法签名)
//jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
jmethodID methodId3 = (*env)->GetMethodID(env,dpclazz,"printStringFromJava","(Ljava/lang/String;)V");
if(methodId3==0){
LOGI("find methodId3 error");
return;
}
LOGI("find methodId3 success ");
//3、调用返回值为空的,参数为String的方法
//void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
//将char*转换成java中的String类型。
//jstring (*NewStringUTF)(JNIEnv*, const char*);
char* ch = "→i am from c !";
jstring jstr = (*env)->NewStringUTF(env,ch);
(*env)->CallVoidMethod(env,obj,methodId3,jstr);
LOGI("callMethodFromJava3------------------------end");
}
// 4、C调用java中参数为string的方法,返回String public String getNameFromJava(String s)
JNIEXPORT void JNICALL Java_cn_zengfanheng_ccallinjava_DataProvider_callMethodFromJava4
(JNIEnv *env, jobject obj){
//1、找到这个类
//jclass (*FindClass)(JNIEnv*, const char*);
jclass dpclazz = (*env)->FindClass(env, "cn/zengfanheng/ccallinjava/DataProvider");
if (dpclazz==0) {
LOGI("find class error");
return;
}
//2、找到java中要调用的方法的id (..方法名,方法签名)
//jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
jmethodID methodId4 = (*env)->GetMethodID(env,dpclazz,"getNameFromJava","(Ljava/lang/String;)Ljava/lang/String;");
if(methodId4==0){
LOGI("find methodId4 error");
return;
}
LOGI("find methodId4 success ");
//3、执行方法
//jobject (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);
char* ch = "hacket";
jstring jstr = (*env)->NewStringUTF(env,ch);
jstring name = (*env)->CallObjectMethod(env,obj,methodId4,jstr);
char* myname = Jstring2CStr(env,name);
LOGI("c--%s",myname);
LOGI("callMethodFromJava4------------------------end");
}
//5、C调用java中static静态方法,参数为String,返回为void , public static void printStaticStr(String s)
JNIEXPORT void JNICALL Java_cn_zengfanheng_ccallinjava_DataProvider_callMethodFromJava5
(JNIEnv * env, jobject obj) {
//1、找到这个类
//jclass (*FindClass)(JNIEnv*, const char*);
jclass dpclazz = (*env)->FindClass(env, "cn/zengfanheng/ccallinjava/DataProvider");
if (dpclazz==0) {
LOGI("find class error");
return;
}
//注意:静态的方法,不一样
//2、找到java中要调用的方法的id (..方法名,方法签名)
// jmethodID (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*);
jmethodID methodId5 = (*env)->GetStaticMethodID(env,dpclazz,"printStaticStr","(Ljava/lang/String;)V");
if(methodId5==0){
LOGI("find methodId5 error");
return;
}
LOGI("find methodId5 success ");
//3、执行方法,静态方法,返回void,参数String
//void (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);
char* ch = "i am in c static";
jstring jstr = (*env)->NewStringUTF(env,ch);
(*env)->CallStaticVoidMethod(env,dpclazz,methodId5,jstr);
LOGI("callMethodFromJava5------------------------end");
}
//6、C调用的方法的和native方法的声明不在同一个类中 ,在不同的类中,调用helloFromJava
JNIEXPORT void JNICALL Java_cn_zengfanheng_ccallinjava_MainActivity_call_1dp_1callMethodFromJava1
(JNIEnv *env, jobject obj) {
//1、找到这个类
//jclass (*FindClass)(JNIEnv*, const char*);
jclass dpclazz = (*env)->FindClass(env, "cn/zengfanheng/ccallinjava/DataProvider");
if (dpclazz==0) {
LOGI("find class error");
return;
}
//2、找到java中要调用的方法的id (..方法名,方法签名)
//jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
jmethodID methodId6 = (*env)->GetMethodID(env,dpclazz,"helloFromJava","()V");
if(methodId6==0){
LOGI("find methodId6 error");
return;
}
LOGI("find methodId6 success ");
//3、由于不是在同一类中,声明的native方法,此obj代表的是MainActivity,obj不对。而要调用的方法在DataProvider,所以要new出来调用java的方法所在的类
// jobject (*AllocObject)(JNIEnv*, jclass);
jobject dp_obj = (*env)->AllocObject(env,dpclazz);
//4、执行方法,由于不是在同一类中,obj不同
//void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
(*env)->CallVoidMethod(env,dp_obj,methodId6,jstr);
LOGI("callMethodFromJava6------------------------end");
}