當前位置:首頁 » 操作系統 » androidjni源碼

androidjni源碼

發布時間: 2022-06-11 14:34:53

『壹』 如何在android源碼中添加自己的jni方法

1,、項目實現了一個簡單的四則運算,項目的目錄層次如下:

AndroidManifest.xml Android.mk jni res src

資源文件簡簡單單,一個布局文件,稍後會有demo的下載地址

主要記錄備忘的內容如下:

MainActivity.java

[html] view plain public native int add(int x, int y);

public native int substraction(int x, int y);

public native float multiplication(int x, int y);

public native float division(int x, int y);

static{

System.loadLibrary("arithmetic");

}

2、生成lib的名稱為libarithmetic.so.注意load的時候寫"arithmetic"

jni 目錄下有兩個文件,一個是Android.mk,一個是c++源文件long.cpp

jni/Android.mk如下:

[html] view plain LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_MODULE:= libarithmetic

LOCAL_SRC_FILES:= \

long.cpp

LOCAL_SHARED_LIBRARIES := \

libutils

LOCAL_STATIC_LIBRARIES :=

LOCAL_C_INCLUDES += \

$(JNI_H_INCLUDE)

LOCAL_CFLAGS +=

LOCAL_PRELINK_MODULE := false

include $(BUILD_SHARED_LIBRARY)

3、注釋:

LOCAL_PATH(必須定義,而且要第一個定義),宏函數『my-dir』, 由編譯系統提供,用於返回當前路徑(即包含Android.mk
file文件的目錄);

include $( CLEAR_VARS),

CLEAR_VARS由編譯系統提供,指定讓GNU MAKEFILE為你清除許多LOCAL_XXX變數(例如 LOCAL_MODULE,
LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, 等等...),除LOCAL_PATH
。這是必要的,因為所有的編譯控制文件都在同一個GNU MAKE執行環境中,所有的變數都是全局的;

LOCAL_MODULE_TAGS :=user eng tests optional

user: 指該模塊只在user版本下才編譯

eng: 指該模塊只在eng版本下才編譯

tests: 指該模塊只在tests版本下才編譯

optional:指該模塊在所有版本下都編譯

LOCAL_MODULE(必須定義),標識你在Android.mk文件中描述的每個模塊。名稱必須是唯一的,而且不包含任何空格。Note:編譯系統會自動產生合適的前綴和後綴,例如:arithmetic編譯成功後將生成libarithmetic.so庫文件

LOCAL_SRC_FILES 變數必須包含將要編譯打包進模塊中源代碼文件。不用在這里列出頭文件和包含文件。

LOCAL_SHARED_LIBRARIES中加入所需要鏈接的動態庫(*.so)的名稱

LOCAL_STATIC_LIBRARIES加入所需要鏈接的靜態庫(*.a)的名稱

LOCAL_CFLAG可選的編譯器選項,用法之一是定義宏,例如LOCAL_CFLAGS := -Werror作用是編譯警告也作為錯誤信息

LOCAL_PRELINK_MODULE:=false,不作prelink處理,默認是要prelink操作的,有可能造成地址空間沖突(這地方目前還不明白)
long.cpp源代碼如下:

[html] view plain #define LOG_TAG "LongTest2 long.cpp"

#include

#include

#include "jni.h"

jint add(JNIEnv *env, jobject thiz, jint x, jint y){

return x + y;

}

jint substraction(JNIEnv *env, jobject thiz, jint x, jint y){

return x - y;

}

jfloat multiplication(JNIEnv *env, jobject thiz, jint x, jint y){

return (float)x * (float)y;

}

jfloat division(JNIEnv *env, jobject thiz, jint x, jint y){

return (float)x/(float)y;

}

static const char *classPathName = "com/inspur/test2/MainActivity";

static JNINativeMethod methods[]= {

{"add", "(II)I", (void*)add},

{"substraction", "(II)I", (void*)substraction},

{"multiplication", "(II)F", (void*)multiplication},

{"division", "(II)F", (void*)division},

};

typedef union{

JNIEnv* env;

void* venv;

}UnionJNIEnvToVoid;

static int registerNativeMethods(JNIEnv* env, const char* className,

JNINativeMethod* gMethods, int numMethods){

jclass clazz;

clazz = env->FindClass(className);

if (clazz == NULL)

return JNI_FALSE;

if (env->RegisterNatives(clazz, gMethods, numMethods)<0)

return JNI_FALSE;

return JNI_TRUE;

}

static int registerNatives(JNIEnv *env){

if (!registerNativeMethods(env, classPathName,

methods, sizeof(methods)/sizeof(methods[0])))

{

return JNI_FALSE;

}

return JNI_TRUE;

}

jint JNI_OnLoad(JavaVM* vm, void* reserved){

UnionJNIEnvToVoid uenv;

uenv.venv = NULL;

jint result = -1;

JNIEnv *env = NULL;

if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK){

goto l;

}

env = uenv.env;

env = uenv.env;

if (registerNatives(env) != JNI_TRUE){

goto l;

}

result = JNI_VERSION_1_4;

l:

return result;

}

除了利用 編寫native JAVA類,通過javah生成.h文件,根據.h文件編寫.c/cpp文件
方法外(名字像老太太的裹腳步,又臭又長,而且不靈活),Android還可以通過引用JNI_Onload方式實現。jint JNI_onLoad(JavaVM*
vm, void* reverced),改方法在so文件被載入時調用。

JNI_OnLoad()有兩個重要的作用:

指定JNI版本:告訴VM該組件使用那一個JNI版本(若未提供JNI_OnLoad()函數,VM會默認該使用最老的JNI
1.1版),如果要使用新版本的JNI,例如JNI
1.4版,則必須由JNI_OnLoad()函數返回常量JNI_VERSION_1_4(該常量定義在jni.h中) 來告知VM。

初始化設定,當VM執行到System.loadLibrary()函數時,會立即先呼叫JNI_OnLoad()方法,因此在該方法中進行各種資源的初始化操作最為恰當。

JNI_OnUnload()的作用與JNI_OnLoad()對應,當VM釋放JNI組件時會呼叫它,因此在該方法中進行善後清理,資源釋放的動作最為合適。

4、項目根目錄下Android.mk文件:

[html] view plain LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_SRC_FILES := $(call all-java-files-under, src)

LOCAL_JNI_SHARED_LIBRARIES := libarithmetic

LOCAL_PACKAGE_NAME := LongTest

LOCAL_SHARED_LIBRARIES := \

libutils\

liblog

include $(BUILD_PACKAGE)

include $(LOCAL_PATH)/jni/Android.mk

# Also build all of the sub-targets under this one: the shared library.

include $(call all-makefiles-under,$(LOCAL_PATH))

LOCAL_PACKAGE_NAME:項目名稱,即最終生成apk的名字

LOCAL_JNI_SHARED_LIBRARIES := libxxx就是把so文件放到apk文件里的libs/armeabi里

執行BUILD_PACKAGE。它的定義也是在config.mk中定義如下:BUILD_PACKAGE:=
$(BUILD_SYSTEM)/package.mk

$(call all-java-files-under, src)編譯的源代碼文件列表添加src目錄下所有的java 源文件

$(call all-makefiles-under, $(LOCAL_PATH))編譯器會在編譯完當前目錄下的文件後再深入子目錄編譯

如果make過android源碼,可以在項目根目錄下執行mm命令進行編譯。前提是執行過source
androidSRC/build/envsetup.sh

或者直接把source androidSRC/build/envsetup.sh添加到~/.bashrc中,會更加方便

『貳』 Android源碼學習之如何創建使用JNI


  • publicclassHelloWorld{

  • ();//所有native關鍵詞修飾的都是對本地的聲明

  • static{

  • System.loadLibrary("hello");//載入本地庫

  • }

  • publicstaticvoidmain(String[]args){

  • newHelloWorld().displayHelloWorld();

  • }

  • }

上面的就是使用JNI的方式,其中so庫的名字是libhello.so,放到libs下面。

jni中的方法需要在修飾符後面加上native,

例如:();,

在使用之前需要導入so庫,

導入方法:

  • static{

  • System.loadLibrary("hello");//載入本地庫

  • }

在導入的時候是可以省略so庫前面的lib的,當然加上也沒事。

還有就是使用的地方一定要在固定的包名類名下。

希望能夠幫助你。

『叄』 如何在Android下使用JNI

