主要记录一些as使用JNI的一些配置,避免忘记每次都要到处查找。。。
使用as开发可以不用创建Android.mk文件,Application.mk文件,只要在build.gradle文件中配置相应的参数即可使用。。
1.JNI文件的创建
首先创建Java的native类
public classMyJniTest {
public native voidprint(String str);
public native String getName();
}
然后运行项目,运行完成后在项目的build/intermediates/classes/debug/目录下面可以看到生成的MyJniTest.class文件,然后用java命令生成对应的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
创建完成后就可以看到对应的.h文件,在../debug/下面
B712C089-290A-4CFA-AD97-391F9A3F695C.png具体代码如下:
/* 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的参数了
debug{
ndk{
moduleName "MyJniTest"//生成的so名字
stl "stlport_static"
ldLibs "log" //实现__android_log_print
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种 abi体系结构下的so库。
}
}
其中stl就相当于Android.mk文件中的APP_STL属性。大概就是导入C++运行时库吧。。
abiFilters就相当.mk文件中的APP_ABI。用于生成不同架构的.so包。
3.实现jni方法
拷贝.h文件到项目的jni目录下面。(as的jni目录默认在main下面,需要自己创建,当然也可以在build.gradle中自己指定)
创建对应的.cpp文件
然后就是实现.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部分的实现了。
然后就是java层调用jni了,先是加载jni库:
static {
System.loadLibrary("MyJniTest");
}
接着就是调用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中显示,可以用来调试C++代码,使用方法也和android的log类似,比如:ANDROID_LOG_DEBUG对应就是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的标识
//#undef LOG // 取消默认的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
这样子使用的时候直接调用:
LOGD("log.d 这是Jni中的log: xxxxxxx");
这就和android中的log方法差不多了。。
👌打完收工~~~~
网友评论