NDK項(xiàng)目的簡(jiǎn)單構(gòu)建

基本概念

JNI

  • Java Native Interface纲菌,Java本地接口试疙。

  • 是為了方便Java調(diào)用C柳弄、C++等本地代碼所封裝的一層接口唱捣。

NDK

  • Android提供的一個(gè)工具集合两蟀,更加方便地在Android中實(shí)現(xiàn)JNI。

  • NDK提供了交叉編譯器震缭,開發(fā)人員可將JNI代碼生成各指定CPU平臺(tái)的動(dòng)態(tài)庫赂毯。

加載本地庫

  • Java代碼中通過System.loadLibrary("library-name")來導(dǎo)入本地庫。

  • 注意此處的library-name是本地庫的名字拣宰,不用包含后綴党涕,Java將根據(jù)當(dāng)前系統(tǒng)的類型自動(dòng)擴(kuò)展后綴名,如Linux擴(kuò)展成.so巡社,Windows擴(kuò)展成.dll遣鼓。

  • 若要導(dǎo)入Linux下的libxxx.so,只要寫System.loadLibrary("xxx")即可重贺。

Native方法

  • 定義Native方法有兩種方式

    1. 函數(shù)命名規(guī)則來匹配和映射;

    2. 運(yùn)行時(shí)動(dòng)態(tài)注冊(cè)(RegisterNatives)。

Java類中聲明native方法

  • 在開發(fā)Native方法前气笙,先創(chuàng)建一個(gè)Java類次企,在此類中聲明與Native方法對(duì)應(yīng)的Java本地方法。
package com.daking.jni;
    
public class JNIUtil {
    static {
        System.loadLibrary("nativecode"); // 加載libnativecode.so
    }
    public static native String getLibName();
}

1. 函數(shù)命名規(guī)則來匹配和映射Native方法

  • 匹配和映射Native方法的c函數(shù)命名規(guī)則為:
JNIEXPORT 返回類型 JNICALL Java_{packageName}_{className}_{functionName}(jni參數(shù)列表);
  • 上面的Java類聲明的native方法對(duì)應(yīng)的c函數(shù)為:
JNIEXPORT jstring JNICALL Java_com_daking_jni_JNIUtil_getLibName(JNIEnv* env, jobject obj);
  • 該c函數(shù)的特點(diǎn)是:

    返回類型為jstring等JNI類型潜圃;

    將{packageName}中的.全部改為_缸棵。

    JNI方法的形參列表至少有以下兩個(gè)參數(shù):

    1. JNIEnv* env:JNI環(huán)境的引用,用env可調(diào)用所有JNI提供的函數(shù)谭期;
    1. jobject obj:調(diào)用該函數(shù)的對(duì)象的引用堵第。

2. 運(yùn)行時(shí)動(dòng)態(tài)注冊(cè)Native方法

  • 運(yùn)行時(shí)動(dòng)態(tài)注冊(cè)的方式簡(jiǎn)化了函數(shù)名稱,并且可以動(dòng)態(tài)地更新映射關(guān)系隧出。

  • 首先踏志,在C代碼中實(shí)現(xiàn)各Native方法。

jstring getLibName(JNIEnv* env, jobject obj) {
    return (*env)->NewStringUTF(env, "hello world!");
}
  • 接著胀瞪,創(chuàng)建JNINativeMethod數(shù)組针余。
static JNINativeMethod jniMethods[] = {
    {"getLibName", "()Ljava/lang/String;", (void*)getLibName}
    // 其他Java本地方法與C Native方法的映射...
};
  • 此處的JNINativeMethod結(jié)構(gòu)有三個(gè)成員:

    1. const char* name:Java中聲明的native方法名
    1. const char* signature:native方法的簽名
    1. void* fnPtr:c函數(shù)指針
  • 最后,在JNI_OnLoad中調(diào)用RegisterNatives()注冊(cè)各Native方法到JVM凄诞,建立映射關(guān)系圆雁。

static const char* className = "com/daking/jni/JNIUtil";
    
int JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env;
    if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_4) != JNI_OK) {
        return JNI_ERR;
    }
    
    jclass cls = (*env)->FindClass(env, className);
    if (cls == NULL)
        return JNI_ERR;
        
    int len = sizeof(jniMethods) / sizeof(jniMethods[0]);
    (*env)->RegisterNatives(env, cls, jniMethods, len);
    
    return JNI_VERSION_1_4;
}

NDK Sample Project

1. 創(chuàng)建Android項(xiàng)目

  • Android項(xiàng)目中創(chuàng)建JNIUtil類,作為調(diào)用JNI的入口工具類帆谍。
package com.daking.jni;
    
public class JNIUtil {
    static {
        System.loadLibrary("nativecode");
    }
    public static native String getLibName();
}

