Android Studio工程目錄結(jié)構(gòu)及簡(jiǎn)單使用

1.Android Studio安裝

下載地址:https://developer.android.google.cn/studio/
android studio安裝完后要在安裝jdk(1.8)和sdk版本(24)

2.目錄分析

榕樹(shù)目錄結(jié)構(gòu).png

1、.gradle gradle編譯系統(tǒng),版本由wrapper決定
.idea AndroidStudio IDE所需要的文件 IntelliJ IDEA 同樣有這個(gè)文件
這兩個(gè)目錄下文件都是Android Studio 自動(dòng)生成的一些文件,我們無(wú)需關(guān)心,也不要手動(dòng)去編輯
2、app app項(xiàng)目的代碼、資源等內(nèi)容幾乎都是放在這個(gè)目錄下,我們后期的開(kāi)發(fā)也基本都是在這個(gè)目錄下進(jìn)行
3、build build代碼編譯后生成的文件存放的位置
4、gradle wrapper的jar和配置文件所在位置,這個(gè)目錄下包含了gradle wrapper的配置文件使用gradle wrapper的方式不需要提前將gradle下載好,而是會(huì)自動(dòng)根據(jù)vending的緩存情況決定是否需要聯(lián)網(wǎng)下載gradle
5、.gitgnore git使用的ignore文件 這個(gè)文件是用來(lái)將指定的目錄或者文件排除在版本控制之外的
6、build.gradle gradle編譯的相關(guān)配置文件,這是項(xiàng)目全局的gradle構(gòu)建腳本,通常這個(gè)文件中的內(nèi)容是不需要修改的
7、gradle.properties gradle相關(guān)的全局屬性設(shè)置,這個(gè)文件是全局的gradle配置文件,在這里配置的屬性將會(huì)影響到項(xiàng)目中所有的gradle編譯腳本
8、gradlew Unix下的gradle wrapper 可執(zhí)行文件
gradlew.bat windows下的gradle wrapper 可執(zhí)行文件
這兩個(gè)文件是用來(lái)在命令行界面中執(zhí)行g(shù)radle命令的,其中g(shù)radlew是在Linux或者M(jìn)ac系統(tǒng)使用的,gradle是windows下使用的
9、項(xiàng)目名.iml iml文件是所有Android Studio項(xiàng)目自動(dòng)生成的文件,我們不需要關(guān)心或者修改這個(gè)文件的內(nèi)容
10、local.projecties 本地屬性設(shè)置(key設(shè)置,android ndk sdk 位置等屬性),這個(gè)文件是不推薦上傳到VCS中去的
11、settings.gradle 這個(gè)文件用于指定項(xiàng)目中所有引入的模塊。

3.app目錄分析

build 編譯后的文件存在的位置(包括最終生成的apk也在這里面)
libs 依賴的庫(kù)所在的位置(jar和aar)
src 源代碼所在的目錄
src/main 主要代碼所在位置
src/main/assets android中附帶的一些文件
src/main/java java代碼所在的位置
src/main/jniLibs jni的一些動(dòng)態(tài)庫(kù)所在的默認(rèn)位置(.so文件)
src/main/res android資源文件的所在位置
src/main/AndroidManifest.xml 清單文件
build.gradle 和這個(gè)項(xiàng)目有關(guān)的gradle配置,相當(dāng)于這個(gè)項(xiàng)目的Makefile,一些項(xiàng)目的依賴就寫(xiě)在這里
proguard.pro 代碼混淆配置文件

4.gradle

build.gradle(Project).png

