基本数据类型的使用
在MainActivity
中修改 name 的值,将值Lsm
修改为TimmyDuncan
MainActivity
代码:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Example of a call to a native method
findViewById<TextView>(R.id.sample_text).text = stringFromJNI()
println("name修改前是:$name")
changeName()
println("name修改后是:$name")
println("age修改前是:$age")
changeAge()
println("age修改后是:$age")
}
val name:String = "Lsm"
private val age:Int = 18;//用native修改为 29
/**
* A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ external fun stringFromJNI(): String
external fun changeName()
external fun changeAge()
companion object {
// Used to load the 'native-lib' library on application startup.
init {
System.loadLibrary("native-lib")
}
}
}
想要修改Lsm的值 先创建external fun changeName()
通过changName,修改Lsm
native-lib.cpp
相关代码:
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_lsm_sociax_jni_1test_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C"//下面的代码采用C的编译方式,无论是C还是C++最终都是JNINativeInterface* 结构体
JNIEXPORT //JNIEXPORT:JNI重要标记关键字,不能少,少了会报错/规则(标记为该方法可以被外部调用),为了统一Window版本,as可以因为android是linux
void //void 代表java中的void
JNICALL //也是一个关键字,(可以少的) jni call(约束函数入栈顺序和堆栈内存清理的规则
//方法名 = 包名 +类名 + 方法
// jobject 谁调用 谁的对象this 静态的话是jclass
Java_com_lsm_sociax_jni_1test_MainActivity_changeName(JNIEnv *env, jobject thiz) {//JNIEnv 是整个JNI的桥梁
//如果当前是native-lib.c
//(*env)->xxx函数 C是二级指针 C++是一级指针
//(*env)->DeleteLocalRef(env,null);//C是没有对象的,想持有env环境,必须包env传递进去
//String 对象引用 都是object
jclass mainActivityCls = env->FindClass("com/lsm/sociax/jni_test/MainActivity");
jfieldID nameFid = env->GetFieldID(mainActivityCls,"name","Ljava/lang/String;");//属性的签名 可以
jstring value = env->NewStringUTF("TimmyDuncan");
env->SetObjectField(thiz,nameFid,value);
}extern "C"
JNIEXPORT void JNICALL
Java_com_lsm_sociax_jni_1test_MainActivity_changeAge(JNIEnv *env, jobject thiz) {
jclass mainActivityCls = env->FindClass("com/lsm/sociax/jni_test/MainActivity");
jfieldID ageFil = env->GetFieldID(mainActivityCls,"age","I");
env->SetIntField(thiz,ageFil,29);
}
使用JNI 调用java方法
java代码:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Example of a call to a native method
findViewById<TextView>(R.id.sample_text).text = stringFromJNI()
callAddMethod()
}
/**
* A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ external fun stringFromJNI(): String
external fun callAddMethod();//C 调用java方法--> add(ing number1,)
//被C调用的方法
public fun add(number1:Int,number2:Int):Int
{
return number1 + number2;
} companion object {
// Used to load the 'native-lib' library on application startup.
init {
System.loadLibrary("native-lib")
}
}
}
JNI代码:
#include <jni.h>
#include <string>
//日志输出
#include <android/log.h>
#define TAG "Lsm"
//__VA_ARGS__代表 ...可变参数
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)
extern "C" JNIEXPORT jstring JNICALL
Java_com_lsm_sociax_jni_1test_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C"//下面的代码采用C的编译方式,无论是C还是C++最终都是JNINativeInterface* 结构体
JNIEXPORT //JNIEXPORT:JNI重要标记关键字,不能少,少了会报错/规则(标记为该方法可以被外部调用),为了统一Window版本,as可以因为android是linux
void //void 代表java中的void
JNICALL //也是一个关键字,(可以少的) jni call(约束函数入栈顺序和堆栈内存清理的规则
//方法名 = 包名 +类名 + 方法
// jobject 谁调用 谁的对象this 静态的话是jclass
Java_com_lsm_sociax_jni_1test_MainActivity_changeName(JNIEnv *env, jobject thiz) {//JNIEnv 是整个JNI的桥梁
//如果当前是native-lib.c
//(*env)->xxx函数 C是二级指针 C++是一级指针
//(*env)->DeleteLocalRef(env,null);//C是没有对象的,想持有env环境,必须包env传递进去
//String 对象引用 都是object
jclass mainActivityCls = env->FindClass("com/lsm/sociax/jni_test/MainActivity");
jfieldID nameFid = env->GetFieldID(mainActivityCls,"name","Ljava/lang/String;");//属性的签名 可以
jstring value = env->NewStringUTF("TimmyDuncan");
env->SetObjectField(thiz,nameFid,value);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_lsm_sociax_jni_1test_MainActivity_callAddMethod(JNIEnv *env, jobject thiz) {
jclass mainActivityCls = env->GetObjectClass(thiz);
jmethodID addMid = env->GetMethodID(mainActivityCls,"add","(II)I");
int result = env->CallIntMethod(thiz,addMid,1,1);
LOGD("result:%d\n",result);
}
JNI 接收 java传递过来的参数
- java层代码:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
jniObj1()
}
/**
* A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ external fun stringFromJNI(): String
external fun jniObject(count:Int,textInfo:String,intList:IntArray,stringList:Array<String>)
companion object {
// Used to load the 'native-lib' library on application startup.
init {
System.loadLibrary("native-lib")
}
}
fun jniObj1(){
var listInt = intArrayOf(1,2,3,4,5)
var listString = arrayOf("lsm","yl","wy")
jniObject(3,"timmyDuncan",listInt,listString)
listInt.forEach { i ->
println("java经过C++修改的数组$i")
}
}
}
2.JNI层的代码
#include <jni.h>
#include <string>
//日志输出
#include <android/log.h>
#define TAG "Lsm"
//__VA_ARGS__代表 ...可变参数
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)
extern "C" JNIEXPORT jstring JNICALL
Java_com_lsm_sociax_jni_1test2_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}extern "C"
JNIEXPORT void JNICALL
Java_com_lsm_sociax_jni_1test2_MainActivity_jniObject(JNIEnv *env, jobject thiz, jint count,
jstring text_info, jintArray int_list,
jobjectArray string_list) {
int _count = count;
LOGD("java传递进来的count是:%d\n",_count);
const char *_text_info = env->GetStringUTFChars(text_info, 0);//第二个参数是否需要Copy机制转换,这里不需要所以是0
LOGD("java传递进来的count是:%s\n",_text_info);
//C/C++用完是需要释放资源
env->ReleaseStringUTFChars(text_info,_text_info);
jint *_int_list = env->GetIntArrayElements(int_list,0);
int int_list_size = env->GetArrayLength(int_list);
for (int i = 0; i < int_list_size; ++i) {
LOGD("java传递进来的int数组是:%d\n",*(_int_list +i));
*(_int_list + i) = 1000 + i;
LOGD("java传递进来的int数组是:%d\n",*(_int_list +i));
}
/*
第三个参数mode的值:
JNI_OK 本次C++的修改的数组,刷新给JVM,java层,并且释放C++数组
JNI_COMMIT 本次C++的修改的数组,刷新给JVM,java层
JNI_ABORT 只释放C++数组
* */ env->ReleaseIntArrayElements(int_list,_int_list,JNI_OK);
}
在JNI中创建JAVA对象,并调用对象的方法
- 两个实体类:
class Person {
private var student: Student? = null
fun setStudent(student: Student) {
println(
"java调用了Person的setStudent方法->name=${
student.name
}---age=${student.age}"
)
this.student = student
}
fun getStudent(): Student? {
return this.student
}
}
class Student {
var name: String? = null
var age: Int? = null
constructor(name: String?, age: Int?) {
this.name = name;
this.age = age
}
}
- 在MainActivity中调用JNI方法
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Example of a call to a native method
findViewById<TextView>(R.id.sample_text).text = stringFromJNI()
newObjectPerson()
}
/**
* A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ external fun stringFromJNI(): String
external fun newObjectPerson()
companion object {
// Used to load the 'native-lib' library on application startup.
init {
System.loadLibrary("native-lib")
}
}
}
- 在JNI中创建对象,并使用
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_lsm_sociax_jni_1test3_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}extern "C"
JNIEXPORT void JNICALL
Java_com_lsm_sociax_jni_1test3_MainActivity_newObjectPerson(JNIEnv *env, jobject thiz) {
jclass personClass = env->FindClass("com/lsm/sociax/jni_test3/Person");
jobject personObj = env->AllocObject(personClass);//C++分配一个对象出来,但不会调用构造函数
//env->NewObject() //C++实例化出一个对象,会调用构造函数
jmethodID setStudent = env->GetMethodID(personClass,"setStudent", "(Lcom/lsm/sociax/jni_test3/Student;)V");
//实例化Student类
jclass studentClass = env->FindClass("com/lsm/sociax/jni_test3/Student");
//Student类的构造方法
jmethodID studentInitMethod = env->GetMethodID(studentClass,"<init>", "(Ljava/lang/String;Ljava/lang/Integer;)V");
jstring name = env->NewStringUTF("TimmyDuncan");
//创建一个Integer对象,kotlin int是一个对象
jclass intClass = env->FindClass("java/lang/Integer");
jmethodID intInit = env->GetMethodID(intClass,"<init>", "(I)V");
jobject intObj = env->NewObject(intClass,intInit,18);
//传承Student的对象
jobject studentObj = env->NewObject(studentClass,studentInitMethod,name,intObj);
env->DeleteLocalRef(intObj);
env->DeleteLocalRef(name);
//调用person的setStudent
env->CallVoidMethod(personObj,setStudent,studentObj);
//释放工作
env->DeleteLocalRef(personObj);
env->DeleteLocalRef(studentObj);//释放对象
}