2. 創(chuàng)建JNI項(xiàng)目

  • JNI項(xiàng)目的目錄結(jié)構(gòu)如下:
JNIDemo
├── jni
│   ├── Android.mk
│   ├── Application.mk
│   ├── include
│   │   └── api.h
│   └── src
│       └── api.c
  • api.h文件內(nèi)容如下:
#include <jni.h>
#ifndef NATIVECODE_API_H
#define NATIVECODE_API_H
        
#ifdef __cplusplus
extern "C" {
#endif
        
JNIEXPORT jstring JNICALL
Java_com_daking_jni_JNIUtil_getLibName(JNIEnv*, jobject);
        
#ifdef __cplusplus
}
#endif
#endif //NATIVECODE_API_H
  • api.c文件內(nèi)容如下:
#include "api.h"
#include <stdio.h>
        
JNIEXPORT jstring JNICALL
Java_com_daking_recyclerdemo_jni_getLibName(JNIEnv* env, jobject thiz) {
    return (*env)->NewStringUTF(env, "libnativecode.so");
}
  • Android.mk文件內(nèi)容如下:
LOCAL_PATH := $(call my-dir)
        
include $(CLEAR_VARS)
        
LOCAL_MODULE := nativecode
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_SRC_FILES := ./src/api.c
include $(BUILD_SHARED_LIBRARY)
  • Application.mk文件內(nèi)容如下:
APP_ABI := armeabi
  • 在JNI項(xiàng)目中與jni子目錄同級(jí)的路徑下伪朽,執(zhí)行ndk-build,生成so庫汛蝙。

3. Android項(xiàng)目引用so庫

  • 將JNI項(xiàng)目生成的so庫放到Android項(xiàng)目/app/src/main/jniLibs/<abi>下即可烈涮。

  • <abi>有armeabi、armeabi-v7a患雇、arm64-v8a跃脊、x86、x86_64苛吱、mips酪术、mips64。

我的博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末翠储,一起剝皮案震驚了整個(gè)濱河市绘雁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌援所,老刑警劉巖庐舟,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異住拭,居然都是意外死亡挪略,警方通過查閱死者的電腦和手機(jī)历帚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來杠娱,“玉大人挽牢,你說我怎么就攤上這事√螅” “怎么了禽拔?”我有些...
    開封第一講書人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長室叉。 經(jīng)常有香客問我睹栖,道長,這世上最難降的妖魔是什么茧痕? 我笑而不...
    開封第一講書人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任野来,我火速辦了婚禮,結(jié)果婚禮上凿渊,老公的妹妹穿的比我還像新娘梁只。我一直安慰自己,他們只是感情好埃脏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開白布搪锣。 她就那樣靜靜地躺著,像睡著了一般彩掐。 火紅的嫁衣襯著肌膚如雪构舟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,521評(píng)論 1 304
  • 那天堵幽,我揣著相機(jī)與錄音狗超,去河邊找鬼。 笑死朴下,一個(gè)胖子當(dāng)著我的面吹牛努咐,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播殴胧,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼渗稍,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了团滥?” 一聲冷哼從身側(cè)響起竿屹,我...
    開封第一講書人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎灸姊,沒想到半個(gè)月后拱燃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡力惯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年碗誉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了召嘶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡哮缺,死狀恐怖苍蔬,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蝴蜓,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布俺猿,位于F島的核電站茎匠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏押袍。R本人自食惡果不足惜诵冒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谊惭。 院中可真熱鬧汽馋,春花似錦、人聲如沸圈盔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽驱敲。三九已至铁蹈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間众眨,已是汗流浹背握牧。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留娩梨,地道東北人沿腰。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像狈定,于是被迫代替她去往敵國和親颂龙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,130評(píng)論 25 707
  • Android跨進(jìn)程通信IPC整體內(nèi)容如下 1掸冤、Android跨進(jìn)程通信IPC之1——Linux基礎(chǔ)2厘托、Andro...
    隔壁老李頭閱讀 11,533評(píng)論 1 46
  • 一、NDK產(chǎn)生的背景 Android平臺(tái)從誕生起稿湿,就已經(jīng)支持C铅匹、C++開發(fā)。眾所周知饺藤,Android的SDK基于J...
    Ten_Minutes閱讀 3,502評(píng)論 1 27
  • *** 說明:本文不代表博主觀點(diǎn)包斑,均是由以下資料整理的讀書筆記流礁。 *** 【參考資料】 1、向您的Android ...
    莫緒旻_向嶼閱讀 1,681評(píng)論 0 6
  • 又是一個(gè)雨天 雨落如煙幕般看不清真實(shí) 我撐著傘繞著你轉(zhuǎn) 商場(chǎng)罗丰、食店神帅、路邊 這秋天的風(fēng)雨里 我想即便是冬天 也不覺寒...
    f74d6afb74d6閱讀 155評(píng)論 0 0