Android游戲開發(fā)實(shí)踐(1)之NDK與JNI開發(fā)03

Android游戲開發(fā)實(shí)踐(1)之NDK與JNI開發(fā)03

前面已經(jīng)分享了兩篇有關(guān)Android平臺(tái)NDK與JNI開發(fā)相關(guān)的內(nèi)容免绿。以下列舉前面兩篇的鏈接地址葵姥,感興趣的可以再回顧下驶兜。那么刁岸,這篇繼續(xù)這個(gè)小專題塞颁,主要分享下AndroidStudio下的NDK與JNI開發(fā)的相關(guān)操作以及簡(jiǎn)述下CMake的使用走贪。最后,會(huì)以一個(gè)實(shí)例來(lái)結(jié)束這個(gè)小專題的分享缰盏,那個(gè)涌萤,就放在最后一篇吧。

傳送門:
Android游戲開發(fā)實(shí)踐(1)之NDK與JNI開發(fā)01
Android游戲開發(fā)實(shí)踐(1)之NDK與JNI開發(fā)02

本文的目錄如下:

  • 1口猜、環(huán)境搭建
  • 2形葬、創(chuàng)建一個(gè)支持C/C++的項(xiàng)目
    • 2.1 新建項(xiàng)目
    • 2.2 擴(kuò)展現(xiàn)有項(xiàng)目
  • 3、AndroidStudio與Gradle
    • 3.1 project/build.gradle
    • 3.2 project/settings.gradle
    • 3.3 module/build.gradle

<h3 id="get-start">1暮的、 環(huán)境搭建</h3>

要讓AndroidStudio支持NDK開發(fā)笙以,除了需安裝AndroidStudio2.2以上的版本。還得安裝NDK冻辩、CMake猖腕、LLDB等工具拆祈。
在AndroidStudio中選擇Tools->Android->SDK Manager->SDK Tools。如圖:

這里簡(jiǎn)單介紹下:
NDK:是Android開發(fā)本地C/C++代碼的一套工具集倘感。
CMake:一套跨平臺(tái)的構(gòu)建工具放坏,可以Gradle腳本配合使用來(lái)構(gòu)建你的本地庫(kù)。在AndroidStudio中老玛,Google默認(rèn)和推薦使用CMake進(jìn)行編譯淤年,當(dāng)然,你仍然可以繼續(xù)使用ndk-build來(lái)編譯你的本地代碼蜡豹。注意:32位的操作系統(tǒng)可能會(huì)裝不上麸粮。
LLDB: 一種調(diào)試器,Android Studio中可以使用它來(lái)調(diào)試本地代碼镜廉。

<h3 id="new-project">2弄诲、 創(chuàng)建一個(gè)支持C/C++的項(xiàng)目</h3>

這里所說的創(chuàng)建一個(gè)支持C/C++的項(xiàng)目,可以理解為創(chuàng)建一個(gè)NDK項(xiàng)目娇唯,但又包含兩種方式齐遵,分別是從零開始新建一個(gè)支持C/C++開發(fā)的項(xiàng)目和在原有項(xiàng)目的基礎(chǔ)上讓它支持C/C++開發(fā)。下面對(duì)這兩種方式分別進(jìn)行說明下塔插。

<h5 id="new-project1">2.1 新建項(xiàng)目</h5>

如果安裝好了梗摇,上面介紹的幾個(gè)工具(主要是NDK),并且AndroidStudio2.2以上的版本想许,新建項(xiàng)目的時(shí)候伶授,會(huì)看到這個(gè)選項(xiàng)。如圖:


創(chuàng)建項(xiàng)目時(shí)伸刃,勾選C++支持。


項(xiàng)目中所用的C++標(biāo)準(zhǔn)可以選擇默認(rèn)或者支持C++11逢倍,以及是否支持異常和rtti特性捧颅。


創(chuàng)建完項(xiàng)目,會(huì)比一般的Android項(xiàng)目多出cpp目錄以及CMakeLists.txt的文件较雕。


這里指定NDK的路徑碉哑。即,上面環(huán)境搭建里安裝的ndk亮蒋,會(huì)下載到AndroidStudio根目錄下的ndk-bundle文件夾中扣典。


make一下當(dāng)前新創(chuàng)建的工程,默認(rèn)會(huì)在build/cmake/debug/obj/下生成相應(yīng)的動(dòng)態(tài)庫(kù)慎玖。

<h5 id="new-project2">2.2 擴(kuò)展現(xiàn)有項(xiàng)目</h5>

要讓現(xiàn)有的Android項(xiàng)目能調(diào)用本地C/C++代碼或者支持C/C++開發(fā)贮尖,只需要在原來(lái)項(xiàng)目的基礎(chǔ)稍加修改即可。步驟如下:


切換到project視圖趁怔,打開module即上圖的app模塊湿硝,在src/main下右鍵New->Directory薪前,填寫一個(gè)文件名,例如:cpp关斜。


在剛建的cpp路徑下示括,右鍵New->C/C++ Source File,輸入文件名痢畜,若要一并生成相應(yīng)的.h文件垛膝,勾選Create an associated header選項(xiàng)即可。注意丁稀,后面可以指定源文件的后綴吼拥,例如:.cxx,.hxx


在module的根目錄即上圖的app根目錄二驰,右鍵New->File扔罪,輸入CMakeLists.txt。注意:文件名必須為CMakeLists.txt


在module的根目錄即上圖的app根目錄桶雀,選擇Link C++ Project with Gradle矿酵,然后,找到剛創(chuàng)建的CMakeLists.txt文件矗积。將CMakeLists.txt關(guān)聯(lián)到項(xiàng)目中全肮。注意,Build System仍可以選擇ndk-build方式進(jìn)行編譯棘捣。

當(dāng)然辜腺,這步操作也可以手動(dòng)完成,相當(dāng)于在當(dāng)前module下的build.gradle腳本中乍恐,添加了如下代碼评疗,

android {
    //指定使用CMake編譯----------------
    externalNativeBuild {
        cmake {
            path 'CMakeLists.txt'
        }
    }
    //--------------------------------
} 

打開新建的CMakeLists.txt文件,輸入如下代碼:

cmake_minimum_required (VERSION 3.4.1)

add_library (hellojni SHARED src/main/cpp/hellojni.cpp)

分別指定CMake要求的版本茵烈,add_library中參數(shù)分別是百匆,指定生成庫(kù)的名稱,生成庫(kù)的類型呜投,默認(rèn)是靜態(tài)塊加匈,即:·a,源碼的路徑仑荐。這里實(shí)例只簡(jiǎn)單介紹下CMake的用法雕拼,后續(xù)會(huì)有專門一篇來(lái)介紹下CMake更多高級(jí)的用法。

以上完畢粘招,在make一下當(dāng)前工程啥寇,或者rebuild一下,不出意外會(huì)在build/intermediates/cmake/debug路徑下生成各種libhellojni.so文件。

<h3 id="as-gradle">3示姿、AndroidStudio與Gradle</h3>

上面提到甜橱,將CMakeLists.txt關(guān)聯(lián)到項(xiàng)目中,會(huì)在build.gradle腳本中栈戳,添加一段代碼即可岂傲。可能剛接觸AndroidStudio(特別是使用其它IDE開發(fā)的子檀,例如:eclipse等)對(duì)Gradle不是很了解镊掖,這里就拋磚引玉下,簡(jiǎn)要講述下gradle腳本的使用褂痰。

首先亩进,AndroidStudio是基于IntelliJ IDEA的IDE,在AndroidStudio中新創(chuàng)建的Android工程都形如如下結(jié)構(gòu):

MyApp  
├── build.gradle  
├── settings.gradle  
└── app  
    ├── build.gradle  
    ├── build  
    ├── libs  
    └── src  
        └── main  
            ├── java  
            │   └── com.package.myapp  
            └── res  
                ├── drawable  
                ├── layout  
                └── etc.  

