AndroidStudio编译JNI

以前使用其他IDE做JNI的时候还比较麻烦,特别是JNI和Java的操作是分开的,现在使用Android Studio做特别方便,还可以直接打包成 aar 格式对外提供。因为项目是对外提供开发包方式的,并不是自身App模式,因此打算直接创建一个简单的Android工程作为调用测试,再单独添加模块作为封装库。

创建工程

Android创建工程很简单,随便创建一个,然后基本项目目录就会出现 app 模块作为App程序,我们需要再单独添加一个库模块,创建一个 Android Library,再次目录下会创建一个库的目录,然后项目的目录结构如下

...
- app
- mylib
- gradle

JNI接口定义

开发JNI首先必须要有一定的JNI开发知识。

首先在库模块里面创建我们的接口类 ,然后添加接口,比如在文件 Decoder.java

package com.xx.mylib;
public class Decoder {
public native long decode(byte[] code, char[] id);
static {
System.loadLibrary("DeCodec");
}
}

上面的例子中,native 是指C++实现的动态库需要提供的接口方法,然后后面是提供的库名称,比如上面的 DeCodec 对应的就是 libDeCodec.so,有Linux基础的同学会比较清楚。

接下来就需要根据上面的接口生成对应的C的接口文件了,一般也可以手写,也可以使用 javah 生成,这里我们在 Android Studio 中添加一个生成工具,可以更快的生成。

Settings - Tools - External Tools 添加一个工具,配置参照下图

注意JDK的环境变量配置,否则可能直接找不到 javah 程序。

配置完成之后,在java文件上右击,出现菜单,里面会出现 NDK - javah 菜单项,点击会生成对应的头文件,正常情况下的名称类似 com_xx_decodec_Decoder.h,目录在 src/java 同目录下的 jni 目录。

JNI接口开发

JNI接口生成之后,我们就需要写实现了,使用C或C++都可以,使用NDK编译。不过一般接口参数等都不是C的类型,是JNI的类型,可能需要做一些数据类型转换,而且在实现的时候要注意安全性,否则最终使用直接导致进程崩溃,而非Java的异常,具体的百度。

代码实现之后,Android Studio 使用CMake编译脚本,在当前 jni 目录也创建一个 CMakeLists.txt 的文件,内容参照下面的脚本修改

cmake_minimum_required(VERSION 3.4.1)

AUX_SOURCE_DIRECTORY(./DeCodec CODE_SOURCE)
add_compile_options(-fvisibility=hidden)

set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -s")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s")

add_library(DeCodec SHARED ${BARCODE_SOURCE} com_xx_decodec_Decoder.cpp )
target_link_libraries(DeCodec ${log-lib} )

然后在库目录 mylib 下的 build.gradle 中的 android 节点下添加

externalNativeBuild {
cmake {
path "src/main/jni/CMakeLists.txt"
version "3.10.2"
}
}

然后同步一下Gradle即可,编译模块或整个项目就能在 build/outpus/aar/ 目录下获得 aar 格式的库。

测试使用

将生成的 aar 文件拷贝到测试工程 app 目录下的 libs 目录,然后在测试工程 app 目录下的 build.gradleandroid 节点添加以下内容

repositories {
flatDir {
dirs 'libs'
}
}

然后在最后面的 dependencies 添加依赖项

implementation(name: 'mylib-release', ext: 'aar')

工程配置完成了,然后就可以在java代码中引用使用了,比如

...
import com.xx.mylib.Decoder;

private Decoder decoder = new Decoder();
最近的文章

JAR使用JNA并打包dll

搞Java的同学应该都清楚,Java与C++交互方式是通过DLL,使用JNI技术,也就是现在Android上最常用的方式,但其实现在有更高层次的封装了,那就是JNA方式。虽然JNA使用很简单,但是发布却比较麻烦,特别是参考网上的文章基本很少有正确的方法,本文将详述正确的方法。 JNA的使用JNA(J …

技术 继续阅读
更早的文章

部署AppRTC服务

AppRTC是WebRTC视频通话的服务程序,一般可以将其作为参考实现,搭建AppRTC服务受限于很多条件,并不是太容易。在参考了官方操作和大量的博客之后,根据自己操作实践排除了很多网络博客上的错误方法,终于部署成功了一套环境。测试环境为阿里云的CentOS 7服务器,带公网IP和域名。 部署前的必 …

技术 继续阅读