AS创建项目时选择NativeC++
会创建一个基本的JNI项目
MainActivity中写java层的native方法
具体实现在cpp文件中
native-lib.cpp
#include <jni.h>
#include <string>
extern "C"
JNIEXPORT
jstring JNICALL
Java_com_cn_techvision_jnidemo2_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C" //采用c的编译方式
JNIEXPORT //JNI重要标记关键字,不能少
jstring //返回值String
JNICALL //也是个关键字(linux可以少) 约束函数入栈顺序和堆栈内存清理规则
//注意此处函数命名规则,包名类名方法名
Java_com_cn_techvision_jnidemo2_MainActivity_getStr(JNIEnv *env, jobject thiz) {
// TODO: implement getStr()
//如果是.c文件
//(*env)->xxx函数
//如果是.cpp
//env->xxx函数
}
JNIEnv在c层和java的桥梁,不可缺少
jobject 是MainActivity的this实例(调用者)
如果getStr是一个static方法,那么这里应该是个jclass
cpp:
extern "C" //采用c的编译方式
JNIEXPORT //JNI重要标记关键字,不能少
void //返回值void
JNICALL //也是个关键字(linux可以少) 约束函数入栈顺序和堆栈内存清理规则
//注意此处函数命名规则,包名类名方法名
Java_com_cn_techvision_jnidemo2_MainActivity_getStr(JNIEnv *env, jobject thiz) {
// TODO: implement getStr()
//获取jclass对象
jclass clazz=env->FindClass("com/cn/techvision/jnidemo2/MainActivity");
//jfieldID GetFieldID(jclass clazz, const char* name, const char* sig)
jfieldID nameFid=env->GetFieldID(clazz,"name", "Ljava/lang/String;");
jstring value=env->NewStringUTF("helloworld");
//void SetObjectField(jobject obj, jfieldID fieldID, jobject value)
env->SetObjectField(thiz,nameFid,value);
}
MainActivity:
public class MainActivity extends AppCompatActivity {
// Used to load the 'jnidemo2' library on application startup.
static {
System.loadLibrary("jnidemo2");
}
private ActivityMainBinding binding;
private String name="hello";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// Example of a call to a native method
TextView tv = binding.sampleText;
getStr();
tv.setText(name);
}
/**
* A native method that is implemented by the 'jnidemo2' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
public native void getStr();
}
cpp:
extern "C"
JNIEXPORT void JNICALL
Java_com_cn_techvision_jnidemo2_MainActivity_callAddMethod(JNIEnv *env, jobject thiz) {
// TODO: implement callAddMethod()
jclass clazz=env->GetObjectClass(thiz);
jmethodID addMethod=env->GetMethodID(clazz,"add", "(II)I");
int result=env->CallIntMethod(thiz,addMethod,1,1);
LOGD("result:%d\n",result);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_cn_techvision_jnidemo2_MainActivity_callShowStrMethod(JNIEnv *env, jobject thiz) {
// TODO: implement callShowStrMethod()
jclass clazz=env->GetObjectClass(thiz);
jmethodID showStrMethod=env->GetMethodID(clazz,"showString", "(Ljava/lang/String;)Ljava/lang/String;");
jstring str= static_cast<jstring>(env->CallObjectMethod(thiz, showStrMethod,
env->NewStringUTF("helloworld")));
jstring s=(jstring)env->CallObjectMethod(thiz,showStrMethod,env->NewStringUTF("helloworld"));
//string转换为char
const char * resultStr=env->GetStringUTFChars(s,NULL);
LOGD("result:%s\n",resultStr);
}
java:
private int add(int num1,int num2){
return num1+num2;
}
private String showString(String str){
return "["+str+"]";
}
public native void callAddMethod();
public native void callShowStrMethod();
上面一些方法中出现的const char* sig参数就是方法签名,用来表示字段的类型,常见字段类型示例:
Z:boolean类型
B:byte类型
C:char类型
S:short类型
I:int类型
J:long类型
F:float类型
D:double类型
[<>:数组类型,例如[I表示int数组
L<>;:引用类型,例如Ljava/lang/String;表示String类型