Liping Zou bio photo

Liping Zou

An Android Developer

Email Twitter Instagram Github Stackoverflow

Overview

###JNI数据类型

Java数据类型 JNI数据类型
int jint/jsize
long jlong
byte jbyte
string jstring
boolean jboolean
char jchar
float jfloat
double jdouble
short jshort

###Android.mk

Android.mk用来向Android NDK描述C/C++资源文件的,是GNU Makefile的片段。

Android.mk in HelloJni:

1
2
3
4
5
6
7
8
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c

include $(BUILD_SHARED_LIBRARY)
  1. Android.mk必须以LOCAL_PATH的定义开始,用于在开发树中定位源文件。my-dir方法返回当前的目录。
  2. CLEAR_VARS变量指向一个特定的GNU Makefile,用于阐明除了LOCAL_PATH外的LOCAL_XXX。
  3. 在Android.mk中必须定义LOCAL_MODULE变量来辨识每个模块。LOCAL_MODULE的名字必须是唯一的,且不包含空格。Build System将自动生成前缀和后缀,例如一个共享库模块的名字是”test”,将会生成”libtest.so”。
  4. LOCAL_SRC_FILES定义了包括在模块中的一系列C/C++源文件。在这里需要注意的是,不要将头文件和包含文件定义在这里,系统将自动添加依赖。
  5. BUILD_SHARED_LIBRARY指向了一个GNU Makefile来收集定义在LOCAL_XXX变量中的信息。

###Application.mk

Application.mk用于描述应用所需的native模块。

###JNIEnv

  1. JNIEnv指向了线程相关的结构,线程相关结构指向了一个指针数组,在指针数组的每个元素都可以指向一个JNI方法。
  2. JNIEnv用于线程本身的存储,所以不能跨线程传递。
  3. 在C和C++中的JNIEnv是不同的。

查看/android-ndk-r10/platforms/android-L/arch-arm/usr/include/jni.h,可以对比在C和C++中对JNIEnv的定义。

1
2
3
4
5
6
7
8
9
10
11
struct _JNIEnv;
struct _JavaVM;
typedef const struct JNINativeInterface* C_JNIEnv;

#if defined(__cplusplus)
typedef _JNIEnv JNIEnv;
typedef _JavaVM JavaVM;
#else
typedef const struct JNINativeInterface* JNIEnv;
typedef const struct JNIInvokeInterface* JavaVM;
#endif
  • 在C中:

JNIEnv是struct JNINativeInterface* JNIEnv,要获取JNINativeInterface中的函数指针,必须对其进行解引用,通过JNIEnv *env来调用JNI方法。例如,(*env)->NewStringUTF(env, "Hello from JNI");

  • 在C++中:

JNIEnv是struct _JNIEnv,调用JNI方法,直接调用即可。例如,nv->NewStringUTF(env, "Hello from JNI");

###输出Log

####引入头文件

在c文件中,加入如下代码。

1
2
3
#define LOG_TAG "jni log"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)

__android_log_print的第一个参数是priority优先级,分为ANDROID_LOG_DEBUG、ANDROID_LOG_ERROR、ANDROID_LOG_INFO等等。第二个参数是tag标签。第三个参数是输出的文本。这就相当于Android中的Log.d(tag, msg)

####Android.mk中添加log动态库

在Android.mk文件中,添加LOCAL_LDLIBS += -llog

1
2
3
4
5
6
7
8
9
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c
LOCAL_LDLIBS    += -llog

include $(BUILD_SHARED_LIBRARY)

添加库的方法是LOCAL_LDLIBS += -lname,其中的name是动态库的名字,不包含前缀lib和后缀.so。

####添加输出log代码

在c文件中,添加类似LOGE("jni print log”);的代码,运行即可在logcat中输出你打印的log。