小白windows編譯android的so庫

一般我們開發(fā)主要是使用Java,但項(xiàng)目中有些涉及到復(fù)雜的算法或耗時(shí)操作時(shí),通常使用C/C++完成算法實(shí)現(xiàn)并提供給java層(通過JNI)調(diào)用,以此提高運(yùn)行的效率。這種情況下,C/C++所實(shí)現(xiàn)的代碼以及JNI調(diào)用相關(guān)的代碼被打包為.so庫。
筆者在項(xiàng)目中遇到了需要使用JNI調(diào)用c++算法的情況,之前也沒有相關(guān)的經(jīng)驗(yàn),折騰了一番之后終于跑通,故整理一下整個(gè)過程。

本文以一個(gè)加法運(yùn)算的簡單功能為例,說明如何使用JNI開發(fā)。

環(huán)境、工具的準(zhǔn)備

1、系統(tǒng)環(huán)境:windows x10

2、工具:1)android studio 或者 eclipse;2)android-ndk-r10b

3、搭建:筆者因?yàn)橐延衋ndroid studio開發(fā)的環(huán)境,所以只需要搭建NDK環(huán)境。
1)Android官網(wǎng)下載NDK;
2)解壓縮下載的ziP包到某個(gè)目錄,例如 D:\android-ndk-r10b;
3)配置添加環(huán)境變量 NDK_ROOT 為: D:\android-ndk-r10b, 在環(huán)境變量 PATH 下追加 :%NDK_ROOT%;
4)驗(yàn)證ndk安裝是否成功:cmd進(jìn)入安裝ndk的目錄,找到D:\android-ndk-r10b\samples\hello-jni目錄,運(yùn)行ndk-build 命令,出現(xiàn)以下結(jié)果就表明環(huán)境安裝成功

SO庫編寫

先看一下整個(gè)工程的目錄,先說明一點(diǎn),標(biāo)紅的命名需要一致。接下來就可以講述整個(gè)過程的實(shí)現(xiàn)了

1、生成.h頭文件
打開android studio,新建android項(xiàng)目JniTestApp,creat 一個(gè)package com.yxq.jnitestapp.add,建一個(gè)類AddUtil

AddUtil.java

package com.yxq.jnitestapp.add;

/**
 * Created by yxq on 2016/12/15.
 */
public class AddUtil {

    public static native int  add(int addend,int summand);

    static {
        System.loadLibrary("addLib");
    }
}

cmd進(jìn)入JniTestApp工程所在的java目錄, 用 Javac 編譯成 AddUtil .java文件成class文件,再用javah編譯生成.h文件

.h文件具體內(nèi)容

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_yxq_jnitestapp_add_AddUtil */

#ifndef _Included_com_yxq_jnitestapp_add_AddUtil
#define _Included_com_yxq_jnitestapp_add_AddUtil
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_yxq_jnitestapp_add_AddUtil
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_yxq_jnitestapp_add_AddUtil_add
  (JNIEnv *, jobject, jint, jint);

#ifdef __cplusplus
}
#endif
#endif

2、編寫.c文件

在JniTestApp的app\src\main目錄下新建一個(gè)文件夾jni,將第一步生成的com_yxq_jnitestapp_add_AddUtil.h文件拷貝至jni文件夾, 新建一個(gè)文件com_yxq_jnitestapp_add_AddUtil.c文件,c文件是源碼文件,實(shí)現(xiàn)了此項(xiàng)目核心功能add。

#include <jni.h>

#include "com_yxq_jnitestapp_add_AddUtil.h"

JNIEXPORT jint JNICALL Java_com_yxq_jnitestapp_add_AddUtil_add
  (JNIEnv *env, jobject obj, jint addend, jint summand){
  return add(addend, summand);
}

int add(int addend, int summand){
  return addend + summand;
}

3、編寫Android.mk文件

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE     := addLib
LOCAL_SRC_FILES  := com_yxq_jnitestapp_add_AddUtil.c
include $(BUILD_SHARED_LIBRARY)

4、編譯

cmd進(jìn)入工程所在的main目錄,執(zhí)行命令 ndk-build,就完成了。

完成后,刪除多余的文件,并將生成armeabi文件夾移動(dòng)到j(luò)niLibs目錄下面,然后就可以在Java工程中調(diào)用了。

遇到的問題和注意事項(xiàng)

1、可能會(huì)遇到如下問題,原因是工程的路徑有空格,NDK編譯無法通過,解決方案是將整個(gè)工程換一個(gè)目錄,比如換到D:\Android\workspace\JniTestApp>

D:\Program Files\Android\workspace\JniTestApp>ndk-build
Android NDK: Your Android application project path contains spaces: 'D:/ Files/Android/workspace/'
Android NDK: The Android NDK build cannot work here. Please move your project to a different location.
D:\android-ndk-r10b\build/core/build-local.mk:155: *** Android NDK: Aborting.    .  Stop.

2、可能會(huì)遇到如下問題,找到不庫,解決方法是生成的lib庫需要放到j(luò)niLibs目錄下面才能調(diào)用成功,

 Process: com.yxq.jnitestapp, PID: 19527
    java.lang.UnsatisfiedLinkError: Couldn't load addLib from loader dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.yxq.jnitestapp-4.apk"],nativeLibraryDirectories=[/data/app-lib/com.yxq.jnitestapp-4, /vendor/lib, /system/lib]]]: findLibrary returned null
            at java.lang.Runtime.loadLibrary(Runtime.java:358)
            at java.lang.System.loadLibrary(System.java:526)
            at com.yxq.jnitestapp.add.AddUtil.<clinit>(AddUtil.java:11)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容