Android中JNI是編譯so庫的源代碼,編譯成功後會生成SO庫,android中最終是使用SO庫的。 1.android的NDK開發需要在linux下進行: 因為需要把C/C++編寫的代碼生成能在arm上運行的.so文件,這就需要用到交叉編譯環境,而交叉編譯需要在linux系統下才能完成。 2.安裝android-ndk開發包,這個開發包可以在google android 官網下載: 通過這個開發包的工具才能將android jni 的C/C++的代碼編譯成庫 3.android應用程序開發環境: 包括eclipse、java、 android sdk、 adt等。 NDK編譯步驟: 1.選擇 ndk 自帶的例子 hello-jni ,我的位於E:\android-ndk-r5\samples\hello-jni( 根據具體的安裝位置而定 ) 。 2.運行 cygwin ,輸入命令 cd /cygdrive/e/android-ndk-r5/samples/hello-jni ,進入到 E:\android-ndk-r5\samples\hello-jni 目錄。 3.輸入 $NDK/ndk-build ,執行成功後,它會自動生成一個 libs 目錄,把編譯生成的 .so 文件放在裡面。 ($NDK是調用我們之前配置好的環境變數, ndk-build 是調用 ndk 的編譯程序 ) 4.此時去 hello-jni 的 libs 目錄下看有沒有生成的 .so 文件,如果有,ndk 就運行正常啦。

『肆』 android studio 怎麼編譯jni

一、使用已經編譯好的so

這種情況比較件簡單,只要把的.so文件放到相應的目錄即可。如下:

.[mole_name]
. . [src]
. . .[main]
. . . .[jniLibs]
. . . . .[armeabi]
. . . . .[armeabi-v7a]
. . . . .[x86]
. . . . .[mips]

注意 jniLibs 目錄是放在 mole 下面,在Android Studio中效果如下,這樣編譯之後so就會被自動打包進apk,代碼中直接 loadLibrary即可了:

1 String libName = "helloNDK"; // 庫名, 注意沒有前綴lib和後綴.so
2 System.loadLibrary( libName );

二、使用C/C++源碼

1 r9d以上版本NDK

首先確保自己的NDK版本在r9d以上,目前最新可以拿到的是r10,下載地址:

http://tools.android-studio.org/

感謝 Android Studio中文組的無私奉獻。

如果低於r9d版本,Android studio 下ndk編譯會出現 No rule to make target 的錯誤。

2 配置 ndk.dir

在 local.properties 添加如下配置:

sdk.dir=/path/to/android-sdk

ndk.dir=/path/to/android-ndk

『伍』 android 源碼dvmusejnibridge在哪

一、下載android 源碼 1/android/git-repo/git-repo' 改為清華大學的地址 REPO_URL = 'git://aosp/android/git-repo' 3/platform/manifest 改為清華大學的地址 $ repo init -u git://aosp/android/platform/manifest 4/" /> 改為下面的code即可: <remote name="aosp" fetch="git://aosp/android/" review="https://android-review/" /> 這個方法也可以用來在同步Cyanogenmod代碼的時候從TUNA同步部分代碼

『陸』 android jni 使用第三方提供的.so庫及所對應的jar包

1.將SO文件直接放到libs/armeabi下,然後代碼中System.loadLibrary("xxx");再public native static int xxx_xxx_xxx();接下來就可以直接調用xxx_xxx_xxx()方法;
2.第二種方案,創建自己的SO文件,在自己的SO文件里調用第三方SO,再在程序中調用自己的SO,這種比較復雜,需要建java類文件,生成.h文件,編寫C源文件include之前生成的.h文件並實現相應方法,最後用android NDK開發包中的ndk-build腳本生成對應的.so共享庫。 http://www.ijiami.cn/newsInfo?id=293&v=3

2. DEX加殼保護,DEX指令動態載入保護和高級源碼混淆保護。其中DEX加殼保護是「愛加密」主推的賣點,該技術通過將DEX文件隱藏,並生成一個類似於虛像的殼文件,阻止黑客利用反編譯工具獲取App源碼。另外,愛加密http://www.ijiami.cn/推出了so庫保護,使得C/C++ 層面的代碼安全也得到防護。加上資源文件保護(圖片、音頻等文件的防查看和防修改)、xml 主配文件保護(對主配文件進行二次簽名)、內存保護等措施,可以基本保證App的動態和靜態安全。

『柒』 Android JNI開發資料,源碼

pekdou

您 好 :