1.buildscript
buildscript中的聲明是gradle腳本自身需要使用的資源??梢月暶鞯馁Y源包括依賴項(xiàng)、第三方插件、maven倉(cāng)庫(kù)地址等
2.repositories
顧名思義就是倉(cāng)庫(kù)的意思啦,而jcenter()、maven()和google()就是托管第三方插件的平臺(tái)
3.dependencies
當(dāng)然配置了倉(cāng)庫(kù)還不夠,我們還需要在dependencies{}里面的配置里,把需要配置的依賴用classpath配置上,因?yàn)檫@個(gè)dependencies在buildscript{}里面,所以代表的是Gradle需要的插件。
4.allprojects
allprojects塊的repositories用于多項(xiàng)目構(gòu)建,為所有項(xiàng)目提供共同所需依賴包。而子項(xiàng)目可以配置自己的repositories以獲取自己獨(dú)需的依賴包。
5.buildscript和allprojects的作用和區(qū)別
buildscript中的聲明是gradle腳本自身需要使用的資源,而allprojects聲明的卻是你所有module所需要使用的資源,就是說(shuō)每個(gè)module都需要用同一個(gè)第三庫(kù)的時(shí)候,你可以在allprojects里面聲明
6.task clean
運(yùn)行g(shù)radle clean時(shí),執(zhí)行此處定義的task。該任務(wù)繼承自Delete,刪除根目錄中的build目錄。相當(dāng)于執(zhí)行Delete.delete(rootProject.buildDir)。其實(shí)這個(gè)任務(wù)的執(zhí)行就是可以刪除生成的Build文件的,跟Android Studio的clean是一個(gè)道理。

build.gradle(Moudle).png

1.android{}
是Android插件提供的一個(gè)擴(kuò)展類型,可以讓我們自定義Android Gradle工程,是Android Gradle工程配置的唯一入口。
2.compileSdkVersion
是編譯所依賴的Android SDK的版本,這里是API Level。
3.buildToolsVersion
是構(gòu)建該Android工程所用構(gòu)建工具的版本。
4.defaultConfig{}
defaultConfig是默認(rèn)的配置,它是一個(gè)ProductFlavor。ProductFlavor允許我們根據(jù)不同的情況同時(shí)生成多個(gè)不同的apk包。
5.applicationId
配置我們的包名,包名是app的唯一標(biāo)識(shí),其實(shí)他跟AndroidManifest里面的package是可以不同的,他們之間并沒(méi)有直接的關(guān)系。
package指的是代碼目錄下路徑;applicationId指的是app對(duì)外發(fā)布的唯一標(biāo)識(shí),會(huì)在簽名、申請(qǐng)第三方庫(kù)、發(fā)布時(shí)候用到。
6.minSdkVersion
是支持的Android系統(tǒng)的api level,這里是15,也就是說(shuō)低于Android 15版本的機(jī)型不能使用這個(gè)app。
7.targetSdkVersion
表明我們是基于哪個(gè)Android版本開(kāi)發(fā)的,這里是22。
8.versionName
表明我們的app應(yīng)用的版本名稱,一般是發(fā)布的時(shí)候?qū)懺赼pp上告訴用戶的
9.versionCode
表明我們的app應(yīng)用的版本,一般app升級(jí)基于versionCode(應(yīng)用市場(chǎng))
10.multiDexEnabled
用于配置該BuildType是否啟用自動(dòng)拆分多個(gè)Dex的功能。一般用程序中代碼太多,超過(guò)了65535個(gè)方法的時(shí)候。
11.ndk{}
多平臺(tái)編譯,生成有so包的時(shí)候使用,包括四個(gè)平臺(tái)'armeabi', 'x86', 'armeabi-v7a', 'mips'。一般使用第三方提供的SDK的時(shí)候,可能會(huì)附帶so庫(kù)。
12.manifestPlaceholders
占位符,我們可以通過(guò)它動(dòng)態(tài)配置AndroidManifest文件一些內(nèi)容

builde(module).png

13.buildType
構(gòu)建類型,在Android Gradle工程中,它已經(jīng)幫我們內(nèi)置了debug和release兩個(gè)構(gòu)建類型,兩種模式主要車別在于,能否在設(shè)備上調(diào)試以及簽名不一樣,其他代碼和文件資源都是一樣的。一般用在代碼混淆,而指定的混淆文件在下圖的目錄上,minifyEnabled=true就會(huì)開(kāi)啟混淆,shrinkResources=true 縮小APK大小,刪除沒(méi)有引用的資源文件(drawable和layout)

