调用C层代码步骤:
1.第一步JniDataUtil.java中编写java层的native代码
2.在/app/src/app/java目录下执行javah命令生成javah -jni com.ldw.jnitest.JniDataUtil生成.h文件
3.编辑test.cpp代码,实现.h中需要实现的c语言的方法
4.在jni目录下执行ndk-build.cmd命令生成so文件
5.在MainActivity.java中调用JniDataUtil.java中的native方法,简介调用c语言的方法
JniDataUtil.java
package com.ldw.jnitest;
/**
* author: ldw
* created on: 2019/10/13 2:13
* description:
*/
public class JniDataUtil {
private static JniDataUtil instance = null;
//设置一个单例
public static JniDataUtil getInstance() {
if (instance == null) {
instance = new JniDataUtil();
}
return instance;
}
// 动态导入 so 库
static {
System.loadLibrary("JNITest");
}
//创建一个 native 方法
public native void jni_void();
public native static String jni_string();
public native int jni_int(int a, int b);
public native boolean jni_boolean(boolean a);
public native static String jni_string_params(String str1, String str2);
public native void jni_array(int [] array);
}
com_ldw_jnitest_JniDataUtil.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_ldw_jnitest_JniDataUtil */
#ifndef _Included_com_ldw_jnitest_JniDataUtil
#define _Included_com_ldw_jnitest_JniDataUtil
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_ldw_jnitest_JniDataUtil
* Method: jni_void
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_ldw_jnitest_JniDataUtil_jni_1void
(JNIEnv *, jobject);
/*
* Class: com_ldw_jnitest_JniDataUtil
* Method: jni_string
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_ldw_jnitest_JniDataUtil_jni_1string
(JNIEnv *, jclass);
/*
* Class: com_ldw_jnitest_JniDataUtil
* Method: jni_int
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_ldw_jnitest_JniDataUtil_jni_1int
(JNIEnv *, jobject, jint, jint);
/*
* Class: com_ldw_jnitest_JniDataUtil
* Method: jni_boolean
* Signature: (Z)Z
*/
JNIEXPORT jboolean JNICALL Java_com_ldw_jnitest_JniDataUtil_jni_1boolean
(JNIEnv *, jobject, jboolean);
/*
* Class: com_ldw_jnitest_JniDataUtil
* Method: jni_string_params
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_ldw_jnitest_JniDataUtil_jni_1string_1params
(JNIEnv *, jclass, jstring, jstring);
/*
* Class: com_ldw_jnitest_JniDataUtil
* Method: jni_array
* Signature: ([I)V
*/
JNIEXPORT void JNICALL Java_com_ldw_jnitest_JniDataUtil_jni_1array
(JNIEnv *, jobject, jintArray);
#ifdef __cplusplus
}
#endif
#endif
test.cpp
#include<jni.h>
#include <android/log.h>
//导入我们创建的头文件
#include "com_ldw_jnitest_JniDataUtil.h"
#ifdef __cplusplus
extern "C" {
#endif
//自定义方法
void JNI_show()
{
__android_log_print(ANDROID_LOG_ERROR,"jni_show", "Function from test.cpp=====JNI_show()");
return;
}
/*
* Class: com_ldw_jnitest_JniDataUtil
* Method: jni_void
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_ldw_jnitest_JniDataUtil_jni_1void
(JNIEnv * env, jobject obj)
{
JNI_show();
}
/*
* Class: com_ldw_jnitest_JniDataUtil
* Method: jni_string
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_ldw_jnitest_JniDataUtil_jni_1string
(JNIEnv * env, jclass obj)
{
return env->NewStringUTF("Function from test.cpp=====jni_string()");
}
/*
* Class: com_ldw_jnitest_JniDataUtil
* Method: jni_int
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_ldw_jnitest_JniDataUtil_jni_1int
(JNIEnv * env, jobject obj, jint jni_a, jint jni_b)
{
int a = (int) jni_a;
int b = (int) jni_b;
__android_log_print(ANDROID_LOG_ERROR,"jni_show", "JNI: a = %d, b = %d", a, b);
int c = 20;
return (jint)c;
}
/*
* Class: com_ldw_jnitest_JniDataUtil
* Method: jni_boolean
* Signature: (Z)Z
*/
JNIEXPORT jboolean JNICALL Java_com_ldw_jnitest_JniDataUtil_jni_1boolean
(JNIEnv * env, jobject obj, jboolean jni_b)
{
//JNI_TRUE JNI_FALSE
bool arg_bool = (jni_b == JNI_TRUE)?true:false;
__android_log_print(ANDROID_LOG_ERROR,"jni_show", "JNI: bool = %s",
((arg_bool == true) ? "true":"false"));
return (arg_bool == true)?JNI_TRUE:JNI_FALSE;
}
/*
* Class: com_ldw_jnitest_JniDataUtil
* Method: jni_string_params
* Signature: (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_ldw_jnitest_JniDataUtil_jni_1string_1params
(JNIEnv * env, jclass cla, jstring jni_str1, jstring jni_str2)
{
//jstring --- >char*
const char *c_str1 = NULL;
const char *c_str2 = NULL;
//将java中的字符串转换成char*类型
c_str1 = env->GetStringUTFChars(jni_str1, 0);
__android_log_print(ANDROID_LOG_ERROR,"testjni", "JNI: c_str1 = %s",c_str1);
//释放java传递过来jstring里面的在堆上开辟的字符串空间
env->ReleaseStringUTFChars(jni_str1, c_str1);
c_str2 = env->GetStringUTFChars(jni_str2, 0);
__android_log_print(ANDROID_LOG_ERROR,"testjni", "JNI: c_str2 = %s",c_str2);
env->ReleaseStringUTFChars(jni_str2, c_str2);
//给java返回一个字符串
jstring ret_j_string = env->NewStringUTF("JNI return String jni_string_params(String str1, String str2)");
return ret_j_string;
}
/*
* Class: com_ldw_jnitest_JniDataUtil
* Method: jni_array
* Signature: ([I)V
*/
JNIEXPORT void JNICALL Java_com_ldw_jnitest_JniDataUtil_jni_1array
(JNIEnv * env, jobject, jintArray jni_int_array)
{
//获取java中 jni_int_array数组的首地址
jint *pia = env->GetIntArrayElements(jni_int_array, 0);
//得到数组的长度
jsize array_len = env->GetArrayLength(jni_int_array);
//使用该pia pia[1] pia[2]
for (int i = 0; i < array_len; i++) {
__android_log_print(ANDROID_LOG_ERROR,"testjni", "JNI:array[%d]:%d",i, (int)pia[i]);
}
//释放j_int_array数据空间
env->ReleaseIntArrayElements(jni_int_array, pia, 0);
}
#ifdef __cplusplus
}
#endif
调用JNI方法的java文件MainActivity.java
package com.ldw.jnitest;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private Button btn;
public static String LOG_TAG = "MainActivity===";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initUi();
}
public void initUi(){
btn = (Button) findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
JniDataUtil.getInstance().jni_void();
Log.e(LOG_TAG, "jni_boolean===" +JniDataUtil.getInstance().jni_string());
Log.e(LOG_TAG, "jni_int===" + JniDataUtil.getInstance().jni_int(12,24) );
Log.e(LOG_TAG,"jni_boolean===" + JniDataUtil.getInstance().jni_boolean(true));
Log.e(LOG_TAG,"jni_string_params===" + JniDataUtil.getInstance().jni_string_params("jni_string_params_str1", "jni_string_params_str2"));
int[] aList = {1, 2, 3, 4, 5, 6};
JniDataUtil.getInstance().jni_array(aList);
}
});
}
}
输出:
2019-10-13 07:46:38.721 18568-18568/com.ldw.jnitest E/jni_show: Function from test.cpp=====JNI_show()
2019-10-13 07:46:38.721 18568-18568/com.ldw.jnitest E/MainActivity===: jni_boolean===Function from test.cpp=====jni_string()
2019-10-13 07:46:38.721 18568-18568/com.ldw.jnitest E/jni_show: JNI: a = 12, b = 24
2019-10-13 07:46:38.721 18568-18568/com.ldw.jnitest E/MainActivity===: jni_int===20
2019-10-13 07:46:38.721 18568-18568/com.ldw.jnitest E/jni_show: JNI: bool = true
2019-10-13 07:46:38.722 18568-18568/com.ldw.jnitest E/MainActivity===: jni_boolean===true
2019-10-13 07:46:38.722 18568-18568/com.ldw.jnitest E/testjni: JNI: c_str1 = jni_string_params_str1
2019-10-13 07:46:38.722 18568-18568/com.ldw.jnitest E/testjni: JNI: c_str2 = jni_string_params_str2
2019-10-13 07:46:38.722 18568-18568/com.ldw.jnitest E/MainActivity===: jni_string_params===JNI return String jni_string_params(String str1, String str2)
2019-10-13 07:46:38.722 18568-18568/com.ldw.jnitest E/testjni: JNI:array[0]:1
2019-10-13 07:46:38.722 18568-18568/com.ldw.jnitest E/testjni: JNI:array[1]:2
2019-10-13 07:46:38.722 18568-18568/com.ldw.jnitest E/testjni: JNI:array[2]:3
2019-10-13 07:46:38.722 18568-18568/com.ldw.jnitest E/testjni: JNI:array[3]:4
2019-10-13 07:46:38.722 18568-18568/com.ldw.jnitest E/testjni: JNI:array[4]:5
2019-10-13 07:46:38.722 18568-18568/com.ldw.jnitest E/testjni: JNI:array[5]:6
截图如下: