Android JNI入门到基础

发布时间:2023年12月24日

一、JNI项目创建

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

二、通过native方法修改Java变量值

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();
}

三、native函数调用java方法

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();

调用这两个native函数结果:
在这里插入图片描述

四、方法签名

上面一些方法中出现的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类型

文章来源:https://blog.csdn.net/qq_56892136/article/details/135149541
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。