image.png

14.signingConfigs
簽名配置,一個(gè)app只有在簽名之后才能被發(fā)布、安裝、使用,簽名是保護(hù)app的方式,標(biāo)記該app的唯一性。如果app被惡意刪改,簽名就不一樣了,無(wú)法升級(jí)安裝,一定程度保護(hù)了我們的app。而signingConfigs就很方便為我們提供這個(gè)簽名的配置。storeFile簽名文件,storePassword簽名證書(shū)文件的密碼,storeType簽名證書(shū)類型,keyAlias簽名證書(shū)中秘鑰別名,keyPassword簽名證書(shū)中改密鑰的密碼。
默認(rèn)情況下,debug模式的簽名已經(jīng)被配置好了,使用的就是Android SDK自動(dòng)生成的debug證書(shū),它一般位于$HOME/.android/debug.keystore,其key和密碼是已經(jīng)知道的,一般情況下我們不需要單獨(dú)配置debug模式的簽名信息。
15.productFlavors
Gradle的多渠道打包,你可以在不同的包定義不同的變量,實(shí)現(xiàn)自己的定制化版本的需求。
buildConfigField是BuildConfig文件的一個(gè)函數(shù),而B(niǎo)uildConfig這個(gè)類是Android Gradle構(gòu)建腳本在編譯后生成的
image.png

image.png

16.dependencies{}
我們平時(shí)用的最多的大概就這個(gè)了,
首先第一句compile fileTree(include: ['.jar'], dir: 'libs')*,這樣配置之后本地libs文件夾下的擴(kuò)展名為jar的都會(huì)被依賴,非常方便。
如果你要引入某個(gè)本地module的話,那么需要用compile project('×××')。
如果要引入網(wǎng)上倉(cāng)庫(kù)里面的依賴,我們需要這樣寫(xiě)compile group:'com.squareup.okhttp3',name:'okhttp',version:'3.1.0',當(dāng)然這樣是最完整的版本,縮寫(xiě)就把group、name、version去掉,然后以":"分割即可。
compile 'com.squareup.okhttp3:okhttp:3.1.0'
但是到了gradle3.0以后build.gradle中的依賴默認(rèn)為implementation,而不是
之前的compile。另外,還有依賴指令api。
gradle 3.0中其實(shí)api跟以前的compile沒(méi)什么區(qū)別,將compile全部改成api是不會(huì)錯(cuò)的;而implementation指令依賴是不會(huì)傳遞的,也就是說(shuō)當(dāng)前引用的第三方庫(kù)僅限于本module內(nèi)使用,其他module需要重新添加依賴才能用

5.文件編譯及打包

Make Project:編譯Project下所有Module,一般是自上次編譯后Project下有更新的文件,不生成apk。
Clean Project:刪除之前編譯后的編譯文件,并重新編譯整個(gè)Project,比較花費(fèi)時(shí)間,不生成apk。
Rebuild Project:先執(zhí)行Clean操作,刪除之前編譯的編譯文件和可執(zhí)行文件,然后重新編譯新的編譯文件,不生成apk,這里效果其實(shí)跟Clean Project是一致的,這個(gè)不知道Google搞什么鬼~~
Build APK:前面4個(gè)選項(xiàng)都是編譯,沒(méi)有生成apk文件,如果想生成apk,需要點(diǎn)擊Build APK。
Generate Signed APK:生成有簽名的apk。
打包過(guò)程
不管使用什么IDE,Android 打包生成Apk主要都是由以下幾步完成:

1、根據(jù)資源文件和AndroidManifest.xml生成R.java文件

2、處理aidl,生成對(duì)應(yīng)的java文件,如果沒(méi)有aidl,則跳過(guò)

