Android程序猿Android知识程序员

android Ndk JNI开发 入门

2017-08-08  本文已影响138人  MiBoy

相信很多人对于NDK 开发都是懵逼的,比如都知道把加密的逻辑以及密钥放在so文件中,但是你知道怎么生成so文件吗?你知道开发jni吗?你熟悉jni语法吗?怎么配置android studio 中的NDK环境?此时你一定很懵逼,我也是从这过来的,我不能帮助你开发Ndk,但是我可以让你不懵逼。
Eclipse ndk开发这么古老的方法我就不说了,其实我也不会。有需要的可以去百度,这里讲一下android studio。顺便说一下百度上有很多很坑的文章,自己没动手做过不知道,文章晦涩难懂,而且有些地方一言蔽之,搞不清方向,必须仔细过滤,才能发现。所以我总结了这篇文章

一、NDK相关角色概述

1、NDK和SO
image.png

NDK 全称 Native Development Kit,是Google在Android开发中提供的一套用于快速创建native工程的一个工具。从上图这个Android系统框架来看,我们上层是通过JNI方式来调用NDK层的,使用这个工具可以很方便的编写和调试JNI的代码。因为C语言不跨平台,在Windows系统下使用NDK编译在Linux下能执行的函数库——SO文件,全称Shared Objects,其实质就是一堆c、c++的头文件和实现文件打包成一个库。目前Android系统目前支持以下七种不同的CPU架构,每一种对应着各自的应用程序二进制接口ABI:(Application Binary Interface)定义了二进制文件(尤其是.so文件)如何运行在相应的系统平台上,从使用的指令集,内存对齐到可用的系统函数库。

二、JNI

image.png

JNI 全称Java Native Inteface,即Java本地接口,是Java中定义的一种用于连接Java和C/C++接口的一种实现方式。Java语言装载到虚拟机中,不能和硬件交互,不能驱动开发。JNI扩展了Java虚拟机的能力,驱动开发、无线热点共享,底层语言(C、C++)效率高,数学运算、实时渲染的游戏,音视频处理等等,简而言之,就是Java代码调用c、c++代码,JNI模式一共涉及到三个角色:C/C++ 代码本地方法接口类Java层中具体业务类

1、JNI简要流程
image.png
2、JNI的变量类型与Java类型对比表
Java中变量的类型 JNI对应的类型名 C/C++变量类型
boolean jboolean unsigned char
float jfloat float
double jdouble double
byte jbyte signed char
char jchar unsigned short
short jshort short
int jint/jsize int
long jlong long long
Object jobject void *
String jstring void *
3、JNI的基本语法
JNIEXPORT jstring JNICALL
Java_xiao_mi_jni_JNITest_getJniStr(JNIEnv *env, jclass type) {
    return (*env)->NewStringUTF(env, "Hello from JNI!");
}

jstring--------->返回值类型
xiao_mi_jni --->包名
JNITest--------->类名
getJniStr------->方法名

static {
        System.loadLibrary("jnitest");//加载so文件,不要带上前缀lib和后缀.so
    }
ps:以前不明白上边注释的这句话,只有自己去看才能明白为什么,所以我用AS打开了apk,原来打包出来的都是前缀加lib后缀加.so的文件格式。
lib.so
4、Gradle

Gradle 是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置。以往Android NDK开发需要在Eclipse或源码环境下,建立并配置Android.mk和Application.mk,且还要通过java命令生成.h头文件,才能编译生成so库。但在Android Studio中这些步骤都不需要,因为Gradle足够强大,只需配置Gradle即可编译生成so库。

三、开发JNI的步骤

JNI代码主要又分为Native代码和Java代码,所以我们得实现Native端和Java端

1、安装NDK配置环境变量和相关插件(NDK、CMake、LLDB)
image.png

下载完之后 会自动下载到sdk里面

image.png
2、新建一个Android标准工程,并在工程设置中配置NDK路径。
image.png
3、打开app下的 build.gradle,配置NDK和在gradle.properties里配置android.useDeprecatedNdk=true
  defaultConfig {
        applicationId "xiao.mi.jni"
        minSdkVersion 16
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        ndk{
            moduleName "jnitest"//*生成的so文件名,必填
            abiFilters  "armeabi-v7a", "x86" //配置输出的abi体系结构下的so库,
        }
    }

配置gradle.properties 文件

android.useDeprecatedNdk=true
4.在类中定义jni本地接口方法。
public class JNITest {

    public static native String getJniStr();
    public static native String processBitmap(Bitmap bitmap);

}
5、生成对应的C文件默认实现

在我们定义了本地接口方法之后,我们在方法上按alt+Enter,然后生成对应的方法,可是不出意外的话生成的c文件只是有一个头文件的,并没有为我们生成对应的方法框架,

#include <jni.h>

如果你熟悉Jni的语法可以自己去实现,但是太麻烦了,幸好谷歌为我们提供了一个插件gradle-experimental,我们只需要在app下的gradle.build脚本里配置(仅仅在我们生成jni方法框架时添加,当我们全部添加完JNI方法框架之后,必须注释或者删除掉,否则run的时候就绝对报错)

所以定义好本地方法之后,按alt+enter就会出现下边的页面。

image.png image.png

点击左边的两个箭头,点击就可以跳转到本地方法去,也很方便。

6、完成上面5个步骤之后,就可以make或者run了,然后就会生成对应的so文件(..\build\intermediates\ndk\debug\obj\local)
上一篇下一篇

猜你喜欢

热点阅读