強 烈 建 議 你 直 接 看 一 下 這 個 吧 ! 可 以 節 省 你 很 多 時 間 !

tZx www.PoPa.sumwu.com。UmV

¤○①¤◎◇▓↓⊕◎
jclass GpsInfoClass = env->FindClass("com/parser/GPSINFO");
jfieldID ID_bValid = env->GetFieldID(GpsInfoClass,"bValid","I");
jfieldID ID_bSpeed = env->GetFieldID(GpsInfoClass,"bSpeed","I");
env->SetIntField(_obj,ID_bValid,(jint)info.bValid);
env->SetIntField(_obj,ID_bSpeed,(jint)info.bSpeed);
return _obj;
以上就可以了。但是不知道你的BYTE是自定義的什麼類型,如果是char之類的,就另外想辦法轉換成jint。其中 _obj 變數是public native GPSINFO getGpsInfo();這個本地方法在C代碼中的參數:JNIEXPORT jobject JNICALL Java_com_parser_GPSINFO_ getGpsInfo(JNIEnv *env, jobject _obj)

『捌』 做jni開發android系統源碼怎麼分析

Android中JNI是編譯so庫的源代碼,編譯成功後會生成SO庫,android中最終是使用SO庫的。
1.android的NDK開發需要在linux下進行: 因為需要把C/C++編寫的代碼生成能在arm上運行的.so文件,這就需要用到交叉編譯環境,而交叉編譯需要在linux系統下才能完成。
2.安裝android-ndk開發包,這個開發包可以在google android 官網下載: 通過這個開發包的工具才能將android jni 的C/C++的代碼編譯成庫
3.android應用程序開發環境: 包括eclipse、java、 android sdk、 adt等。

『玖』 android jni層用什麼寫的

NDK開發可以linux下的android源碼中編譯單個模塊生成.so文件,然後放在上層android 項目中調用,你在源碼中吧,你要編譯的模塊驅動的C代碼放進去,按照JIN規則取號名字,然後編\編譯,就行了,把生成的 so文件導入到上層項目,然後你知道C的函數名,在java層寫本地方法和,C的函數名一樣,記得類名也別搞錯了,就行了。不要燒錄整個系統,只要編譯你需要的驅動模塊生成so文件就行

『拾』 Android用NDK和整套源碼下編譯JNI的不同

2. 注冊函數的方法是不同的。舉例說,在com/evan129/jnitest/jniutils.java有個native int foo()方法,需要在jni中實現
在ndk中,只要實現這個函數,然後函數名是以jint java_com_evan129_jnitest_jniutils_foo(jnienv* env, jobject thiz) 命名既可。也就是說,如果jni只要實現這個函數,並且功能也很簡單的話,那麼jni c/cpp文件里只需要這一個函數就完事了。
但在android源碼中編譯jni代碼是不同的,jni中的函數名無所謂。不過至少還需要加一個
jniexport jint jnicall jni_onload(javavm* vm, void* reserved)方法,這個方法可以找個現有的復制一把就行,檢查運行環境的。然後主要是這個方法中會調用(*env).registernatives函數,在這里把jni中的方法和java文件中的方法關聯起來。
3. 有個很詭異的區別,自動傳入的jnienv* env好像不是一個東西。因為在android源碼中使用這個env一般是如env->newstringutf(…),而ndk中sample里的一處是(*env)->newstringutf(…) 這env和*env差很大。但兩處函數傳入的都是jnienv* env,只能懷疑jnienv的定義是不是都是不同的。

熱點內容
順序存儲文件 發布:2024-11-02 16:26:16 瀏覽:795
python266 發布:2024-11-02 16:22:06 瀏覽:364
計算機如何設置雙密碼 發布:2024-11-02 15:38:18 瀏覽:929
超高速存儲 發布:2024-11-02 15:23:30 瀏覽:898
javades加密文件 發布:2024-11-02 15:14:15 瀏覽:534
讀卡器怎麼看配置 發布:2024-11-02 15:14:10 瀏覽:459
安卓手機如何更改屏幕常亮 發布:2024-11-02 15:14:02 瀏覽:605
存儲空間介紹 發布:2024-11-02 15:12:22 瀏覽:417
沒有連上伺服器怎麼辦 發布:2024-11-02 14:39:02 瀏覽:626
早期存儲卡 發布:2024-11-02 14:26:50 瀏覽:990