3、編譯工程源碼(主項(xiàng)目,庫(kù))src目錄下所有的源碼,同時(shí)上邊生成的R.java和aidl生成的java文件也會(huì)被編譯生成相應(yīng)的class文件

4、將第3步生成的class文件打包生成.dex文件

5、將資源文件打包,生成初始的apk

6、將第4步生成的.dex文件加入到apk中生成未簽名的包

7、apk簽名

一、生成R.java
R.java對(duì)于Android開(kāi)發(fā)同學(xué),肯定非常熟悉,它是一個(gè)非常重要的一個(gè)類,并且它是自動(dòng)生成的,主要是包含了res目錄下所有資源的ID,我們可以在程序中通過(guò)它來(lái)獲取資源ID,然后通過(guò)Android Api來(lái)獲取具體的資源。
TextView tv = (TextView) findViewById(R.id.tv_text);
tv.setText(R.string.app_name);
R.java是由SDK中提供的aapt(sdk/build-tools/ 中對(duì)應(yīng)的版本下,本文使用的26.0.2,那么具體的路徑就是sdk/build-tools/26.0.2)工具生成的。
二、javac 編譯所有java文件
這一步其實(shí)就是使用jdk的javac將項(xiàng)目中所有的java文件編譯成class文件。
三、打包生成.dex文件
dex文件是Android虛擬機(jī)可運(yùn)行文件,可以使用dx工具生成。
dx工具會(huì)將上一步app/src/main/build/中生成的class文件全部打包,得到classes.dex,apk包中包含的classes.dex就是這樣生成的,當(dāng)然實(shí)際項(xiàng)目可能類會(huì)很多,但是過(guò)程是一樣的。
有了classes.dex,開(kāi)始要打包apk了
四、打包資源文件
apk包中的資源文件都是經(jīng)過(guò)編譯過(guò)的,是二進(jìn)制文件。我們還是使用aapt工具:
將AndroidManifest.xml與res目錄除了assets目錄以為的文件進(jìn)行編譯,生成resource.arsc和若干二進(jìn)制的xml文件。
資源ID和資源文件的對(duì)應(yīng)關(guān)系都是在resource.arsc中的。這些文件都會(huì)被打包到res.apk中。
五、將.dex打包到apk
直接使用apkbuilder的實(shí)現(xiàn)類,該類是sdk/tools/lib/sdklib.jar文件中的
com.android.sdklib.build.ApkBuilderMain
如果沒(méi)有出錯(cuò),會(huì)在out目錄下得到app.apk,解壓后可以看到classes文件以及被打進(jìn)去了。
到此,已經(jīng)得到了未簽名的apk,剩下的就是apk簽名了。
六、簽名apk
apk用安裝必須要簽名,我們使用jarsigner給apk手動(dòng)簽名

APK文件結(jié)構(gòu)和安裝過(guò)程
APK文件結(jié)構(gòu)
Android應(yīng)用是用Java編寫(xiě)的,利用Android SDK編譯代碼,并且把所有的數(shù)據(jù)和資源文件打包成一個(gè)APK (Android Package)文件,這是一個(gè)后綴名為.apk的壓縮文件,APK文件中包含了一個(gè)Android應(yīng)用程序的所有內(nèi)容,是Android平臺(tái)用于安裝應(yīng)用程序的文件。APK就是一個(gè)zip壓縮包,解開(kāi)這個(gè)APK包我們可以看到以下的結(jié)構(gòu):

