资讯专栏INFORMATION COLUMN

Andorid Studio NDK开发-使用库

Freeman / 813人阅读

摘要:总而言之,会在开发的过程中会使用大量的库,系统自带的库,第三方库等。在中使用语言的库是非常便利的。这里引入的库为静态链接库,名称为指定库依赖动态链接库这里在中指定库的依赖为上面定义的类型为如果是动态链接库就是。

C语言是一个巨大的宝库,系统底层的很多的实现都是基于C语言实现的,比如图像处理,加密等。
C语言的运行效率也是很高的,因此为了效率有时候也会引入第三方的C语言库。
总而言之,会在NDK开发的过程中会使用大量的库,系统自带的库,第三方库等。
gradle-experimental中使用C语言的库是非常便利的。

调用系统库

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

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

直接在ldLIbs中加入log就可以,如果需要引入其他的系统库,只要在数组中直接增加即可。
再定义一个native的方法:

public static native void callLogFromJni();

在Jni中调用Log库的方法:

//引入 log
#include 

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,ANDROID_LOG_DEBUG,ANDROID_LOG_INFO,ANDROID_LOG_WARN,ANDROID_LOG_ERROR分别对应java中的Log.v,Log.d,Log.i,Log.w,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");
使用第三方类库

OpenSSL是最常用的加密库之一,下面以OpenSSL为例,介绍下在gradle-experimental中如何引入第三方类库。关于如何编译Android下的OpenSSL详见:编译Android的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),静态类库和动态类库的引入方式是不一样的,分为对应:StaticLibraryBinarySharedLibraryBinary。这里引入的库为静态链接库,名称为:openssl.

指定库依赖:

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

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

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

首先定义一个native方法,需要从OpenSSL中读取随机数:

public static native byte[] getRandom();

生成对应的JNI方法:

//引入OpenSSL的rand
#include 
JNIEXPORT jbyteArray JNICALL
Java_com_jjz_NativeUtil_getRandom(JNIEnv *env, jclass type) {
    unsigned char rand_str[128];
    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));

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

源代码地址:https://github.com/jjz/android/tree/master/experimental

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/12904.html

相关文章

  • Andorid Studio NDK开发-使用NDK

    摘要:首先定义一个方法,该方法的目的是从中读取随机数对应的方法引入的使用的方法是的方法,能够读取随机数。这段代码的意思就是读取一个位的随机数,然后转换为的数组。 C语言是一个巨大的宝库,Android是一个以Linux为基础的开源操作系统,系统底层很多的实现都是基于C语言开发,比如图像处理,加密等。另一方面C语言的运行效率也比Java开发要高很多,因此为了高效率的运行有时候也会使用C语言开发...

    Leck1e 评论0 收藏0
  • Andorid Studio NDK开发-编译OpenSSL类

    摘要:在上开发对于安全的需求越来越高,虽然出现过几次漏洞,但它仍然是在安全方面的使用最多的加密库之一。这篇文章主要写的是如何编译的类库。 OpenSSL是一个强大的开源安全套接字层密码库,它包含了主要的密码学算法,常用的密钥和证书封装管理以及SSL协议,并提供丰富的应用程序供测试或其他目的使用。在Android上开发对于安全的需求越来越高,虽然OpenSSL出现过几次漏洞,但它仍然是在安全方...

    yiliang 评论0 收藏0
  • Android 增加JNI

    Android:JNI 与 NDK到底是什么?(含实例教学) 前言 在android开发中,使用NDK开发的需求正逐渐增大; 很多人搞不懂JNI与NDK到底是怎么回事? 今天我们先介绍JNI与NDK之间的区别,手把手进行NDK的使用教学,希望你们会喜欢; 目录: 1. JNI介绍 1.1 简介 定义:Java Native Interface,即Java接口 作用:使得Java 与 本地其...

    springDevBird 评论0 收藏0
  • Andorid Studio NDK开发-Hello World

    摘要:介绍了在中配置的开发环境开发环境配置,开发环境配置完成之后,就要写一下著名的程序了。尤其是但是并不妨碍你使用其他语言,只要调用约定支持就可以了。是指定所在的目录,项目成功之后,会在目录里生成文件。是包名加上类名。 介绍了在Android Studio中配置NDK的开发环境:Android Studio NDK开发-环境配置,NDK开发环境配置完成之后,就要写一下著名的Hello Wor...

    melody_lql 评论0 收藏0
  • Andorid Studio NDK开发-Hello World

    摘要:介绍了在中配置的开发环境开发环境配置,开发环境配置完成之后,就要写一下著名的程序了。尤其是但是并不妨碍你使用其他语言,只要调用约定支持就可以了。是指定所在的目录,项目成功之后,会在目录里生成文件。是包名加上类名。 介绍了在Android Studio中配置NDK的开发环境:Android Studio NDK开发-环境配置,NDK开发环境配置完成之后,就要写一下著名的Hello Wor...

    niceforbear 评论0 收藏0

发表评论

0条评论

Freeman

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<