Android Studio上进行NDK编程之Hello world

Android Studio很早之前就支持NDK编程了,但是资料比较少,照着网上的写,一大堆的坑,各种错误一堆。

经过不断的努力,弄出了第一个能正常奔跑的NDK示例——Hello world。现整理如下:

我的配置:

Android Studio 3.0.0

Gradle 4.1

NDK 14

OpenJDK 8

总结一下流程:

1、下载与安装NDK(最好连CMake,LLDB也下了)

2、配置NDK环境变量(如果需要到处运行)

3、为项目配置NDK

4、编写java以及需要相关的C/C++代码

5、编译C/C++代码生成.so库文件

6、引入库文件,编译/调试/运行APP。

-------------------

1、第一件要事就是下载NDK。

可以直接在Android Studio下载,也可以单独去下载。Android Studio下载的NDK默认放置于“android-sdk/ndk-bundle”路径下。

NDK版本集合:https://developer.android.google.cn/ndk/downloads/revision_history.html

NDK的官方示例:https://github.com/googlesamples/android-ndk(NDK10自带,13、14没看见)

在Android Studio下载更方便,Android Studio下载的是最新版——NDK14。顺便连CMake和LLDB也下载了。

CMake: C/C++的外部构建工具,可以提示代码什么的。

LLDB: 调试本地代码的工具。

如图:

2、配置NDK环境变量。

如果想要想java命令一样在CMD上,各种路径下到处跑ndk的命令,需要设置。最好设置。

类似java,将NDK安装目录丢到Path中即可。如:

新建变量

变量名:NDK_HOME

变量值:“D:\Programming\Android\android-sdk\ndk-bundle”

3、为项目配置NDK

在开的项目的Android Studio中依次打开“File——Project Structure”,设置NDK路径并确定:

或者直接在项目的“local.properties”文件中添加NDK路径:

## This file is automatically generated by Android Studio.# Do not modify this file -- YOUR CHANGES WILL BE ERASED!## This file must *NOT* be checked into Version Control Systems,# as it contains information specific to your local configuration.## Location of the SDK. This is only used by Gradle.# For customization when using a Version Control System, please read the# header note.#Wed Mar 22 18:21:45 CST 2017ndk.dir=D\:\\Programming\\Android\\android-sdk\\ndk-bundlesdk.dir=D\:\\Programming\\Android\\android-sdk

配置完,我感觉最好重启一下。。。我擦,未知原因,我的头一次使用ndk-build命令时提示不是内部或外部命令,也不是可运行的程序或批处理文件。

4、编写java以及相关的C/C++代码。

(1)新建JniLoader类。如:

package yue.excample.hello;/** * Created by Yue on 2017/3/19. */public class JniLoader {static {        System.loadLibrary("firstndk");    }public native StringgetHelloString();}

(2)编写C/C++文件。

在“项目/app/src/main/jni”路径下(没有jni文件夹就创建)新建C++资源文件,名字随便写,尽量规范易懂。我取名为JniLoaderndk.cpp,内容如下:

注意事项:如果编写的是C++代码,而不是C,应当注意使用extern “C”{};上述代码注释部分有说明。

比较固定的写法,其中Java层的native方法getHelloString()对应的名称为Java_yue_simplendk_JniLoader_getHelloString,是一种全称的写法,Java代表java方法,接着是包名+方法名。包名的分隔符“.”号用“_”代替。两个参数貌似乎是C/C++的指针和java对象。

如果需要编写C/C++的头文件,可以使用javah命令来快速生成。首先要找到.class文件所在,没有需要先Make Project 一下。

Android Studio和eclipse目录不同,Android Studio在“项目/app/build/intermediates/classes/debug”下。

使用terminal进入该目录下,执行“javah -jni yue.simplendk.JniLoader”命令。

JniLoader类要写全名,即带包名的方式,不能直接为“javah -jni JniLoader”,会提示找不到类文件。成功则在debug目录下直接生成了规范的头文件了,丢过去用即可。

(3)Activity中使用:

5、编译C/C++文件为.so库。

编写Android.mk和Application.mk文件。

Android.mk指定.so文件名称:

Application.mk指定生成不同平台的.so库:

三种常用平台,不写则全部生成(armeabi arm64-v8a armeabi-v7a mips mips64 x86 x86_64)。架构不同有的不兼容。不写则全部生成。

在Terminal中使用cd 命令跳转到“jni”目录下,使用“ndk-build”命令编译C/C++文件。

生成结果如图:

题外话:

快速获取指定路径:Android Studio中选中文件(夹),Ctrl+Shift+C复制路径,相当于鼠标右击——Copy Path。然后cd+粘贴路径即可。

另一个方法就直接跳转过去了:拖文件(夹)到Tirminal中。但是这么做的弊端是,清空了缓存的命令,也就是历史命令不能调出来了(windows的CMD中不会,只会把路径字符串放过来)。

6、引入.so文件,调试、运行

首先,马上要注意ndk-build命令生成的.so文件默认在src/main/libs目录下,此目录非Android Studio 默认的.so库目录,直接调试/运行会报错。要将.so文件全部移动到src/main/jniLibs中去。默认目录,可以修改。

打开app目录下的build.gralde,在android 节点下添加sourceSets部分,设置jni库的资源路径:

之后尝试调试/运行了,结构报错:

说的是项目包含C++文件,但是却没有使用能够支持的构建系统。考虑使用CMake,或者稳定的ndk集成插件进行构建。

看来,新版的有所问题。使用Cmake,额,这又是什么东东...好吧先不用它。。查资料,是这么解决的:在项目下的gradle.properties中增加一句:

android.useDeprecatedNdk=true

使用过时的NDK。

再次编译运行:


刚开始开这个错误日志有点懵了,但是我们仔细看一下会发现android.useDeprecatedNdk不在被支持了,但是在日志后面给了我们一个解决办法

To continue using the deprecated NDK compile for another 60 days, set android.deprecatedNdkCompileLease=1517304753794 in gradle.properties

大概意思是想要继续使用已弃用的NDK编译60天,在gradle.properties文件里把android.useDeprecatedNdk去掉换成android.deprecatedNdkCompileLease=1517304753794就行了,我猜有肯能每个人错误日志里得到android.deprecatedNdkCompileLease=1517304753794不一定一样,所以尽量使用自己错日志里的进行运行。

再次运行:


这是ndk 版本更新到16后出现的问题,修改如下:

1、删除application.mk;

2、app的build.gradle文件中修改如下:

android {

    compileSdkVersion26

    defaultConfig {

        //省略

        ndk{

            moduleName "NDK_01" //必须加上,否则在AS中就报错。

            ldLibs"log","z","m" //可以不写,在C代码打印Log

            abiFilters'armeabi-v7a','arm64-v8a' // 'x86', 'x86_64' may be added

        }

    }

    sourceSets{

        main{

                jniLibs.srcDirs = ['src/main/libs']//Android Studio 默认的.so库目录src/main/jniLibs

        }

    }

    task ndkClean(type: Delete) {

        delete fileTree('.externalNativeBuild') {

                exclude defaultConfig.ndk.abiFilters.collect {'**/' + it }

         }

      }

      tasks.findByPath(':clean').dependsOn ndkClean

}

删除.so文件,再次ndk-build,并运行项目:


错误说的是文件重复,在app目录查看是否jniLibs目录下是否也生成了对应的so文件,由于在build.gradle已经指定so

文件目录为jniLibs.srcDirs = ['src/main/libs',所以将jniLibs目录下的so文件删除即可。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容