image
  1.   assets目錄:用于存放需要打包到APK中的靜態(tài)文件,和res的不同點(diǎn)在于,assets目錄支持任意深度的子目錄,用戶可以根據(jù)自己的需求任意部署文件夾架構(gòu),而且res目錄下的文件會(huì)在.R文件中生成對(duì)應(yīng)的資源ID,assets不會(huì)自動(dòng)生成對(duì)應(yīng)的ID,訪問(wèn)的時(shí)候需要AssetManager類。
    
    
  2.   lib目錄:這里存放應(yīng)用程序依賴的native庫(kù)文件,一般是用C/C++編寫(xiě),這里的lib庫(kù)可能包含4中不同類型,根據(jù)CPU型號(hào)的不同,大體可以分為ARM,ARM-v7a,MIPS,X86,分別對(duì)應(yīng)著ARM架構(gòu),ARM-V7架構(gòu),MIPS架構(gòu)和X86架構(gòu),這些so庫(kù)在APK包中的構(gòu)成如下圖Figure2:
    
    
image

其中,不同的CPU架構(gòu)對(duì)應(yīng)著不同的目錄,每個(gè)目錄中可以放很多對(duì)應(yīng)版本的so庫(kù),且這個(gè)目錄的結(jié)構(gòu)固定,用戶只能按照這個(gè)目錄存放自己的so庫(kù)。目前市場(chǎng)上使用的移動(dòng)終端大多是基于ARM或者ARM-V7a架構(gòu)的,X86和MIPS架構(gòu)的移動(dòng)智能終端比較少,所以有些應(yīng)用程序lib目錄下只包含armeabi目錄或者armeabi-v7a目錄,也就是說(shuō),這四個(gè)目錄要根據(jù)CPU的架構(gòu)來(lái)選,而市面上ARM架構(gòu)的手機(jī)占大多數(shù),所以一般的APK只包含ARM和ARM-V7a的so。

  1.   res目錄:res是resource的縮寫(xiě),這個(gè)目錄存放資源文件,存在這個(gè)文件夾下的所有文件都會(huì)映射到Android工程的.R文件中,生成對(duì)應(yīng)的ID,訪問(wèn)的時(shí)候直接使用資源ID即R.id.filename,res文件夾下可以包含多個(gè)文件夾,其中anim存放動(dòng)畫(huà)文件;drawable目錄存放圖像資源;layout目錄存放布局文件;values目錄存放一些特征值,colors.xml存放color顏色值,dimens.xml定義尺寸值,string.xml定義字符串的值,styles.xml定義樣式對(duì)象;xml文件夾存放任意xml文件,在運(yùn)行時(shí)可以通過(guò)Resources.getXML()讀?。籸aw是可以直接復(fù)制到設(shè)備中的任意文件,他們無(wú)需編譯。
    
    
  2.   META-INF目錄:保存應(yīng)用的簽名信息,簽名信息可以驗(yàn)證APK文件的完整性。AndroidSDK在打包APK時(shí)會(huì)計(jì)算APK包中所有文件的完整性,并且把這些完整性保存到META-INF文件夾下,應(yīng)用程序在安裝的時(shí)候首先會(huì)根據(jù)META-INF文件夾校驗(yàn)APK的完整性,這樣就可以保證APK中的每一個(gè)文件都不能被篡改。以此來(lái)確保APK應(yīng)用程序不被惡意修改或者病毒感染,有利于確保Android應(yīng)用的完整性和系統(tǒng)的安全性。META-INF目錄下包含的文件有CERT.RSA,CERT.DSA,CERT.SF和MANIFEST.MF,其中CERT.RSA是開(kāi)發(fā)者利用私鑰對(duì)APK進(jìn)行簽名的簽名文件,CERT.SF,MANIFEST.MF記錄了文件中文件的SHA-1哈希值。
    
    
  3.   AndroidManifest.xml:是Android應(yīng)用程序的配置文件,是一個(gè)用來(lái)描述Android應(yīng)用“整體資訊”的設(shè)定文件,簡(jiǎn)單來(lái)說(shuō),相當(dāng)于Android應(yīng)用向Android系統(tǒng)“自我介紹”的配置文件,Android系統(tǒng)可以根據(jù)這個(gè)“自我介紹”完整地了解APK應(yīng)用程序的資訊,每個(gè)Android應(yīng)用程序都必須包含一個(gè)AndroidManifest.xml文件,且它的名字是固定的,不能修改。我們?cè)陂_(kāi)發(fā)Android應(yīng)用程序的時(shí)候,一般都把代碼中的每一個(gè)Activity,Service,Provider和Receiver在AndroidManifest.xml中注冊(cè),只有這樣系統(tǒng)才能啟動(dòng)對(duì)應(yīng)的組件,另外這個(gè)文件還包含一些權(quán)限聲明以及使用的SDK版本信息等等。程序打包時(shí),會(huì)把AndroidManifest.xml進(jìn)行簡(jiǎn)單的編譯,便于Android系統(tǒng)識(shí)別,編譯之后的格式是AXML格式,如下圖Figure3所示:
    
    
  4.   classes.dex:
    
    

