最近项目中的蓝牙通讯部分,需要对数据进行加解密,使用到了 jni 技术,这是我第一次使用 jni 技术,这篇文章记录一下 jni 的一些知识点。

  • 工具篇,在 Android Studio 2.2 中进行 jni 开发。
  • 代码篇,c 和 java 互相调用,数据类型的转换。
  • 打包篇,使用了 so 库的应用安装包瘦身。

在 Android Studio 2.2 中进行 jni 开发

在 Android Studio 2.2 中进行 jni 开发,可以参考 这篇文章,Android Studio 2.2 使用的是 CMake 或者 NDK 作为构建工具,编译后的 so 文件类似于 jar/aar 文件,可以直接在项目中引用。

com.hello.jni.Foo.java 中的 public native void bar() 方法在 c 的 .h 文件中声明为void java_com_hello.jni_Foo_bar(),只需要在 .c 或者 .cpp 中实现这个方法即可,在 .h 文件中声明类似于在 java 的接口中声明方法,便于复用一些 common 部分。

需要注意的是,c 里面的值调用,地址调用,引用调用和 java 中传参还是存在差别的。

c 和 java 互相调用,数据类型的转换

关于 java 和 c 代码之间的相互调用,数据类型的转换,查看 这篇文章

使用了 so 库的应用安装包瘦身

Android 支持很多 ABI 类型,在 这篇文章 里有提到。

Android系统目前支持以下七种不同的CPU架构:ARMv5,ARMv7 (从2010年起),x86 (从2011年起),MIPS (从2012年起),ARMv8,MIPS64和x86_64 (从2014年起),每一种都关联着一个相应的ABI。

如果存在应用安装包瘦身的需求,可以采用动态加载的方式加载 so 库,整体思路是

1 获取手机支持的 ABI 类型
2 从服务器上下载对应的 so 库
3 加载 so 库

详细查看 这篇文章

原理:

Android 包管理器安装 APK 时,会自动选择 APK 包中为对应系统 ABI 预编译好的 .so 文件,如果在对应的 lib/ABI 目录中存在 .so 文件的话。

所以,实际上安装包上的六个 so 库,对于用户的手机来说,只有一个是会被安装,并且起作用的。

那么,其他的五个 so 库实际上是多余的,如果能够从安装包中去掉多余的五个 so 库,就可以达到为 APK 瘦身的目的。

我们如何得知系统支持何种 ABI 架构?使用 Android 自带的 API 即可。

1
2
3
4
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void getSupportABIS() {
String[] supportedAbis = Build.SUPPORTED_ABIS;
}