1.去NDK官网下载mac版的ndk,然后自己解压出来。
2.打开androidStudio正常新建一个显示"hello world" 的android工程.
3.配置NDK路径
(a)点击菜单栏File, ProjectStructure
(b)在弹出的窗口里,左侧选中SDKLocation
(c)然后在右侧Android NDK Location中填入刚才解压出来的NDK目录的路径,如图:
上面蓝色选中的路径就是我的NDK存放的路径。
4.编译生成.class文件。点菜单栏的Build, Make Project
这时,在工程的app/build/intermediates下就会生成classes文件夹,打开classes目录下的debug目录就会看到以你的包名命名的各级文件夹,最里边文件夹下有Java类对应的.class文件
5.假如现在要在mainActivity引用jni方法。在MainActivity类里添加下面代码
static { System.loadLibrary("myNativeLib"); }
这是用于声明本地代码库。
6.定义native方法(先在java层定义,待会到C里面去实现内容)。比如输入:
public native String getStringFromNative();
7.使用javah命令行生成jni目录及对应的头文件。
(a)进入当前java目录,也就是包的外层的目录(src/main/java)。
(b)在androidStudio下面底部的终端(Terminal)输入:
javah -d ../jni 你的包名.引用本地方法的类的名称
javah意思是生成一个.h头文件,-d ../jni的意思是生成一个位置是在当前目录(src/main/java)的上一级目录(即src/main目录)名字叫做jni的文件夹(directory);
比如我的工程下,这条命令是
javah -d ../jni com.example.yucan.mytest.MainActivity
然后就可以在工程目录下看到新建的jni文件夹下的头文件:
到这里,我们就基本相当于完成了相当于Eclipse中的add native support功能了。
8.配置app模块下的build.gradle文件。
在build.gradle的defaultConfig下加入以下ndk配置:
ndk { moduleName"myNativeLib" abiFilters "armeabi", "armeabi-v7a", "x86" }
其中moduleName是与上面在Java类中使用System.loadLobrary(“本地库名称”);以及生成的.so文件名称对应的;
abiFilters指的是我们要生成哪些平台的so文件,这里生成arm平台和x86平台;
配置完成,如图:
这一步有点像我们eclipse中配置.mk文件
9.打开工程目录下的local.properties。看看是否有这行代码
ndk.dir=/Users/yucan/NDK/android-ndk-r14b
如果上面配好了NDK路径,讲道理是有的,如果没有自己按照自己的NDK路径加上去。
10.打开工程目录下的gradle.properties文件,在文件的最后一行加入:
android.useDeprecatedNdk=true
这句的作用是允许我们使用已经过时的NDK版本,不知道AndroidStudio要求使用哪个版本的NDK才不会报错,总之只要配置了这一句就可以使用比较旧的NDK版本了。
11.接下来就是写C层的代码了(可以自己去用其他软件写,都可以)。
为了方便,我现在就就在刚才的jni文件夹里写吧。
(a)首先右键jni文件夹,创建一个.h头文件。
随便取名,比如我取名myH
(b)然后将com_example_yucan_mytest_MainActivity.h文件的内容直接复制粘贴到myH.h文件去。
myH.h代码如下:
// // Created by yuCan on 2017/10/12. // #ifndef MYTEST_MYH_H #define MYTEST_MYH_H #endif //MYTEST_MYH_H /* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_example_yucan_mytest_MainActivity */ #ifndef _Included_com_example_yucan_mytest_MainActivity #define _Included_com_example_yucan_mytest_MainActivity #ifdef __cplusplus extern "C" { #endif /* * Class: com_example_yucan_mytest_MainActivity * Method: getStringFromNative * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_example_yucan_mytest_MainActivity_getStringFromNative (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
细心的肯定发现了,这个头文件已经声明了一个jni方法。那我们就去实现他。
(c)在新建一个c文件(记住是c文件,不是c++)
当然c++也可以,代码写起来有一丝丝不一样而已。我以c为例。
创建好后(自己随便命名,比如我叫myNewTest),敲一下刚才.h声明的方法的实现。代码如下:
// // Created by yuCan on 2017/10/12. // #include "myH.h" JNIEXPORT jstring JNICALL Java_com_example_yucan_mytest_MainActivity_getStringFromNative (JNIEnv * env, jobject jobj){ return (*env)->NewStringUTF(env, "hello JNI,I'm coming"); }
到这一步,我们基本就实现了c层的代码了,也就是刚才的native方法的具体实现。
12.在Android程序调用这个在c层实现的方法.我就写一个简单的调用方法。整个MainActivity代码如下:
package com.example.yucan.mytest; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.Toast; public class MainActivity extends AppCompatActivity { static { System.loadLibrary("myNativeLib"); } public native String getStringFromNative(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toast.makeText(this, getStringFromNative(), Toast.LENGTH_SHORT).show(); } }
现在整个工程基本就已经实现了
13.点菜单栏的Build->Make Project编译一下工程。
编译完成之后,在工程目录下app/build/intermediates/ndk/debug/lib目录下应该就成功生成了相应的.so文件,而且会生成对应平台的.so文件。
debug目录下还自动生成了Android.mk文件,相当于我们用build.gradle文件的配置替代了Android.mk文件的配置。如图:
现在就可以将项目运行到真机上去看效果了。
如果不知道mac 使用androidStudio到android真机调试应用点击这里。
可以看到真机toast了一下
"hello JNI,I'm coming"
效果图在真机上,就不截屏看了。
这就是整个AndroidStudio中配置了NDK/JNI开发环境的全部过程。