Andorid Studio NDK开发-使用NDK库

C语言是一个巨大的宝库,Android是一个以Linux为基础的开源操作系统,系统底层很多的实现都是基于C语言开发,比如图像处理,加密等。另一方面C语言的运行效率也比Java开发要高很多,因此为了高效率的运行有时候也会使用C语言开发一些功能。再Android上面使用C语言开发就需要使用NDK,在使用NDK开发的过程中会使用大量的库,系统自带的库,第三方库以及自己写的库等。
使用Android Studio调用NDK的库是非常简便,NDK内置了一些库方便开发者使用比如:Log库,还有一些比较常用的第三方库比如:OpenSSL。下面会分别介绍下,这两种库的使用。

调用系统库

Log是在Android开发过程用来调试程序必备的工具之一,他会把日志信息输入到Logcat中,如何在NDK中使用android.util.Log方便在Logcat中查看JNI程序的运行情况呢?
这就需要在NDK开发中导入Android系统的Log库。首先需要在gradle中引入Log库,引入的方式使用是在ldLibs中添加:

model{
 ....
 android {
        compileSdkVersion 23
        buildToolsVersion "23.0.2"
        ndk {
            moduleName "experiment"    
            ldLibs.addAll([ 'log']);
        }
   }
 }

直接gradle中的ldLIbs中加入log就可以了,如果还需要引入其他的系统库,只要在数组中直接增加即可。
下面来测试下log库的使用,先定义一个native的方法:

public static native void callLogFromJni();

在JNI中调用Log库:

//引入 log
#include <android/log.h>

JNIEXPORT void JNICALL
Java_com_jjz_NativeUtil_callLogFromJni(JNIEnv *env, jclass type) {

    __android_log_print(ANDROID_LOG_INFO,"jni-log","from jni log");

}

第一个参数,ANDROID_LOG_INFO是Log的级别他包含:

typedef enum android_LogPriority {
    ANDROID_LOG_UNKNOWN = 0,
    ANDROID_LOG_DEFAULT,    /* only for SetMinPriority() */
    ANDROID_LOG_VERBOSE,
    ANDROID_LOG_DEBUG,
    ANDROID_LOG_INFO,
    ANDROID_LOG_WARN,
    ANDROID_LOG_ERROR,
    ANDROID_LOG_FATAL,
    ANDROID_LOG_SILENT,     /* only for SetMinPriority(); must be last */
} android_LogPriority;

一般我们常用的是

  • ADNROID_LOG_VERBOSE->Log.v
  • ANDROID_LOG_DEBUG->Log.d
  • ANDROID_LOG_INFO-> Log.i
  • ANDROID_LOG_WARN->Log.w
  • ANDROID_LOG_ERROR->Log.e

第二个参数是tag,用来方便的对Log分类。
第三个参数是message,对应Log的具体信息。

一般会采用宏定义的方式,定义Log的输出的方法,方便调用,例如:

#define LOG_TAG "jni-log"
#define LOGW(...)  __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__)

这里定义了一个warning log的宏,在代码里面可以直接调用:

  LOGW("log from  define");

系统库的调用比较简单方便,使用第三方库就比较麻烦些,第三方库需要使用NDK重新编译才能在JNI中调用。

调用第三方类库

OpenSSL是最常用的加密库,下面就以OpenSSL为例,介绍下在gradle-experimental中如何引入第三方类库。
关于如何编译Android下的OpenSSL详见:Andorid Studio NDK 开发 - 编译 OpenSSL 类库
首先定义对于库的repositories,用来指定库的基本信息,包括库文件的路径,头文件的路径以及链接的方式等,详见如下代码:

model {
   repositories{
        libs(PrebuiltLibraries) {
            // Configure one pre-built lib: static
            openssl {
                // 头文件地址
                headers.srcDir "/usr/local/ssl/android-23/include"
                // 静态链接库的引用,
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile = file("libs/libcrypto.a")
                }
                //动态链接库的引用
//                binaries.withType(SharedLibraryBinary) {
//                    sharedLibraryFile = file("libs/libcrypto.so")
//                }
            }

        }

    }
  }

c语言的类库分为静态链接库(.a)动态链接库(.so),静态类库和动态类库在引入方式上是不一样的,分为对应:

  • StaticLibraryBinary->静态库
  • SharedLibraryBinary-> 动态链接库

这里引入的库为静态链接库,库的repositories名称为:openssl.
定义好了一个repositories,现在就需要调用了,在gradle可以指定库的依赖:

model{
 ......
 android{
  .....
   sources {
            main {
                jni {
                    dependencies{
                        //静态链接库
                        library 'openssl' linkage 'static'
                        //动态链接库
                        //  library 'openssl' linkage 'shared'
                    }
                    source {
                        srcDir "src/main/jni"
                    }
                }
                jniLibs{
                    source{
                        srcDir "libs/"
                    }
                }
              ....
            }
        }
 }
}

model.android.sources.main中指定库的依赖,依赖的是上面定义的openssl,linkage类型为static,如果是动态链接库则linkage就是shared
因为在编译OpenSSL设置了只支持arm结构的cpu,所以还需要指定abi为对应为arm架构,在model.android添加配置:

 ndk {
      moduleName "experiment"
      abiFilters.addAll(['armeabi', 'armeabi-v7a'])      
     }

定义了库的链接,就可以在代码中测试下OpenSSL的使用了。
首先定义一个native方法,该方法的目的是从OpenSSL中读取随机数:

public static native byte[] getRandom();

对应的JNI方法:

//引入OpenSSL的rand
#include <openssl/rand.h>
JNIEXPORT jbyteArray JNICALL
Java_com_jjz_NativeUtil_getRandom(JNIEnv *env, jclass type) {
    unsigned char rand_str[128];
    //使用OpenSSL的方法
    RAND_seed(rand_str, 32);
    jbyteArray bytes = (*env)->NewByteArray(env, 128);
    (*env)->SetByteArrayRegion(env, bytes, 0, 128, rand_str);
    return bytes;

}

RAND_seed是OpenSSL的方法,能够读取随机数。这段代码的意思就是读取一个128位的随机数,然后转换为Java的byte数组
在界面上面使用实现出读取的随机数内容:

tv2.setText(Base64.encodeToString(NativeUtil.getRandom(), Base64.DEFAULT));

运行之后可以在界面看到一段随机的字符串显示:

从openssl中读取随机数

可以看到使用gradle-experiment无论是调用系统库还是第三方库都比较简单。
以上源代码地址:https://github.com/jjz/android/tree/master/UseLibrary

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

推荐阅读更多精彩内容