Android Studio JNI 流程
1. 在Android code中,加载so库,添加native方法
package com.stone.jni;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
/**
* author : stone
* email : [email protected]
* time : 16/2/16 23 45
*/
public class MainActivity extends Activity {
static {
System.loadLibrary("stonelib_test");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
setContentView(tv);
// tv.setText(hello("admin"));
tv.setText(hello("中华小子"));
}
public native String hello(String username);
}
2. 利用javah命令,生成当前native方法所在类的对应的 .h 头文件
先build一下工程,生成源文件对应的.class文件。通过菜单栏中的Build>Make Project 或 Make Module 选项
在 <project>/<module>/build/intermediates/classes/debug/ 目录下生成相应的.class文件
$ cd <project>/<module>/src/main
$ javah-d jni -classpath <android.jar-path>:<project>/<module>/build/intermediates/classes/debug/ com.stone.jni.MainActivity
会在studio中的module/src/main 下生成一个jni目录,并生成一个.h头文件
生成的.h文件:
#ifndef _Included_com_stone_jni_MainActivity
#define _Included_com_stone_jni_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_stone_jni_MainActivity
* Method: hello
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT jstring JNICALL Java_com_stone_jni_MainActivity_hello
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
在extern "C" { … } 中 按C语言进入编译,而不是C++
在{}之外就是按C++ 编译了
note:
JNIEXPORT、JNICALL 为jni关键字 ,表示jni调用将调用后面的方法
Java_com_stone_jni_MainActivity_hell 方法名,以Java_ 开头,后跟完全限定类名和方法名
关于方法的参数:
第一个是 JNIEnv *类型。第二个jobject类型表示该方法是一个实例方法;
若方法本身是一个static修饰的静态方法,那么第二个参数会是jclass类型。
再之后的才是java方法中的参数对应的在jni中的数据类型
JNIEXPORT jstring JNICALL Java_com_stone_jni_MainActivity_hell(JNIEnv *, jobject, jstring);
这里在C中调用String类的相关方法;需要通过命令拿到java类的 所有方法签名
$javap -s java.lang.String
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <stdlib.h>
/* Header for class com_stone_jni_MainActivity */
#ifndef _Included_com_stone_jni_MainActivity
#define _Included_com_stone_jni_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_stone_jni_MainActivity
* Method: hello
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT jstring JNICALL Java_com_stone_jni_MainActivity_hello
(JNIEnv *env, jobject obj, jstring jstr)
{
jstring hel = (*env)->NewStringUTF(env, "hello,");
jclass cls = (*env)->FindClass(env, "java/lang/String");
jmethodID initId = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V");
jobject object = (*env)->NewObject(env, cls, initId, hel);
jmethodID concatM = (*env)->GetMethodID(env, cls, "concat", "(Ljava/lang/String;)Ljava/lang/String;");
jstring ss = (*env)->CallObjectMethod(env, object, concatM, jstr);
return ss;
}
#ifdef __cplusplus
}
#endif
#endif
4. 在build.gradle中配置NDK
> 在local.properties文件中
添加ndk.dir=ndk-path //指定ndk路径
>修改module下的build.gradle配置
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
defaultConfig {
applicationId "com.stone.jni"
minSdkVersion 8
targetSdkVersion 23
versionCode 1
versionName "1.0"
ndk {
moduleName "stonelib_test" //库的名字
ldLibs "log", "z", "m" //附加系统库
abiFilters "armeabi", "armeabi-v7a", "x86", "mips" //cpu架构
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.1.1'
}
然后运行工程,生成的so文件目录<Project>/app/build/intermediates/ndk/
mk文件,也会自动生成于该目录下