android ndk环境搭建就不详细介绍。
首先介绍NDK方法直接返回字符串
1、env->NewStringUTF(char* str)
2、先把char*或者char[]数组转化为字符串变量,代码如下:
jstring pcharToJstring(JNIEnv* env, const char* pat, const char* encoding)
{
jclass gStringClass;
jmethodID gmidStringInit;
jmethodID gmidStringGetBytes;
gStringClass= (*env)->FindClass(env,"java/lang/String");
gmidStringGetBytes= (*env)->GetMethodID(env,gStringClass, "getBytes", "(Ljava/lang/String;)[B");
gmidStringInit= (*env)->GetMethodID(env,gStringClass, "<init>", "([BLjava/lang/String;)V");
jstring jencoding;
jbyteArray bytes = (*env)->NewByteArray(env,strlen(pat));
(*env)->SetByteArrayRegion(env,bytes, 0, strlen(pat), (jbyte*)pat);
if (encoding==NULL)
jencoding= (*env)->NewStringUTF(env,"utf-8");
else
jencoding=(*env)->NewStringUTF(env,encoding);
return (jstring)(*env)->NewObject(env,gStringClass, gmidStringInit, bytes, jencoding);
}
上述代码主要把一个char*字符串转化为java String对象。
上面是方法直接返回字符串,下面讲述NDK方法返回Hello(练习代码随变取名)类里面含有String类型
Hello.java类代码
public class Hello {
private int age;
private String name;
public Hello(int age, String name){
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Hello{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
hello-jni.c代码
#include <string.h>
#include <jni.h>
#include <android/log.h>
#define LOG_TAG "LOG_TEST"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
jstring pcharToJstring(JNIEnv* env, const char* pat, const char* encoding)
{
jclass gStringClass;
jmethodID gmidStringInit;
jmethodID gmidStringGetBytes;
gStringClass= (*env)->FindClass(env,"java/lang/String");
gmidStringGetBytes= (*env)->GetMethodID(env,gStringClass, "getBytes", "(Ljava/lang/String;)[B");
gmidStringInit= (*env)->GetMethodID(env,gStringClass, "<init>", "([BLjava/lang/String;)V");
jstring jencoding;
jbyteArray bytes = (*env)->NewByteArray(env,strlen(pat));
(*env)->SetByteArrayRegion(env,bytes, 0, strlen(pat), (jbyte*)pat);
if (encoding==NULL)
jencoding= (*env)->NewStringUTF(env,"utf-8");
else
jencoding=(*env)->NewStringUTF(env,encoding);
return (jstring)(*env)->NewObject(env,gStringClass, gmidStringInit, bytes, jencoding);
}
jobject
Java_com_example_carrry_androidtest_MainActivity_stringFromJNI( JNIEnv* env,
jobject thiz )
{
char temp[30] = {'m','y',' ','i','s',' ','j','k'};
char* hellos = NULL;
jclass pedestrainDeadReckoningClass = (*env)->FindClass(env,"com/example/carrry/androidtest/util/Hello");
jmethodID pedestrainDeadReckoningClassInit = (*env)->GetMethodID(env,pedestrainDeadReckoningClass, "<init>", "(ILjava/lang/String;)V");
jstring hello = pcharToJstring(env,temp,hellos);
int age = 20;
return (*env)->NewObject(env,pedestrainDeadReckoningClass,pedestrainDeadReckoningClassInit,age,hello);
}
c里面代码主要先把char*字符串转化为JAVA String对象,再返回
public native Hello stringFromJNI();
static {
System.loadLibrary("hello-jni");
}
Hello str = stringFromJNI();
button.setText(str.toString());
需要注意的小细节:
1、Java类的全地址
jclass pedestrainDeadReckoningClass = (*env)->FindClass(env,"com/example/carrry/androidtest/util/Hello");
2、new出Java类型对象参数一定要正确
jmethodID pedestrainDeadReckoningClassInit = (*env)->GetMethodID(env,pedestrainDeadReckoningClass, "<init>", "(ILjava/lang/String;)V");
这类型和个数一定要和你调用Java类的结构体类型和个数一样
总结:
c返回一个Java类对象,首先取到Java类地址(包名+类名),再取Java类的结构体参数个数和类型,再使用(*env)->NewObject方法把JAVA对象new出来。一般好久不使用NDK容易把参数个数和类型这东西忘记。