传统 JNI 开发步骤
总述
Android 的 JNI 开发一般可以总结为以下步骤
- 编写含有 Native 方法的 Java 类
- 用 javah 生成 C/C++ 原生函数的头文件
- 用 C/C++ 实现原生函数
- 将项目依赖的原生库和资源添加到工程中
- 生成应用
在类中追加 native 方法
public class Hello {
public native String hellojni();
}
生成头文件
在当前模块目录下追加一个 shell 文件,该文件用于生成头文件
hello.sh
#!/bin/sh
export ProjectPath=$(cd "."; pwd)
#echo $ProjectPath
export TargetClassName="com.example.jni.Hello"
export SourceFile="${ProjectPath}/src/main/java"
export TargetPath="${ProjectPath}/src/main/jni"
#echo $SourceFile
cd "${SourceFile}"
javah -d ${TargetPath} -classpath "${SourceFile}" "${TargetClassName}"
echo -d ${TargetPath} -
其中
TargetClassName
为含有 native 方法的类SourceFile
为 Java 源代码目录TargetPath
为 jni 源代码目录
运行 shell 文件 sh hello.sh
,在目录 src/main/jni
下会发现生成的.h 头文件
例
com_example_jni_Hello.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_jni_Hello */
#ifndef _Included_com_example_jni_Hello
#define _Included_com_example_jni_Hello
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_jni_Hello
* Method: hellojni
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_jni_Hello_hellojni
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
编写 JNI 代码
根据头文件,在 jni 目录下创建对应的.c/.cpp 文件,完成代码
例
hello.cpp
#include "com_example_jni_Hello.h"
/*
* Class: com_example_jni_Hello
* Method: hellojni
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_jni_Hello_hellojni
(JNIEnv *env, jobject){
return env->NewStringUTF( "hello from jni");
}
配置 NDK 环境
下载 NDK,并在工程目录下新建 local.properties
文件,在其中追加 ndk.dir
属性,值为 NDK 的路径
ndk.dir=/Users/localUser/Documents/android-ndk-r10d
编译 JNI 代码
选择当前模块 -> 右键选择 Make Module
后编译代码,完成后在 build/intermediates/ndk
目录下会生成对应的 Android.mk
文件和 xx.so
文件(如果出现错误,需要注意 ndk 下的 platform
目录下是否有当前的 sdk 版本,没有的话需要更新 ndk)。
载入 Library,运行代码
打开拥有 native 方法的类,加入以下语句
static {
System.loadLibrary(libraryName );
}
libraryName
就是上一节 Android.mk
文件中的 LOCAL_MODULE
名,Gradle 默认生成的 libraryName
就是当前的模块名,所以如果你用默认配置的话应该就是 app
。
以上都完成后,就可以运行代码查看效果了。
自定义配置
包含 moduleName 等可以通过修改 build.gradle 文件进行一些自定义配置
debug {
ndk {
// 自定义 library 名
moduleName "jnimain"
// 指定生成的 xx.so 平台
abiFilters "armeabi", "armeabi-v7a"
stl "stlport_shared"
}
}
基于最新 Android Studio 进行 JNI 开发
最新的 Android Studio 使用了新的一套配置来进行 JNI 开发,并且其内置了 NDK 的 Debug 机能。不过目前这种配置还是实验性的,所以与以前的方式相比较需要改动不少地方。
环境
Android Studio 1.3 RC1 以上
Gradle 2.5,目前仅支持 2.5,其它版本的 Gradle 都不行
修改 build.gradle 配置
根目录 build.gradle
注意 classpath
由原来的 classpath 'com.android.tools.build:gradle:1.3.+’
变为了以下这种
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.2.0'
}
}
allprojects {
repositories {
jcenter()
}
}
工程目录 build.gradle
apply plugin: 'com.android.model.application'
repositories {
jcenter()
}
model {
android {
compileSdkVersion = 22
buildToolsVersion = "22.0.1"
defaultConfig.with {
applicationId = "com.example.jni"
minSdkVersion.apiLevel = 9
targetSdkVersion.apiLevel = 22
versionCode = 1
versionName = "1.0"
}
}
android.buildTypes {
release {
minifyEnabled = false
proguardFiles += file('proguard-rules.pro')
}
debug {
ndk.with {
debuggable = true
}
}
}
android.ndk {
moduleName = "app"
}
compileOptions.with {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support:appcompat-v7:22.2.1'
}
这里需要注意几点
plugin 由
com.android.application
变为com.android.model.application
android{}
移到了model{}
下minSdkVersion
等变为了minSdkVersion.apiLevel
defaultConfig
等变为了defaultConfig.with
compileSdkVersion 22
之类的都变成了compileSdkVersion = 22
进行 Debug
以上修改完毕后,选择 Edit Configurations
-> 新建 Android Native
,以 Debug 形式运行此配置
在工程的 native 代码中打上断点,就可以进行 native 代码相关的 debug 了。
参考资料
完整的 Android 示例见 hello-jni