主要記錄一些as使用JNI的一些配置,避免忘記每次都要到處查找。。嚎幸。
使用as開發(fā)可以不用創(chuàng)建Android.mk文件疙挺,Application.mk文件,只要在build.gradle文件中配置相應(yīng)的參數(shù)即可使用。。
1.JNI文件的創(chuàng)建
首先創(chuàng)建Java的native類
public classMyJniTest {
public native voidprint(String str);
public native String getName();
}
然后運行項目,運行完成后在項目的build/intermediates/classes/debug/目錄下面可以看到生成的MyJniTest.class文件,然后用java命令生成對應(yīng)的JNI的.h文件,命令如下:
bogon:asjnitest yjg$ cd build/intermediates/classes/debug/
bogon:debug yjg$ ls
android com
bogon:debug yjg$ javah -jni com.jni.yjg.asjnitest.MyJniTest
創(chuàng)建完成后就可以看到對應(yīng)的.h文件栗竖,在../debug/下面
具體代碼如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_jni_yjg_asjnitest_MyJniTest */
#ifndef _Included_com_jni_yjg_asjnitest_MyJniTest
#define _Included_com_jni_yjg_asjnitest_MyJniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_jni_yjg_asjnitest_MyJniTest
* Method: print
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_jni_yjg_asjnitest_MyJniTest_print
(JNIEnv *, jobject, jstring);
/*
* Class: getName
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_jni_yjg_asjnitest_MyJniTest_getName
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
2.JNI配置
在項目的build.gradle文件中配置jni的參數(shù)了
debug{
ndk{
moduleName "MyJniTest"http://生成的so名字
stl "stlport_static"
ldLibs "log" //實現(xiàn)__android_log_print
abiFilters "armeabi", "armeabi-v7a", "x86" //輸出指定三種 abi體系結(jié)構(gòu)下的so庫。
}
}
其中stl就相當(dāng)于Android.mk文件中的APP_STL屬性渠啤。大概就是導(dǎo)入C++運行時庫吧狐肢。。
abiFilters就相當(dāng).mk文件中的APP_ABI沥曹。用于生成不同架構(gòu)的.so包份名。
3.實現(xiàn)jni方法
拷貝.h文件到項目的jni目錄下面。(as的jni目錄默認(rèn)在main下面妓美,需要自己創(chuàng)建僵腺,當(dāng)然也可以在build.gradle中自己指定)
創(chuàng)建對應(yīng)的.cpp文件
然后就是實現(xiàn).h文件中的方法,.cpp文件的具體代碼
#include <jni.h>
#include <com_jni_yjg_asjnitest_MyJniTest.h>
#include <android/log.h>
JNIEXPORT void JNICALL Java_com_jni_yjg_asjnitest_MyJniTest_print
(JNIEnv * env, jobject obj, jstring jsstr){
__android_log_print(ANDROID_LOG_DEBUG,"android","hello jni");
}
JNIEXPORT jstring JNICALL Java_com_jni_yjg_asjnitest_MyJniTest_getName
(JNIEnv * env, jobject jobject1){
return env->NewStringUTF("I'm jni");
}
ok以上就是JNI部分的實現(xiàn)了。
然后就是java層調(diào)用jni了,先是加載jni庫:
static {
System.loadLibrary("MyJniTest");
}
接著就是調(diào)用jni的方法了:
MyJniTest test=new MyJniTest();
test.print("aaa");
System.out.println("name:"+test.getName());
OK 運行項目壶栋。辰如。
這個就是Logcal中打印出來日志:
07-17 16:52:47.208 2211-2211/com.jni.yjg.asjnitest D/android: hello jni
07-17 16:52:47.208 2211-2211/com.jni.yjg.asjnitest I/System.out: name:I'm jni
OK,這就說明java層通過JNI和C++交互成功了贵试。
補充說明:
__android_log_print(ANDROID_LOG_DEBUG,"android","hello jni")這個是jni的log也能在Logcat中顯示琉兜,可以用來調(diào)試C++代碼,使用方法也和android的log類似毙玻,比如:ANDROID_LOG_DEBUG對應(yīng)就是Log.d
可以簡單的封裝下:
#ifndef MY_APPLICATION_EBEN_HPC_LOG_H
#define MY_APPLICATION_EBEN_HPC_LOG_H
#ifdef __cplusplus
extern "C" {
#endif
#include <android/log.h>
// 宏定義類似java 層的定義,不同級別的Log LOGI, LOGD, LOGW, LOGE, LOGF豌蟋。 對就Java中的 Log.i log.d
#define LOG_TAG "JNILOG" // 這個是自定義的LOG的標(biāo)識
//#undef LOG // 取消默認(rèn)的LOG
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG, __VA_ARGS__)
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG, __VA_ARGS__)
#ifdef __cplusplus
}
#endif
這樣子使用的時候直接調(diào)用:
LOGD("log.d 這是Jni中的log: xxxxxxx");
這就和android中的log方法差不多了。桑滩。
??打完收工~~~~