1. 程式人生 > >JNI中log 列印以及 NDK環境變數配置

JNI中log 列印以及 NDK環境變數配置

1. 匯入log標頭檔案

在你使用的 .c/ .cpp 檔案中

匯入 log.h 標頭檔案

 #include<Android/log.h>

加上

LOCAL_LDLIBS :=-llog

注意Android.mk裡有一行include $(CLEAR_VARS)

必須把LOCAL_LDLIBS :=-llog放在它後面才有用,

否則相當於沒寫。

3. 定義LOG 函式

先定義一個全域性變數,再定義一些輸出的LOG函式:

#define LOG_TAG "HelloJni"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG ,__VA_ARGS__) // 定義LOGD型別
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG ,__VA_ARGS__) // 定義LOGI型別
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG ,__VA_ARGS__) // 定義LOGW型別
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG ,__VA_ARGS__) // 定義LOGE型別
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, LOG_TAG ,__VA_ARGS__) // 定義LOGF型別


上述程式碼中定義的函式

分別對應於Android 的Java程式碼中的

 Log.d(), Log.i(), Log.w(),Log.e(), Log.f()等方法.

4.舉例 一定要注意列印的時候使用C++的列印方法

之前

LOGD("haigui###### number = %d",number);

JNIEXPORT void JNICALL Java_com_example_hellojni_HelloJni_sayHello
  (JNIEnv *env, jobject obj){
    //獲取obj中物件的class物件
    jclass clazz = env->GetObjectClass(obj);
    //獲取Java中的number欄位的id(最後一個引數是number的簽名)
    jfieldID id_number = env->GetFieldID(clazz,"number","I");
    //獲取number的值
    jint number = env->GetIntField(obj,id_number);
    LOGD("haigui###### number = %d",number);
    //修改number的值為100,這裡要注意的是jint對應C++是long型別,所以後面要加一個L
    env->SetIntField(obj,id_number,100L);
}


Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := HelloJni
LOCAL_SRC_FILES := HelloJni.cpp

LOCAL_LDLIBS +=-llog
#LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llog

include $(BUILD_SHARED_LIBRARY)




linux下ndk配置:
在etc/profile 檔案末尾追加 兩行
export NDK_HOME=/home/denghaigui/AndroidDevTool/android-ndk-r10e
export PATH=$NDK_HOME:$PATH
配置完成後 source /etc/profile
注意多次source 會讓/home/denghaigui/AndroidDevTool/android-ndk-r10e 重複新增 重複新增後 專案也會找不到ndk路徑 ndk也沒法編譯
所以只要source一次就可以了 當source多次後 重啟機子就能恢復正常


eg:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <android/log.h>

#define LOG_TAG "HelloJni"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG ,__VA_ARGS__) // 定義LOGD型別
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG ,__VA_ARGS__) // 定義LOGI型別
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG ,__VA_ARGS__) // 定義LOGW型別
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG ,__VA_ARGS__) // 定義LOGE型別
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL, LOG_TAG ,__VA_ARGS__) // 定義LOGF型別



#ifndef _Included_com_example_hellojni_HelloJni
#define _Included_com_example_hellojni_HelloJni
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_hellojni_HelloJni
 * Method:    getString
 * Signature: ()Ljava/lang/String;
 * java呼叫C++中方法
 */
JNIEXPORT jstring JNICALL Java_com_example_hellojni_HelloJni_getString
  (JNIEnv *env, jobject obj){
	env->GetObjectClass(obj);
	 return env->NewStringUTF("Hello from JNI !");
}

/*
 * Class:     com_example_hellojni_HelloJni
 * Method:    sayHello
 * Signature: ()V
 * C++改變java屬性的值
 */
//JNIEXPORT void JNICALL Java_com_example_hellojni_HelloJni_sayHello
//  (JNIEnv *env, jobject obj){
//	//獲取obj中物件的class物件
//	jclass clazz = env->GetObjectClass(obj);
//	//獲取Java中的number欄位的id(最後一個引數是number的簽名)
//	jfieldID id_number = env->GetFieldID(clazz,"number","I");
//	//獲取number的值
//	jint number = env->GetIntField(obj,id_number);
//	LOGD("haigui###### number = %d",number);
//	//修改number的值為100,這裡要注意的是jint對應C++是long型別,所以後面要加一個L
//	env->SetIntField(obj,id_number,100L);
//}

/*
 * Class:     com_example_hellojni_HelloJni
 * Method:    sayHello
 * Signature: ()V
 * C++中呼叫java父函式和子函式
 */
JNIEXPORT void JNICALL Java_com_example_hellojni_HelloJni_sayHello
  (JNIEnv *env, jobject obj){
		//獲取obj中物件的class物件
		jclass clazz = env->GetObjectClass(obj);
		//獲取Java中的father欄位的id(最後一個引數是father欄位的簽名)對應HelloJni.java中 public Father father = new Child();  father物件
		jfieldID id_father = env->GetFieldID(clazz,"father","Lcom/example/hellojni/Father;");   
		//獲取father欄位的物件
		jobject father = env->GetObjectField(obj,id_father);
		//獲取father物件的class物件
		jclass clazz_father = env->FindClass("com/example/hellojni/Father");
		//獲取father物件中的function方法的id
		jmethodID id_father_function = env->GetMethodID(clazz_father,"function","()V");
		//呼叫父類中的function方法(但是會執行子類的方法)
		env->CallVoidMethod(father,id_father_function);
		//呼叫父類中的function方法(執行就是父類中的function方法)
		env->CallNonvirtualVoidMethod(father,clazz_father,id_father_function);
}

/*
 * Class:     com_example_hellojni_HelloJni
 * Method:    maxCallback
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_example_hellojni_HelloJni_maxCallback
  (JNIEnv *env, jobject obj){
	//獲取obj中物件的class物件
	jclass clazz = env->GetObjectClass(obj);
	//獲取Java中的max方法的id(最後一個引數是max方法的簽名)
	jmethodID id_max = env->GetMethodID(clazz,"max","(DD)D");
	//呼叫max方法
	jdouble doubles = env->CallDoubleMethod(obj,id_max,1.2,3.4);
	//輸出返回值
	LOGD("haigui###### double = %f",doubles );

	int i = 0;
	     LOGD("haigui ########## i = %d", i);
}
#ifdef __cplusplus
}
#endif
#endif