MAC环境下Android Studio的第一个JNI程序

时间:2022-08-27 08:58:39

MAC环境下Android Studio的第一个JNI程序

1、环境配置
开发JNI需要用到NDK的支持,需要另外下载NDK。
在Android Studio的设置窗口里面(在AVD按钮的左边一个扳手的按钮),打开android SDK界面,在SDK Tool标签下面找到NDK勾选后apply,然后就会启动下载。NDK下载完成后解压有点慢,到后面会出现卡死的假象,请耐心等待。
MAC环境下Android Studio的第一个JNI程序

2、创建新的类,完成配置文件
新建一个app空的工程。
然后再java目录下新建一个java类,这个类包含着native方法,其他java类可以通过调用他来完成native方法的调用。请看下面的例子。
MAC环境下Android Studio的第一个JNI程序

在JNIUtil.java里面的代码如下

public class JNIUtil {
static {
System.loadLibrary("NDKJNIUtil");//在build.gradle里面设置的so名字,必须一致
}

public static native String getStringFormC();
}

留意到上面System.loadLibrary(“NDKJNIUtil”),这里的NDKJNIUtil指定了要加载的so库(库的名字会变为”libNDKJNIUtil.so”),这个名字还必须添加到app Module的build.gradle文件中的defaultConfig之下。

defaultConfig {
applicationId "com.xxxxxx.ekulelu.jnitest"
minSdkVersion 21
targetSdkVersion 23
versionCode 1
versionName "1.0"

ndk {
moduleName "NDKJNIUtil" //与生成的so名字相关
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库,目前可有可无。
}
}
public static native String getStringFormC();

这段声明了一个native方法,这个方法会返回一个String类型。关于native方法,这里不多做介绍,可以自行百度。java类型和JNI类型有一个对照表可以参考。

3、生成.h头文件
使用终端定位到项目的java文件夹位置(在左边工程目录下对java文件夹右键,Reveal in Finder就可以弹出java文件夹所在的Finder,然后就可以将它拖入终端cd过去。)
现在终端定位到了java文件夹的位置,输入下面的代码

javah -jni com.xxxxxx.ekulelu.jnitest.JNIUtil  

-jni 后面跟的是JNIUtil的完全类名。
这样就会在java/com目录下生成一个com_xxxxxx_ekulelu_jnitest_JNIUtil.h头文件。注意这个头文件的命名,和你使用的那个类是一样的,只不过是用下划线来分割包名。头文件里面的代码如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_xxxxxx_ekulelu_jnitest_JNIUtil */

#ifndef _Included_com_xxxxxx_ekulelu_jnitest_JNIUtil
#define _Included_com_xxxxxx_ekulelu_jnitest_JNIUtil
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_xxxxxx_ekulelu_jnitest_JNIUtil
* Method: getStringFormC
* Signature: ()Ljava/lang/String;
*/

JNIEXPORT jstring JNICALL Java_com_xxxxxx_ekulelu_jnitest_JNIUtil_getStringFormC
(JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

为了将jni文件和java文件分开来,可以在工程目录下面新建一个jni文件夹,专门存放jni相关文件。只需在工程目录下右键New->Folder->JNI Folder,在弹出的窗口中勾选Change Folder Location点击确定,就会在和java文件夹同级下生成一个jni目录。然后就可以将刚刚生成的.h头文件移动到jni文件夹里面。(注:在android studio工程目录下移动的话,需要切换到Project视图才可以移动。)完成后,工程目录如下
MAC环境下Android Studio的第一个JNI程序

4、实现头文件
在jni目录下新建一个.c文件(文件名随便取),里面要实现刚刚头文件里面的那个函数。实现如下代码,这里这个函数返回了一个字符串。

#include "com_xxxxxx_ekulelu_jnitest_JNIUtil.h"  //注意引入刚刚的头文件。

/*
* Class: com_xxxxxx_ekulelu_jnitest_JNIUtil
* Method: getStringFormC
* Signature: ()Ljava/lang/String;
*/


JNIEXPORT jstring JNICALL Java_com_xxxxxx_ekulelu_jnitest_JNIUtil_getStringFormC
(JNIEnv *env, jobject obj){
return (*env)->NewStringUTF(env,"这里是来自jni的string");
}

5、在java类中调用native方法
新建的android工程不是有个hello world的文本控件吗?直接用它来显示从native方法里面得到的字符串就行了。创建JNIUtil对象,然后调用方法得到从native方法来的字符串,设置到textView中显示。

TextView textView = (TextView) findViewById(R.id.textV1); //用id得到TextView控件。
JNIUtil jniUtil = new JNIUtil();
String str = jniUtil.getStringFormC();
textView.setText(str);
Log.e("EK",str);

编译运行工程。效果如下
MAC环境下Android Studio的第一个JNI程序
logcat打印
MAC环境下Android Studio的第一个JNI程序

6、so文件
切换到project视图,在app->bulid->intermediates->ndk->debug->lib下面可以找到三个不同体系的so文件,这三个平台对应了build.gradle文件里面的配置。如果配置文件的这项不填,那么将会生成7个体系的so文件。
MAC环境下Android Studio的第一个JNI程序

7、总结
android studio使用jni也不是太复杂,慢慢来就行了。需要注意的是要配置好ndk,否则会出现很多莫名奇妙的错误。另外建议创建新的类来写native方法,不要直接写入到MainActivity中,因为有时候会出现不能解析出头文件的情况。