傳統(tǒng)的Java程序,首先先把Java文件編譯成class文件,字節(jié)碼都保存在了class文件中,Java虛擬機(jī)可以通過(guò)解釋執(zhí)行這些class文件。而Dalvik虛擬機(jī)是在Java虛擬機(jī)進(jìn)行了優(yōu)化,執(zhí)行的是Dalvik字節(jié)碼,而這些Dalvik字節(jié)碼是由Java字節(jié)碼轉(zhuǎn)換而來(lái),一般情況下,Android應(yīng)用在打包時(shí)通過(guò)AndroidSDK中的dx工具將Java字節(jié)碼轉(zhuǎn)換為Dalvik字節(jié)碼。dx工具可以對(duì)多個(gè)class文件進(jìn)行合并,重組,優(yōu)化,可以達(dá)到減小體積,縮短運(yùn)行時(shí)間的目的

  1.   resources.arsc:用來(lái)記錄資源文件和資源ID之間的映射關(guān)系,用來(lái)根據(jù)資源ID尋找資源。Android的開(kāi)發(fā)是分模塊的,res目錄專門(mén)用來(lái)存放資源文件,當(dāng)在代碼中需要調(diào)用資源文件時(shí),只需要調(diào)用findviewbyId()就可以得到資源文件,每當(dāng)在res文件夾下放一個(gè)文件,aapt就會(huì)自動(dòng)生成對(duì)應(yīng)的ID保存在.R文件,我們調(diào)用這個(gè)ID就可以,但是只有這個(gè)ID還不夠,.R文件只是保證編譯程序不報(bào)錯(cuò),實(shí)際上在程序運(yùn)行時(shí),系統(tǒng)要根據(jù)ID去尋找對(duì)應(yīng)的資源路徑,而resources.arsc文件就是用來(lái)記錄這些ID和資源文件位置對(duì)應(yīng)關(guān)系的文件。
    
    

APK安裝過(guò)程
首先,復(fù)制APK安裝包到/data/app下,然后校驗(yàn)APK的簽名是否正確,檢查APK的結(jié)構(gòu)是否正常,進(jìn)而解壓并且校驗(yàn)APK中的dex文件,確定dex文件沒(méi)有被損壞后,再把dex優(yōu)化成odex,使得應(yīng)用程序啟動(dòng)時(shí)間加快,同時(shí)在/data/data目錄下建立于APK包名相同的文件夾,如果APK中有l(wèi)ib庫(kù),系統(tǒng)會(huì)判斷這些so庫(kù)的名字,查看是否以lib開(kāi)頭,是否以.so結(jié)尾,再根據(jù)CPU的架構(gòu)解壓對(duì)應(yīng)的so庫(kù)到/data/data/packagename/lib下。

APK安裝的時(shí)候會(huì)把DEX文件解壓并且優(yōu)化為odex
odex在原來(lái)的dex文件頭添加了一些數(shù)據(jù),在文件尾部添加了程序運(yùn)行時(shí)需要的依賴庫(kù)和輔助數(shù)據(jù),使得程序運(yùn)行速度更快。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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