最近接触到Android编程下的JNI开发,根据上一篇文章环境配置,下面我想通过我的学习记录一下实践笔记。
首先按照上一篇文章建好工程,可以不使用系统提供创建好的native-lib文件,而是自己创建一个 javacall.c
上一篇文章地址:
Android studio2.2 构建C/C++工程
其次,编辑新建JNI.java,新建本地方法
public native int add(int x,int y);
public native String callformC(String s);
public native int[] intArray(int []array);
public native int checkPwd(String pwd);
在AS中ctrl +/ 可以自动生成对应的C方法
然后就可以在生成对应的C方法中编写响应的测试逻辑
由于java的String 字符串传递过来是不能在C中直接使用,在网上找到一个把一个jstring转换成一个c语言的char* 类型的方法(原理是反射调用javad的 getByte方法)
char* _JString2CStr(JNIEnv* env, jstring jstr) {
char* rtn = NULL;
jclass clsstring = (*env)->FindClass(env, "java/lang/String");
jstring strencode = (*env)->NewStringUTF(env,"GB2312");
jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid, strencode); // String .getByte("GB2312");
jsize alen = (*env)->GetArrayLength(env, barr);
jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);
if(alen > 0) {
rtn = (char*)malloc(alen+1);
memcpy(rtn, ba, alen);
rtn[alen]=0;
}
(*env)->ReleaseByteArrayElements(env, barr, ba,0);
return rtn;
}
传递两个 int 类型数字相加返回的方法
JNIEXPORT jint JNICALLJava_com_mao_javacallc_JNI_add(JNIEnv *env, jobject instance, jint x, jint y) {
LOGI("x+y= %d",x+y);
return x+y;
}
传入字符串拼接返回的方法
JNIEXPORT jstring JNICALLJava_com_mao_javacallc_JNI_callformC(JNIEnv *env, jobject instance, jstring s) {
char * fromjava = _JString2CStr(env,s);//调用上面的字符串转char方法将传递进来的String装换成C的char类型
char *fromc="add from c";
//将连个字符串拼接返回给java
strcat(fromjava,fromc);//拼接好的字符串放在第一个参数里面
return (*env)->NewStringUTF(env, fromjava);
}
传入字int类型数组,数组经过处理返回int类型
JNIEXPORT jintArray JNICALLJava_com_mao_javacallc_JNI_intArray(JNIEnv *env, jobject instance, jintArray jstr) {
int length=(*env)->GetArrayLength(env,jstr);
jint *pInt = (*env)->GetIntArrayElements(env, jstr, JNI_FALSE);
int i;
for (i=0;i<length;i++){ *(pInt+i)+=10;//做位移操作}
return jstr;
}
模拟验证密码是否的方法
JNIEXPORT jint JNICALLJava_com_mao_javacallc_JNI_checkPwd(JNIEnv *env, jobject instance, jstring pwd_client) {
//将输入的密码转换成char
char *fromusr=_JString2CStr(env,pwd_client);
char * server="123";//模拟验证正确密码
//比较两个字符串是否相同
int code=strcmp(server,fromusr);
if(code==0){
return 200;}
else{ return 400;}
}
C中的方法写好了之后别忘了在JNI.java中添加动态链接库文件
static {
System.loadLibrary("javacallc");
}
然后,写个简单的布局,在MainActivity中监听调用这些本地方法就可以实现对写好的C方法调用(逻辑和布局比较简单,这里就不贴了)。
最后来几张运行成功的截图: