Android NDK开发之旅(2):一篇文章搞定Android Studio中使用CMake进行NDK/JNI开发

Android NDK开发之旅(2):一篇文章搞定android Studio中使用CMake进行NDK/JNI开发

 (码字不易,转载请声明出处:http://blog.csdn.NET/andrexpert/article/details/72904462)

前  言

      上篇文章我们详细介绍了Eclipse中NDK/JNI开发的相关原理,由于谷歌停止了对Eclipse的更新,未来AndroidStudio必然会完全替代Eclipse。基于此,本文将详细介绍下AndroidStudio中使用CMake进行NDK/JNI开发,相比于使用ndk-build编译Android.mk和配置AS中的build.gradle编译的方式,CMake方式显得更加的简洁、高效。

1. 安装CMake、LLDB

     CMake是一款比make更强大的编译自动配置工具,它可以根据不同平台、不同的编译器,并通过CMakeLists.txt文件中简单的语句来描述所有平台的编译过程,生成相应的Makefile文件或project文件。CMake被引入于AndroidStudio2.2,其目的是替代原有的JNI/DNK开发方法,使AS在进行JNI/NDK时更加的方便、高效。CMake的优势如下:

(1)   允许直接在C/C++代码中加入断点,调试;

(2)   在Java层中使用“ctrl+左键”快捷键能够直接进入本地方法对应的C/C++代码中;

(3)   在C/C++中使用“ctrl+鼠标点击”快捷键能够直接进入头文件或库;

(4)   自动生成函数原型头文件,无需配置android.useDeprecatedNdk=true属性;

       LLDB是一个高效的C/C++调试器,它提供了丰富的流程控制和数据检测,有效地帮助我们调试程序。AndroidStudio通过引入LLDB调试器,能够实现对NDK本地代码的调试。

2. 配置NDK路径


3. 创建支持C/C++开发的Android工程

(1)   创建新的Android工程,勾选”IncludeC++ Support”选项;


(2)  Android工程结构剖析


       红框中的文件是创建工程时自动生成的,其中:

       (1) .externalNativeBuild文件夹:用于存放cmake编译好的文件,包括支持的各种硬件等信息,有点类似于build.gradle文件明确Gradle如何编译APP;

       (2) cpp文件夹:存放C/C++代码文件,native-lib.cpp文件默认生成的;

       (3) CMakeLists.txt:cmake脚本配置文件,cmake会根据该脚本文件中的指令去编译相关的C/C++源文件,并将编译后产物生成共享库或静态块,然后Gradle将其打包到APK中。CMakeLists.txt文件解析如下:

  1. # 指定cmke版本  
  2. cmake_minimum_required(VERSION3.4.1)  
  3. # add_library()命令用于向CMake添加依赖源文件或库  
  4. # 指令需传入三个参数(函数库名称、库类型、依赖源文件相对路径)  
  5. add_library(  # 生成函数库的名称,即libnative-lib.so或libnative-lib.a(lib和.so/.a默认缺省)  
  6.              native-lib  
  7.              # 生成库类型:动态库为SHARED,静态库为STATIC  
  8.              SHARED  
  9.              # 依赖的c/cpp文件(相对路径)  
  10.              src/main/cpp/native-lib.cpp )  
  11. # find_library()命令用于定位NDK中的库  
  12. # 需传入两个参数(path变量、ndk库名称)  
  13. find_library(  # 设置path变量的名称,这里为NDK中的日志库  
  14.               log-lib  
  15.                             #指定cmake查询库的名称  
  16.                             #即在ndk开发包中查询liblog.so函数库,将其路径赋值给log-lib  
  17.               log )  
  18. #target_link_libraries()命令用于指定要关联到的原生库的库  
  19. target_link_libraries(# 指定目标库,与上面指定的函数库名一致  
  20.                   native-lib  
  21.                   # 链接的库,根据log-lib变量对应liblog.so函数库  
  22.                   ${log-lib} )  

4. 运行效果

      通过查看native-lib.cpp方法,stringFromJNI目的是向Java层返回一个字符串。如果要在native-lib.cpp文件中添加新的方法,必须添加在extern"C" { } 中,或者在每个方法前加extern"C", 否则会报找不到方法。如果源文件为C,则须将extern“C”部分去掉,因为extern "C"的作用就是告诉编译器以C方式编译。

  1. #include<jni.h>  
  2. #include<string>  
  3. extern"C"  
  4. jstring Java_com_jiangdg_hellojni_MainActivity_stringFromJNI(  
  5.         JNIEnv *env,  
  6.         jobject /* this */) {  
  7.     std::string hello = "Hello fromC++";  
  8.     return env->NewStringUTF(hello.c_str());  
  9. }  


如果需要查看so文件是否生成成功,可以使用Analyze APK 工具来实现。“Build->Analyze APK”,选择app/build/outputs/apk/app-debug.apk查看so文件生成情况:


5. 创建新的C文件

(1)  创建.c或.cpp源文件


(2) 修改CmakeLists.txt



       此时,你会发现在main/cpp目录下并没有刚刚新建的JniLearning.c、JniLearning.h文件,我们需要对Android功能进行同步下(Syncnow)。

(3) 添加新的native方法


(4)生成native方法对应的函数原型

       相比于Eclipse中使用javah命令生成头文件,AndroidStudio就太方便了。我们只需要选中定义的native本地方法,使用快捷键“Alt+Enter”即可自动生成相对应的函数原型。


* 非静态属性

       返回值类型Java_包名_类名_方法名(JNIEnv*,jobject,参数1类型,参数2类型,…)

* 静态属性

       返回值类型Java_包名_类名_方法名(JNIEnv*,jclass,参数1类型,参数2类型,…)


调用JNIUtils.calculate(1,100)运行的结果为:


注:关于JNI数据类型和基本使用,可参看我 这篇文章

6. 本地代码调试

   众所周知,当使用Eclipse进行NDK/JNI开发时,基本无法对C/C++本地代码调试,而AndroidStudio却非常容易。AS通过借助LLDB调试工具,可以非常方便地对C/C++本地代码进行调试。LLDB调试的步骤基本与调试Java层代码一致,只是断点标志在C/C++函数中。


     从上面的图中可以看到除了Variables的Tab页以外,还有一个Tab页就是LLDB,点击进入可以看到(lldb)的命令行,在命令行里面可以输入LLDB的命令,LLDB命令有很多强大的能力,比如,打印,寻址,调用堆栈等,通过这些命令可以有效的帮助调试NDK程序。

GitHub项目地址:https://github.com/jiangdongguo/JniLearning

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值