編輯:關於Android編程
Android系統JNI的實現方式
All rights reserved
JNI(Java Native Interface)定義了一種Java代碼調用C或者C++代碼等其他代碼的方式。
在Android系統中,JNI通過JNINativeMethod結構體進行描述,該結構體定義於jni.h,如下所示:
typedef struct { const char* name; const char* signature; void* fnPtr; } JNINativeMethod;
第一個參數name:是Java代碼中的函數名。
第二個參數signature:用於描述函數的參數和返回值。
第三個參數fnPtr:C代碼中函數的指針。
其中,第二個參數為一個描述函數參數和返回值的字符串,字符串的格式如下:
(XX..)X
X的取值和定義如下所示:
字符
Java類型
C類型
V
void
void
Z
jboolean
unsigned char
B
jbyte
signed char
C
jchar
unsigned short
S
jshort
short
I
jint
int
J
jlong
long
F
jfloat
float
D
jdouble
double
另外,從jni.h中對於變量類型的定義中也可以看到這些字符的意義,如下所示:
typedef unsigned char jboolean; /* unsigned 8 bits */ typedef signed char jbyte; /* signed 8 bits */ typedef unsigned short jchar; /* unsigned 16 bits */ typedef short jshort; /* signed 16 bits */ typedef int jint; /* signed 32 bits */ typedef long long jlong; /* signed 64 bits */ typedef float jfloat; /* 32-bit IEEE 754 */ typedef double jdouble; /* 64-bit IEEE 754 */ typedef union jvalue { jboolean z; jbyte b; jchar c; jshort s; jint i; jlong j; jfloat f; jdouble d; jobject l; } jvalue;
例如,為一個驅動添加HAL層,並創建JNI層。僅就JNI層而言,創建frameworks/base/services/jni/com_android_server_DemoService.cpp文件,該文件中用於描述JNI接口的代碼如下所示:
static const JNINativeMethod method_table[] = { {"init_native", "()I", (void*)demo_init}, {"setVal_native", "(II)V", (void*)demo_setVal}, {"getVal_native", "(I)I", (void*)demo_getVal}, };
其中“(II)V”,表示函數的有兩個整形參數,返回值為void。
注意:由參數二指定的函數參數和返回值類型一定要和C函數的參數和返回值保持一致,否則雖然編譯能夠通過,但在Android系統加載過程中,會報如下所示的錯誤,導致Android系統無法正常運行。
E/dalvikvm( 1737): ERROR: couldn't find native method E/dalvikvm( 1737): Requested: Lcom/android/server/DemoService;.init_native:()Z E/dalvikvm( 1737): Candidate: Lcom/android/server/DemoService;.init_native:()I E/JNIHelp ( 1737): RegisterNatives failed for 'com/android/server/DemoService', aborting F/libc ( 1737): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 1737 (system_server)
以上錯誤通發生在frameworks/base/services/jni/onload.cpp文件中的JNI_OnLoad()函數中,如下所示:
extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint result = -1; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { ALOGE("GetEnv failed!"); return result; } ALOG_ASSERT(env, "Could not retrieve the env!"); …… register_android_server_DemoService(env); …… return JNI_VERSION_1_4; }
另外,ProGuard對程序的優化也可能導致上述運行錯誤的發生。此時,可以在makefile文件中添加“LOCAL_PROGUARD_ENABLED:=disabled”宏來關閉ProGuard的優化。
關於ProGuard,可以參考其官方網站:http://proguard.sourceforge.net/
ProGuard是一個免費的Java類文件壓縮器、優化器、混淆器和預校驗器。它會檢測並刪除沒有用到的類、域、方法以及屬性。它最大限度的優化字節碼並且刪除無用的指令。它用很短的沒有意義的名字對剩余的類、域和方法進行重命名。最後,它對處理過的代碼進行預校驗。
ProGuard的一些用途如下:
A.為了更小的代碼檔案、更快的網絡傳輸、更快的加載速度和更小的內存占用創建更緊湊的代碼;
B.使程序和庫難於進行反向工程;
C.列出死代碼,這樣就能將其刪除;
D.為Java 6或更高的版本對存在的類文件進行重定位和預校驗,以充分利用其快速加載類的性能。
寫了一個月應用層代碼,感覺寫嘔了,最近在研究插件化動態加載方面的東西。本文需要解決的作業:在Activity自身的跳轉中進行Hook。先簡要說下遇到的幾個坑以及後面的學習
話不多說:先撸一個html:名字叫index.html,這個html放到哪裡,大家應該都知道吧,哈哈!!!!<!--// Created by wangdan o
hello,大家好,本文主要介紹如何開始開發一個美觀、有情調、人見人愛的Android應用程序,已知我們在市面上有不少布局極其精美,在視覺上讓人愛不釋手的應用程序,如果讓
在眾多主流App中,包括QQ,微信等,為了和ios的UI保持統一,很多App使用的都是底部導航,當然在Android中也並不反對這種設計。這篇文章使用ViewPager實