Android NDK开发(一)  入门

开始之前

最近学习了一下NDK的开发, 就来分享一下.
对一个新鲜事物, 我们先解决的无非就是三件事情: 是什么?为什么?怎么做?.

NDK简介

(英语:native development kit,简称NDK)是一种基于原生程序接口的软件开发工具。通过此工具开发的程序直接以本地语言运行,而非虚拟机。因此只有java等基于虚拟机运行的语言的程序才会有原生开发工具包。[维基百科]

  1. NDK是一系列工具的集合

NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。这些工具对开发者的帮助是巨大的.

  1. NDK集成了交叉编译器,并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪些文件需要编译”、“编译特性要求”等),就可以创建出so。

NDK可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作。

那我们为什么要使用呢?

  1. 代码的保护。由于apk的java层代码很容易被反编译,而C/C++库反汇难度较大。
  2. 可以方便地使用现存的开源库。大部分现存的开源库都是用C/C++代码编写的。
  3. 提高程序的执行效率。将要求高性能的应用逻辑使用C开发,从而提高应用程序的执行效率。
  4. 便于移植。用C/C++写得库可以方便在其他的嵌入式平台上再次使用。

上述文字致谢Devin Zhang提供理论支持

是什么和为什么我就先介绍到这儿, 接下来就具体看看如何进行NDK的开发

开发前准备

开发环境

请大家务必升级到AS 2.2以上版本, 因为这个版本升级了很多内容, 详情请见 Android Studio 2.2 正式稳定版发布

  • Android Studio 2.2.2
  • JDK1.7
  • API 24
  • Gradle 2.2.2

NDK和CMake 的下载和安装

大家可以直接打开SDK进行下载和安装

SDK

由于NDK的工具包较大, 大家也可以选择从网站中下载: http://wear.techbrood.com/tools/sdk/ndk/, 选择自己对应的版本使用迅雷等工具下载即可, 不过通过这种方法一定要修改local.properties文件, 在里面添加:

//后面改成自己下载后解压的路径名
ndk.dir=C\:\\Users\\Lulu\\AppData\\Local\\Android\\android-ndk-r13

关于CMake

  1. CMakeList.txt 是脚本文件, 需要指定包含哪些源代码;
  2. 可以写一些条件语句, 实现不同的代码包含
  3. 内部说明:
    add_library 表示编译一个代码库, 内部包含了代码库的名称, 以及源代码有哪些

NDK两种开发模式

  1. ndk-build 形式; Android Studio 2.2之前的模式
  2. CMake 形式: CLion C/C++编辑器; AS2.2之后整合了CLion代码, AS就支持了CMake形式的NDK开发

开始开发

接下来通过几个案例来演示NDK的开发流程

创建工程

  1. 新建工程, 选中Include C++ Support


    Include C++ Support
  2. 一路Next之后, 在最后Finish页面尽量选中图示两项, 这样会给我们包裹一些特定的示例代码, 帮助我们理解和使用


    NDK
  3. 点击Finish, 如果出现图示错误的肯定没有好好看上面的 开发前准备


    ERROR

案例一 实现在C语言中隐藏AppKey等信息

step1: 为了使代码整洁, 咱们新建一个类 NativeHelper, 专门用于访问C语言代码的帮助类 并添加获取Appkey的方法


public class NativeHelper {
    static {
        // 加载C代码库, 库的名称, 必须是CMakeLists.txt中指定的名称
        System.loadLibrary("native-lib");
    }

    //获取C中隐藏的AppKey
    public static native String getAppKey();
}

Note: 一定要添加上面的静态代码块的内容, 否则无法加载C代码库
此时的getAppKey()方法标红, 不用管它, 继续....

step2: 在cpp目录下右击创建C/C++ Source, 选择Type, 并勾选 Create an associated hader, 为保持对应, 名字命名为: com_lulu_ndkdemo_NativeHelper, 此时会出现, 在cpp目录下会出现两个文件, 如图:

cpp

step3: 在CMakeLists.txt中的add_library中添加依关系, 点击同步

src/main/cpp/com_lulu_ndkdemo_NativeHelper.c
add_library

Note:

C代码库生成的名称规则

  1. 如果栈顶代码库名称为 "nh" 那么生成的文件必定是libnh.so
    命名规则: lib库名.so
  2. System.loadLibrary(库名); //此处不能包含前面的lib和后面的.so

step4: 在com_lulu_ndkdemo_NativeHelper.c文件中添加c语言代码

#include <jni.h>
JNIEXPORT jstring JNICALL
                  Java_com_lulu_ndkdemo_NativeHelper_getAppKey(JNIEnv *env, jclass type) {

    //测试代码, 没有任何意义
    char* app_key = "5465465416948";

    //生成 Java 中的字符串对象
    //指针的指针
    // env <=> JNINativeInterface** C语言
    return (*env)->NewStringUTF(env, app_key);
}

step5: 在MainActivity中获取AppKey, 查看结果 -> 成功


    String appKey = NativeHelper.getAppKey();
    Log.d(TAG, "onCreate: appKey => " + appKey);

Note: Java 调用C/C++代码

  1. 任何一个类的方法, 如果声明了native修饰符, 那么就可以认为是一个C代码;
  1. 可以用对象, 类直接调用
  2. 创建C/C++文件; 如果一个类中有一个native的方法, 那么对应的C方法: Java_包名类名方法名(JNIEnv *env, ...);
  3. 当Java类中包含了native的方法, 那么这个类必须写一个静态初初始化块: System.loadLibrary("库名")

案例二 实现在C语言中打印log

接下来, 只简单介绍核心代码, 不再赘述

step1: 在com_lulu_ndkdemo_NativeHelper.c中添加:


JNIEXPORT void JNICALL
Java_com_lulu_ndkdemo_NativeHelper_printLog(JNIEnv *env, jclass type, jstring str_) {
    const char *str = (*env)->GetStringUTFChars(env, str_, 0);
    //TODO: 显示Android 的日志
    // 调用Android的代码
    // 代码需要调用系统的日志库, 这个库已经在 CMakeList.txt添加了e,因此可以直接调用
    const char *tag = "NativeHelper";
    //jstring -> char*
    jboolean b = JNI_FALSE;
    const char* txt = (*env)->GetStringUTFChars(env, str_, b);
    //打印log日志
    __android_log_write(ANDROID_LOG_DEBUG, tag, txt);
    //释放string
    (*env)->ReleaseStringUTFChars(env, str_, str);
}

step2: NativeHelper中添加

//在C中打印log
public static native void printLog(String str);

step3: MainActivity中调用


//打印C语言中的Log
NativeHelper.printLog("测试Log");

完整代码

Demo已上传到github上, 欢迎大家Clone

小结

至此, 咱们应该大致了解了一下NDK开发的简单流程, 鄙人菜鸟, 希望抛砖引玉, "引"出更好的文章

本文还有下篇, 将再写一些关于NDK开发的案例Demo, 希望大家喜欢和关注

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

推荐阅读更多精彩内容