Android NDK开发之HelloWorld
一、准备工作
-
下载NDK开发包:android-ndk-r16b-windows-x86_64.zip
-
解压NDK,解压路径需要全英文,并且不允许有空格(不可以解压到C:\Program Files路径)。此文中,我的解压路径为:
D:\Android\android-ndk
,此处的android-ndk为我修改后的文件夹名称,你也可以不修改,保留解压后的原始名称 -
Android Studio中新建project,路径需要全英文,并且不允许有空格,命名为
HelloJNI
, 包名为:com.jni
-
按照下图,设置项目的NDK路径
-
路径设置结束后,等待项目重新构建完成,然后按照下图,查看
local.properties
文件中是否有了ndk.dir=D\:\\Android\\android-ndk
字样,如果有,代表NDK路径设置成功
二、编写代码
-
新建java类HelloJava(自己随便定义,我这里加了后缀Java作为标记供读者区分),并在类中声明本地方法
package com.jni; public class HelloJava { static{ System.loadLibrary("HelloUtil"); } public static native String getHelloFromJNI(); }
-
工具栏上执行Build→Make Project操作,生成class
-
查看class文件是否生成
-
在
Terminal
中,输入指令生成头文件javah -d jni -classpath android.jar;app/src/main/java com.jni.HelloJava
。注意:如果你未对sdk设置环境变量,可把android.jar
替换为[你的sdk路径]\platforms\android-22\android.jar
-
在project下,新增了一个
jni
文件夹,生成的头文件就在其中。如果可以看到,则证明头文件生成成功。 -
在
jni
目录下新建HelloC.c(自己随便定义,我这里加了后缀C和后缀Java区分),include刚才生成的头文件,然后补全方法。#include "com_jni_HelloJava.h" JNIEXPORT jstring JNICALL Java_com_jni_HelloJava_getHelloFromJNI(JNIEnv *env, jclass thiz) { return (*env)->NewStringUTF(env, "Hello World From JNI!"); }
三、编译.so包
-
在刚才的
jni
目录下,新建Android.mk
文件,写入以下内容,第3、4行分别对应之前的moduleName和C源码LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := HelloUtil LOCAL_SRC_FILES := HelloC.c include $(BUILD_SHARED_LIBRARY)
-
在刚才的
jni
目录下,新建Application.mk
文件,写入以下内容APP_ABI := all
-
在app路径下的
build.gradle
中,配置ndk节点,moduleName
和HelloJava
代码中要加载的.so库名字要保持一致。其层级结构如下,配置完成后点击右上角的Sync Now
同步一下。android { defaultConfig { //其他配置......... //ndk节点 ndk{ moduleName "HelloUtil" ldLibs "log", "z", 'm' abiFilters "armeabi", "armeabi-v7a", "x86" } } }
-
在
Terminal
中,输入ndk-build
指令编译.so包,看到有.so输出,证明生成成功
四、调用
-
以上生成的.so文件还无法供
HelloJava
类进行加载和使用,需要拷贝到app\libs
路径下,如下图所示: -
将.so拷贝至对应目录后,还应在app路径下的
build.gradle
中,该指定jniLibs
。其层级结构如下,配置完成后点击右上角的Sync Now
同步一下。android { //增加sourceSets节点,并配置jniLibs路径 sourceSets { main { jniLibs.srcDirs = ['libs'] } } }
-
在
MainActivity
中调用HelloJava.
,运行项目,出现吐司,成功。@Override protected void onResume() { super.onResume(); String helloStr = HelloJava.getHelloFromJNI(); Toast.makeText(this, helloStr, Toast.LENGTH_SHORT).show(); }