MyApp是項(xiàng)目名缩歪,app是模塊名归薛,一個(gè)項(xiàng)目下可以包含若干個(gè)模塊。這與eclipse的結(jié)構(gòu)不同匪蝙,對(duì)應(yīng)到eclipse中主籍,app就相當(dāng)于項(xiàng)目名,MyApp相當(dāng)于工作空間逛球∏г或者類似于VS中解決方案與項(xiàng)目的關(guān)系。以上目錄結(jié)構(gòu)關(guān)系颤绕,并不與實(shí)際磁盤上的目錄結(jié)構(gòu)對(duì)應(yīng)幸海。可以看到奥务,在項(xiàng)目根目錄下以及模塊目錄下物独,分別有三個(gè).gradle文件。下面氯葬,就分別介紹這三個(gè)gradle腳本的用途挡篓,當(dāng)然這里主要說的是在AndroidStudio下的gradle的相關(guān)使用。

在AndroidStudio中android項(xiàng)目是基于gradle進(jìn)行構(gòu)建的(eclipse中可以使用ant來(lái)做類似的工作)溢谤,而gradle是一種基于Groovy語(yǔ)言的DSL(domain-specific language瞻凤,領(lǐng)域?qū)S谜Z(yǔ)言)憨攒,而Groovy又是一種基于JVM的動(dòng)態(tài)語(yǔ)言世杀。所以,有java基礎(chǔ)的話肝集,理解Groovy會(huì)更容易瞻坝。有關(guān)Gradle文檔可以看看這個(gè):
https://docs.gradle.org/current/dsl/

<h5 id="project-build">3.1 project/build.gradle</h5>

該build.gradle位于項(xiàng)目的根目錄,該文件是定義在這個(gè)工程下的所有模塊的公共屬性。默認(rèn)如下:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.3'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

以下只是從表象說明下所刀,但實(shí)質(zhì)是Groovy相應(yīng)的數(shù)據(jù)結(jié)構(gòu)(閉包衙荐,Map等)調(diào)用相應(yīng)方法來(lái)動(dòng)態(tài)控制整個(gè)構(gòu)建過程。有關(guān)Groovy的討論可以看看3.3 module/build.gradle浮创。
buildscript:定義了全局的相關(guān)屬性忧吟。
repositories:定義了遠(yuǎn)程倉(cāng)庫(kù)的源,即代表你的依賴包的來(lái)源斩披。這里將jcenter()作為倉(cāng)庫(kù)溜族。
dependencies:定義了android gradle plugin的版本。
allprojects:可以用來(lái)定義各個(gè)模塊的默認(rèn)屬性垦沉,你可以不僅僅局限于默認(rèn)的配置煌抒,未來(lái)你可以自己創(chuàng)造tasks在allprojects方法體內(nèi),這些tasks將會(huì)在所有模塊中可見厕倍。
task clean:執(zhí)行相關(guān)的清理任務(wù)寡壮。

<h5 id="as-settings">3.2 project/settings.gradle</h5>

該文件位于項(xiàng)目根目錄下,也是項(xiàng)目的全局配置文件讹弯,該文件的內(nèi)容如下:

include ':app'

如果况既,你的項(xiàng)目中有多個(gè)模塊時(shí),可以依次添加到該文件中闸婴。例如:

include ':app',':librarys:Mylibrary'

即在項(xiàng)目根目錄下的librarys目錄里有個(gè)Mylibrary庫(kù)工程坏挠。

<h5 id="as-module">3.3 module/build.gradle</h5>

