Android Studio 使用JNI笔记

主要记录一些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/下面

Android Studio 使用JNI笔记_第1张图片
B712C089-290A-4CFA-AD97-391F9A3F695C.png

具体代码如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* 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 
#include 
#include 


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 
// 宏定义类似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方法差不多了。。

打完收工~~~~

你可能感兴趣的:(Android Studio 使用JNI笔记)