首頁 > 軟體

android ndk 動態庫

2019-11-28 19:06:46

      android ndk開發經常遇到了動態庫的問題,本文主要介紹:

      ① 動態連結庫的生成;

      ② 在Java和C混合程式設計的情況下如何呼叫第三方動態連結庫;

      ③ 使用dlopen程式執行時直接呼叫;

      ④ 純c的方式開發呼叫;

      本文重點推薦②和④,第③中太麻煩每個函數都需要dlsym呼叫一次;

      程式碼的百度雲連結: http://pan.baidu.com/s/1dD3qkQ9 密碼:c5s3

1

android ndk下面生成動態庫so檔案的方法很多,但是這裡只提供一種方法,更多的生成方法可以看,「ndk 編譯靜態庫」:http://jingyan.baidu.com/article/63f236280b90690208ab3d12.html

2

fkAdd.c 的內容如下:#include <jni.h>int fkAdd(int nX, int nY){? ? ? returnnX + nY;}

3

Android.mk 的內容如下:LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE:= fkAddLOCAL_SRC_FILES:= fkAdd.cinclude $(BUILD_SHRRED_LIBRARY)

4

1、開啟 eclipse 

2、點選 檔案

3、點選 新建

4、點選 other...


5

1、展開 Android 選項;

2、選擇 Android Project from Existing Code;

3、點選 Next


6

1、輸入 Root Director;

2、取消 tests;

3、選中 Copy projects into workspace;

4、點選 Finish;


7

1、右鍵工程;

2、選擇 Android Tools;

3、Add Native Support...;


8

點選 Finish


9

修改android sdk 版本為 4.0.3;關於如何修改 android sdk 版本:http://jingyan.baidu.com/article/c910274bfdd000cd371d2d4b.html

10

修改 Min SDK version:15

修改 Target SDK version:19


11

在jni目錄下面新建檔案fkAdd.c 的內容如下:int fkAdd(int nX, int nY){? ? ? returnnX + nY;}

12

臨時修改 Android.mk 檔案內容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

#LOCAL_MODULE    := hello-jni

#LOCAL_SRC_FILES := hello-jni.c

LOCAL_MODULE    := fkaddso

LOCAL_SRC_FILES := fkAdd.c

include $(BUILD_SHARED_LIBRARY)


13

使用快捷鍵Ctrl+B編譯後可以在libs目錄下面看到生成的一些列的

libfkaddso.so檔案,如下圖所示


1

1、將libs複製一份到jni目錄下面,刪掉其中不相關的檔案

2、刪掉檔案 jni/fkadd.c 檔案

3、將 Android.mk 檔案還原成最開始的樣子;


2

修改 hello-jni.c 中的部分程式碼,如下:

char szMsg[1024] = {0};

int nSum = fkAdd(100, 10);

sprintf (szMsg, "Hello from JNI !  Compiled with ABI " ABI ". %d ",  nSum);

return (*env)->NewStringUTF(env, szMsg);


3

修改 Android.mk 檔案:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := fkaddso

LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libfkaddso.so

include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni

LOCAL_SRC_FILES := hello-jni.c

LOCAL_SHARED_LIBRARIES := fkaddso

include $(BUILD_SHARED_LIBRARY)


4

修改 HelloJni.java 在其中增加一行:

System.loadLibrary("fkaddso");


5

執行工程看效果:


1

重複「生成動態庫」中的過程1到10,

2

把需要呼叫so檔案的目錄libs拷貝到jni目錄下面,並修改 Android.mk 檔案的內容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := fkaddso

LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libfkaddso.so

include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni

LOCAL_SRC_FILES := hello-jni.c

include $(BUILD_SHARED_LIBRARY)


3

修改 hello-jni.c 的內容如下:

char*szSo = "/data/data/com.example.hellojni/lib/libfkaddso.so";

void* fkAddSo = dlopen(szSo, RTLD_LAZY);

int (*fpAdd)(int,int) =  (int (*)(int,int))dlsym(fkAddSo, "fkAdd");

char szMsg[1024] = {0};

int nSum = fpAdd(100, 200);

dlclose(fkAddSo);

sprintf (szMsg, "%s %d", szSo, nSum);

return (*env)->NewStringUTF(env, szMsg);


4

關於如何獲取 so在手機中的路徑,可以通過在控制台下輸入 adb shell 後,

在手機上查詢:


5

編譯後執行效果:


6

       方便他人亦是方便自己,如果覺得還行就點下下邊投票吧,這樣可以幫助其他人更快的找到解決問題的方法;有疑問的也可留言哦, 謝謝!


1

此方法需要感謝ndk吧的吧友提供哦,本人只是負責將其進行了整理,歸納後發帖,謝謝,原始地址:http://tieba.baidu.com/p/3247530080

2

根據「生成動態庫」中的過程1到10,新建一個純c的ndk程式:

「D:Androidandroid-ndk-r10samplesnative-activity"


3

把會用的so檔案的目錄libs拷貝到 jni目錄下面


4

修改 Android.mk 檔案,內容如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := fkAdd

LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libfkAdd.so

include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE    := main

LOCAL_SRC_FILES := main.c

LOCAL_LDLIBS    := -llog -landroid -lEGL -lGLESv1_CM

LOCAL_STATIC_LIBRARIES := android_native_app_glue

LOCAL_SHARED_LIBRARIES := fkAdd

include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE    := native-activity

LOCAL_SRC_FILES := NativeActivity.c

LOCAL_LDLIBS    := -llog -landroid

LOCAL_STATIC_LIBRARIES := android_native_app_glue

include $(BUILD_SHARED_LIBRARY)

$(call import-module,android/native_app_glue)


5

增加 NativeActivity.c 檔案,新增內容如下:

#include <jni.h>

#include <errno.h>

#include <dlfcn.h>

#include <android_native_app_glue.h>

void android_main(struct android_app* state) {

    // Make sure glue isn't stripped.

    app_dummy();

    void* soAdd = dlopen("/data/data/com.example.native_activity/

lib/libfkAdd.so",RTLD_NOW);

    void* soMain = dlopen("/data/data/com.example.native_activity/

lib/libmain.so",RTLD_NOW);

    void (*fp_android_main)(struct android_app*) =

    (void (*)(struct android_app*))dlsym(soMain,"android_main");

    fp_android_main(state);

    dlclose(soMain);

    dlclose(soAdd);

}


6

在 main.c 檔案中新增一行,方便測試:

__android_log_print(ANDROID_LOG_DEBUG, "fuke", "engine_handle_input 100 + 200 = [%d] ", fkAdd(100, 200));


7

編譯執行,點選手機螢幕後,觀察logcat 效果如下:



IT145.com E-mail:sddin#qq.com