Android对C++进行了兼容,可以通过jni层调用C++的代码,学生时代有几年C++开发经历,对其相关知识比较熟悉。正好最近在修改项目的native签名代码,特意抽空记录下开发过程。
准备工作
NDK目录配置:
1、下载完成之后解压压缩包
2、在Project根目录下的local.properties
中增加一行配置ndk.dir=${ndk_path}
开发步骤
1、新建jni文件夹
AS的默认jni文件夹是在main
下面,与java目录同级。
![KWSSLLXLA72}1OQQEOPARJ.jpg](https://img.haomeiwen.com/i1928639/12651347c23dcd56.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 也可以指定jni目录,设置方法是在目标module的
build.gradle中增加代码
jni.srcDirs = ["${目标文件夹路径}"]`,如下所示:
2、配置build.gradle
在defaultConfig
节点下面添加ndk
配置代码
ndk { moduleName "${Your So Lib Name}" }
build.gradle如下所示:
![Q2}LE}X]%}E@RLAMW}SQTPK.jpg](https://img.haomeiwen.com/i1928639/4e0ccd887c82ffb4.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
NDK还可以配置如下选项
stl "stlport_shared" //Use shared stlport library
cFlags "-DANDROID_NDK -D_DEBUG DNULL=0" //预定义宏
ldLibs "log" //链接库列表
abiFilters "armeabi", "armeabi-v7a", "x86" //打包平台
}```
**常见问题:**
* `Error:(2, 18) string: No such file or directory`
*解决方法:*添加` stl "stlport_shared"`到ndk节点下。
*原因:* C++代码使用了这个库中的代码,所以要把库添加到编译选项。
* `Error: NDK integration is deprecated in the current plugin`
*解决方法:*在project根目录下的`gradle.properties`中添加配置`android.useDeprecatedNdk=true`。
* `no rule to make target....`
*解决方法:* 新建一个空的empty.c文件
*原因:* JNI 的bug
3、声明并生成native方法
前两步只是配置环境,配置好开发环境后就可以进行C++代码编写,但为了让java代码能够正确识别和调用C++的代码,其对外函数的声明需要进行一些特殊的处理:
* 在java类中定义一个native方法,native方法的声明只是在普通的java静态方法声明加上`native`关键字。如:
![6NX6`5]BLVIQ)1}D0]TIN9S.jpg](https://img.haomeiwen.com/i1928639/03039e476b3cea9b.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
* 编译project,生成对应类的class文件
* 找到定义native方法的class文件,使用javah命令生成对应的头文件。以NativeMethod.class为例,在终端输入:` cd app/build/intermediates/classes/debug/
`,然后输入`javah -jni ling.jnitest.NativeMethods
`,其中`ling.jnitest`是`NativeMethods`类的包名
![A8480C58-BC21-4581-8E05-801732288C97.png](https://img.haomeiwen.com/i1928639/6a356bd89b87bc09.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)如果没有报错,在debug目录下会生成一个头文件
![D3239FA4-C3AB-4D09-AC3E-A95D4876BD69.png](https://img.haomeiwen.com/i1928639/de4faa58e7e31f5e.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
* 复制头文件至jni目录,并根据头文件新建一个同名的cpp文件,在该cpp文件内就可以编写C代码。最终目录结构如图所示
![1B092C07-7EDE-4FDE-B583-FE043EF2D509.png](https://img.haomeiwen.com/i1928639/7dac463ed71fc4a4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
输出一条日志到logcat
![730624DE-074C-461F-8AF5-4B8D5189933C.png](https://img.haomeiwen.com/i1928639/b58221fe7606efe4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**常见问题:**
* `错误: 找不到类android.content.Context。`
*解决方法:* `javah -classpath ./:${android.jar path} -jni ling.jnitest.NativeMethods`。
*原因:* 使用了一些非jdk预定类,导致无法找到引用的类,所以在打包的时候需添加class路径,如引用了android sdk里的类则需添加android.jar的路径,如存在多个路径则使用`:`连接。
![64D49FD8-EF86-4AB6-A66C-8FD3B9A67015.png](https://img.haomeiwen.com/i1928639/e52d0f60fce47fcf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
万里长征走完第一步,上面对Android Studio开发jni的开发环境、基本配置以及常见问题进行了详细说明,后续将对C++与java层的一些相互调用,对系统API的调用进行讲解。
[Demo下载地址](https://github.com/lintran-cn/JNITest)
### 参考
[Gradle 2 用户指南](http://wiki.jikexueyuan.com/project/gradle-2-user-guide/)
[JNI/NDK 开发指南](http://wiki.jikexueyuan.com/project/jni-ndk-developer-guide/)
网友评论