1. 创建JNI.java文件,实现方法
public class JNI {
static {
System.loadLibrary("demo_03");
}
//传递 int 类型的数据
public native int add(int x,int y);
//传递String
public native String sayHelloInc(String str);
//传递int类型的数组
public native int[] arrElementsIncrease(int[] intArray);
}
2. 初始化,调用Native方法,并提示返回值
2.1 Demo布局文件 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_pass_int"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:text="传递Int类型数据"
android:textAllCaps="false"
app:layout_constraintBottom_toTopOf="@id/btn_pass_string"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btn_pass_string"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:text="传递String类型数据"
android:textAllCaps="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_pass_int_array"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:text="传递int类型数组"
android:textAllCaps="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_pass_string" />
</androidx.constraintlayout.widget.ConstraintLayout>
2.2 Java调用类实现 MainActivity.java
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private JNI jni;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
jni = new JNI();
initView();
}
//初始化View
private void initView() {
binding.btnPassInt.setOnClickListener(view -> {
int result = jni.add(3, 5);
Toast.makeText(getApplicationContext(), String.valueOf(result), Toast.LENGTH_SHORT).show();
});
binding.btnPassString.setOnClickListener(view -> {
String result = jni.sayHelloInc("abcedf");
Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show();
});
binding.btnPassIntArray.setOnClickListener(view -> {
int[] arr = {1, 2, 3, 4, 5, 6};
// 直接修改数组中的值
jni.arrElementsIncrease(arr);
String str = "";
for (int i : arr)
str += i;
Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT).show();
});
}
}
2.3 C++ 实现接口文件
2.3.1 CMakeLists.txt文件
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.18.1)
# Declares and names the project.
project("demo_03")
add_library( # Sets the name of the library.
demo_03
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
Java_JNI.cpp)
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
target_link_libraries( # Specifies the target library.
demo_03
# Links the target library to the log library
# included in the NDK.
${log-lib})
2.3.2 Java_JNI.cpp文件
#include <jni.h>
#include <cstdlib>
#include <cstring>
#include <android/log.h>
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
/* Header for class com_example_demo_03_javac_JNI */
#ifndef _Included_com_example_demo_03_javac_JNI
#define _Included_com_example_demo_03_javac_JNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_demo_03_javac_JNI
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_example_demo_103_1javac_JNI_add
(JNIEnv *env, jobject obj, jint a, jint b) {
return a + b;
}
char *jStringToChar(JNIEnv *env, jstring jstr) {
char *rtn = NULL;
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("GB2312");
jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
jsize alen = env->GetArrayLength(barr);
jbyte *ba = env->GetByteArrayElements(barr, JNI_FALSE);
if (alen > 0) {
rtn = (char *) malloc(alen + 1);
memcpy(rtn, ba, alen);
rtn[alen] = 0;
}
env->ReleaseByteArrayElements(barr, ba, 0);
return rtn;
}
/*
* Class: com_example_demo_03_javac_JNI
* Method: sayHelloInc
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_demo_103_1javac_JNI_sayHelloInc
(JNIEnv *env, jobject obj, jstring str) {
// char *cstr = jStringToChar(env, str);
char *cstr = (char *) env->GetStringUTFChars(str, nullptr);
//获取C字符串的长度
int len = strlen(cstr);
//for 循环执行完 cstr 每一个元素都 +1 了
for (int i = 0; i < len; ++i) {
*(cstr + i) += 1;
}
return env->NewStringUTF(cstr);
}
/*
* Class: com_example_demo_03_javac_JNI
* Method: arrElementsIncrease
* Signature: ([I)[I
*/
JNIEXPORT jintArray JNICALL Java_com_example_demo_103_1javac_JNI_arrElementsIncrease
(JNIEnv *env, jobject obj, jintArray intArray) {
//获取数组的长度
jsize len = env->GetArrayLength(intArray);
LOGI("length = %d",len);
//获取数组首地址
jint *intArr = env->GetIntArrayElements(intArray, JNI_FALSE);
for (int i = 0; i < len; ++i) {
//intArr[i] += 2;
*(intArr + i) += 2;
}
//jintArray newIntArray = env->NewIntArray(len);
//把计算的值赋值到原有的数组中
env->SetIntArrayRegion(intArray, 0, len, intArr);
//返回数组
return intArray;
}
#ifdef __cplusplus
}
#endif
#endif
3. 向android logcat 输出日志
#include <android/log.h>
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
//实现打印
LOGI("length = %d",len);