在老早之前就想要去接触了解这一块的知识了,奈何在工做中一直都没有机会去接触,就迟迟没有去学习这一块的知识。到如今终于开始去学习了,简单的搜索了一下,都没有太明确的博客去学习,都是很零碎的,并且在最新的版本中也有问题,到最后只能去看官方的文档,固然这才正确的选择,其实一开始就该去看的。废话很少说,这一个系列由于我才开始学习,不知道会有多长,可是会将经常使用的东西所有总结学习完。java
首先来学习一下官方的配置。android
这一条没啥说的,就是下载一些工具方便开发,固然是在Android Studio中。c++
对于ndk的开发,须要下载:bash
这三个均可以直接在SDK Manager中去下载(固然也能够手动下载配置好)。目前我使用的版本对应分别是:ide
NDK : 17.1.4828580
cmake : 3.6.4111459
LLDB : 3.1.4508709
复制代码
这一点分为两种状况:函数
第一种状况没啥说的,就是在新建项目时,选中第一个界面的include C++ support
这个选择框,以后一直默认next(最后finish)便可。工具
重点是第二种状况,由于大多数在在项目一开始时可能没有想着要使用ndk开发功能,后来须要了,那么就去配置便可。学习
在已有项目的main目录下建立cpp文件夹gradle
在cpp文件夹下建立一个c文件,右键->new->c/c++ Source File,例如取名叫作Hello,后缀名为.c,不建立.h文件,点击ok。ui
注:内部暂时能够不用写代码。
在当前module中建立一个CMakeLists.txt文件,右键->new->File,取名叫作CMakeLists.txt
,点击ok。加上如下代码:
cmake_minimum_required(VERSION 3.4.1)
add_library( # Specifies the name of the library.
Hello
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/Hello.c )
复制代码
add_library方法:
选择Android视图,在须要构建的module下,右键->Link C++ Project with Gradle->选择CMakeLists.txt的路径,就是上文中建立的CMakeLists.txt,点击ok。
构建完成,能够看到在当前module下的build.gradle文件中多了如下这段话:
externalNativeBuild {
cmake {
path 'CMakeLists.txt'
}
}
复制代码
这时候再在当前的build.gradle中,android模块,defaultConfig下,添加如下代码:
ndk{
moduleName 'Hello'
}
复制代码
这里的moduleName就是要与CMakeLists.txt中定义的libraryName一致,这里加入叫Hello吧。
到此基本配置就算是完成了。下面就开始写代码,先从java调用c开始。
到这一步,终于回到熟悉的Java代码,咱们在对应的包名中建立一个类,例如取名叫作Hello,加入一个简单的本地方法,只比普通抽象方法多了一个native关键字,以下:
public native String stringFromC();
复制代码
这时候这个方法是找不到的,还须要在以前的Hello.c文件中写上对应的方法,以下:
#include<jni.h>
jstring Java_net_arvin_androidstudy_jni_Hello_stringFromC(JNIEnv *env, jobject instance) {
return (*env)->NewStringUTF(env, "I am from c!");
}
复制代码
代码不长,以此来解释,首先必需要引入的是jni.h
,下边的JNIEnv和jstring,jobject等都是在这里边去定义的。
函数的申明部分,jstring
表示在java中定义的String,这个位置也就是返回值,而后Java_net_arvin_androidstudy_jni_Hello_stringFromC
这一部分看起来很长其实就是三个部分:Java_类的彻底限定名_方法名,只是彻底限定名中的点改成了下划线,后边的两个参数env和instance,env是一个环境,用它能够操做Java类,建立字符串之类的;instance就是当前调用这个代码的类的实例,这里就是Hello类的实例。
最后就是函数的实现内容,这里是返回一个字符串而后,看一看env这个变量的类型,JNIEnv的定义能够看到是一个typedef const struct JNINativeInterface* JNIEnv;
。自己就是指针,而后在方法中的env又是指针,至关于二级指针,因此调用的时候使用的就是(*env)->函数。
回到Hello类中,在类中加一段静态初始化的代码:
static {
System.loadLibrary("Hello");
}
复制代码
其中Hello是上文中在build.gradle中ndk下配置的moduleName。
到这里就能够在其余地方建立Hello类的实例,而后调用stringFromC的方法了。
例如:
Hello jni = new Hello();
System.out.println(jni.stringFromC());
复制代码
就会在run tab下看到I am from c!
这样一句话的输出。
至此Android JNI开发系列之配置就告一段落了。固然后边确定还有进一步的配置学习,例如须要引入多个c文件,须要引用其余c++库等,确定也是须要配置的,那些都会在以后的文章中讲到。
借鉴官方教程