該文件位于當(dāng)前模塊的根目錄下,通常情況下邪乍,該文件只對(duì)當(dāng)前模塊起作用降狠。例如:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.2"
    defaultConfig {
        applicationId "com.alphagl.test"
        minSdkVersion 19
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    externalNativeBuild {
        cmake {
            path 'CMakeLists.txt'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:24.2.1'
}

以上內(nèi)容,要徹底弄清楚庇楞,得深究下Groovy語(yǔ)法榜配。這里,只淺析下。
apply plugin: 'com.android.application':在Groovy中的調(diào)用為project.apply([plugin: 'com.android.application'])畴博,plugin: 'com.android.application會(huì)被作為一個(gè)Map參數(shù)傳遞給apply的方法可很。這里是要將該模塊構(gòu)建為一個(gè)應(yīng)用,若要將模塊構(gòu)建庫(kù)形式烙心,可以傳參為plugin: 'com.android.library

在Groovy中花括號(hào)包含的部分稱為一個(gè)閉包(Closure)乏沸。上面的主要兩部分androiddependencies淫茵,分別對(duì)應(yīng)project中的方法,而參數(shù)是相應(yīng)的閉包結(jié)構(gòu)蹬跃。通過上面的結(jié)構(gòu)匙瘪,可以知道該閉包結(jié)構(gòu)還有閉包嵌套和相應(yīng)的方法。
android:該方法包含了所有的Android屬性,而唯一必須包含屬性為compileSdkVersion和buildToolsVersion丹喻。
compileSdkVersion:該方法包含編譯該app時(shí)候薄货,使用到的api版本。
buildToolsVersion:該方法包含構(gòu)建工具的版本號(hào)碍论。
defaultConfig:該方法包含app的核心屬性谅猾,該屬性會(huì)覆蓋在AndroidManifest.xml中的對(duì)應(yīng)屬性。
applicationId:該方法定義的屬性會(huì)覆蓋AndroidManifest文件中的包名package name屬性鳍悠。
minSdkVersion:該方法定義的屬性表示最小支持api版本赊瞬。同AndroidManifest中對(duì)應(yīng)的屬性。
targetSdkVersion:該方法定義的屬性表示目標(biāo)平臺(tái)api版本贼涩。同AndroidManifest中對(duì)應(yīng)的屬性巧涧。
buildTypes:該方法定義了構(gòu)建不同版本的app相關(guān)的屬性。
release:配置release版本相關(guān)的屬性遥倦。
minifyEnabled:是否進(jìn)行混淆谤绳。
proguardFiles:定義混淆文件的位置。通過getDefaultProguardFile方法獲取袒哥。
externalNativeBuild:native使用cmake編譯缩筛。
dependencies:gradle默認(rèn)的屬性之一,定義了所有的依賴包堡称。
compile:編譯相應(yīng)依賴的jar包瞎抛。組織名,包名却紧,版本號(hào)的結(jié)構(gòu)桐臊。

以上只簡(jiǎn)單的列舉了下部分屬性,對(duì)gradle腳本有初步的了解晓殊。當(dāng)然断凶,Groovy在java領(lǐng)域還是有很多應(yīng)用的。感興趣的巫俺,可以深入了解下认烁。

Groovy文檔:
Groovy-Documentation

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市介汹,隨后出現(xiàn)的幾起案子却嗡,更是在濱河造成了極大的恐慌,老刑警劉巖嘹承,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窗价,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡赶撰,警方通過查閱死者的電腦和手機(jī)舌镶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)豪娜,“玉大人餐胀,你說我怎么就攤上這事×鲈兀” “怎么了否灾?”我有些...
    開封第一講書人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)鸣奔。 經(jīng)常有香客問我墨技,道長(zhǎng),這世上最難降的妖魔是什么挎狸? 我笑而不...
    開封第一講書人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任扣汪,我火速辦了婚禮,結(jié)果婚禮上锨匆,老公的妹妹穿的比我還像新娘崭别。我一直安慰自己,他們只是感情好恐锣,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開白布茅主。 她就那樣靜靜地躺著,像睡著了一般土榴。 火紅的嫁衣襯著肌膚如雪诀姚。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評(píng)論 1 285
  • 那天玷禽,我揣著相機(jī)與錄音赫段,去河邊找鬼。 笑死矢赁,一個(gè)胖子當(dāng)著我的面吹牛瑞佩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播坯台,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼炬丸,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蜒蕾?” 一聲冷哼從身側(cè)響起稠炬,我...
    開封第一講書人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎咪啡,沒想到半個(gè)月后首启,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡撤摸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年毅桃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了褒纲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡钥飞,死狀恐怖莺掠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情读宙,我是刑警寧澤彻秆,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站结闸,受9級(jí)特大地震影響唇兑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜桦锄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一扎附、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧结耀,春花似錦帕棉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)具则。三九已至即纲,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間博肋,已是汗流浹背低斋。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留匪凡,地道東北人膊畴。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像病游,于是被迫代替她去往敵國(guó)和親唇跨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

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