《第一行代碼 Android》作為Android入門書籍,由郭霖大神編寫的,這本書相對比其他入門書籍比較基礎并且深度也不錯。本文主要是針對第一章概況讀書簡記,便于日后溫故,總結。
Android 系統起源
首先,作為一名Android開發人員來說,對于Android系統怎么而來的,想必大家或多或少聽說一些。Android作為現如今擁有用戶群體的手機系統,起初是由Andy Rubin(“Android之父”)同其他三位創始人成立了“Android公司“,為了數碼相機開發出來的一套基于Linux系統,這便是Android的雛形。
隨后,Android轉而開發手機操作系統,并于2005年被谷歌收購,Rubin和其他創始人留在谷歌,開始了真正意義上的智能手機操作系統開發。在這個時候,Android系統的方向已經確定,比如基于Linux、開源、免費供手機廠商使用等等,谷歌則可將其服務深度集成到系統中獲得利潤。
2008年,谷歌發布了第一版Android系統”Android 1.0“,接著在2009年發布了1.1版本,隨后在1.5版本開始出現以甜點命名版本,具體版本如下:
Android Beta,發布于2007年11月5日,同時的軟件開發套件(SDK),發布于2007年11月12日。 11月5日被認為是Android的"生日"。
Android版本名稱Code name | Android版本 | 版本發布時間 | 對應API |
---|---|---|---|
(no code name) | 1.0 | 2008年9月23日 | API level 1 |
(no code name) | 1.1 | 2009年2月2日 | API level 2 |
Cupcake | 1.5 | 2009年4月17日 | API level 3,NDK 1 |
Donut | 1.6 | 2009年9月15日 | API level 4,NDK 2 |
Eclair | 2.0.1 | 2009年12月3日 | API level 6 |
Eclair | 2.1 | 2010年1月12日 | API level 7,NDK3 |
Froyo | 2.2.x | 2010年1月12日 | API level 8,NDK 4 |
Gingerbread | 2.3 – 2.3.2 | 2011年1月1日 | API level 9,NDK5 |
Gingerbread | 2.3.3 – 2.3.7 | 2011年9月2日 | API level 10 |
Honeycomb | 3.0 | 2011年2月24日 | API level 11 |
Honeycomb | 3.1 | 2011年5月10日 | API level 12,NDK 6 |
Honeycomb | 3.2.x | 2011年7月15日 | API level 13 |
Ice Cream | Sandwich 4.0.1 – 4.0.2 | 2011年10月19日 | API level 14,NDK 7 |
Ice Cream | Sandwich 4.0.3 – 4.0.4 | 2012年2月6日 | API level 15,NDK 8 |
Jelly Bean | 4.1 | 2012年6月28日 | API level 16 |
Jelly Bean | 4.1.1 | 2012年6月28日 | API level 16 |
Jelly Bean | 4.2-4.2.2 | 2012年11月 | API level 17 |
Jelly Bean | 4.3 | 2013年7月 | API level 18 |
KitKat | 4.4 | 2013年7月24日 | API level 19 |
Kitkat Watch | 4.4W | 2014年6月 | API level 20 |
Lollipop(Android L) | 5.0/5.1 | 2014年6月25日 | API level 21/API level 22 |
Marshmallow(Android M) | 6.0 | 2015年5月28日 | API level 23 |
Nougat(Android N) | 7.0 | 2016年5月18日 | API level 24 |
Nougat(Android N) | 7.1 | 2016年12月 | API level 25 |
Oreo(Android O) | 8.0 | 2017年8月22日 | API level 26 |
Oreo(Android O) | 8.1 | 2017年12月5日 | API level 27 |
Pie (Android P)不是鳳梨酥(PineappleCake) | 9.0 | 2018年8月7日 | API level 28 |
Android的版本,有個API Level,對應著某個Android發布版本的名稱。
Android系統架構
上面我們大概了解了Android的起源以及對應的版本,并且也大概知道Android是基于Linux系統開發出來的移動終端系統,那接下來我們來了解下Android系統的內部架構,Android大致可以分為四層架構:Linux內核層、系統運行庫層、應用框架層、應用層。
Linux內核層:
Android系統基于Linux內核,這一層為Android設備的各種硬件提供了底層的去驅動,如顯卡驅動、音頻驅動、相機驅動、藍牙驅動、WIFI驅動、電源管理等。系統運行庫層:
這層通過一些C/C++庫為Android系統提供了主要的特性支持,例如SQLite庫提供了數據庫的支持,OpenGL|ES庫提供了3D繪圖的支持,Webkit庫提供了瀏覽器內核的支持等等。
同樣在這一層,還有谷歌為我們提供的Android運行時庫,它主要提供了一些核心庫,能夠允許開發者使用Java語言來編寫Android應用。另外,Android運行時庫中還包含了Dalvik虛擬機(5.0系統之后改為ART運行環境,這兩種環境在本質上有很大的區別,導致Android在運行性能方面更加優越,具體區別在后期會獨篇說明,這里不過多闡述),它使得每個Android應用都能運行在獨立的進程中,并且擁有自己的虛擬機實例。相對比于Java虛擬機,Android虛擬機是專門為移動設備定制的,它針對手機內存、CPU性能有限等情況做了優化處理。應用框架層
這層主要提供了構建應用程序時可能用到的各種API,Android自帶的一些核心應用就是使用這些API完成的。應用層
所有安裝在手機上的應用程序都屬于這一層的,比如系統內置的聯系人、短信等程序,或者從應用商城上下載下來的應用以及自己開發的程序都屬于這層。
Android系統架構可以參考如下圖:
Android開發環境搭建
針對于開發環境搭建,都是每個開發者老生常談的必要走的一步,這里就不多累贅,只是貼出各個環境下載鏈接,便于日后查詢配置使用。
- JDK
- Android Studio(可能部分小伙伴需要墻,也可以訪問百度云盤資源)
-
Android SDK一般這塊不需要單獨下載,谷歌已經將其集成到Android Studio中了,如果小伙伴有需要下載,也可以在 Android Studio上瀏覽到
Command line tools only
選擇即可。
關于小伙伴在使用Android Studio過程中可能會遇到一些構建常見問題,可以詳情了解下我的另外一篇文字《Android Studio 構建常見出錯問題匯總》,以及《Android Studioc常用快捷鍵匯總》,不定時更新哦!
Android Studio目錄結構分析
Android在早期開發還是使用Eclipse比較多,但自從2013年官方推出Android Studio(以下簡稱AS)之后,Android開發更多的傾向于使用AS開發,而且在推出AS之后,官方也相應停止了Eclipse開發Android對應的ADT更新,所以現在大部分都是采用AS開發。在這里有必要扯一下AS目錄結構,畢竟兩個IDE的編譯機制是有所不同的,在Eclipse采用的Ant方式構建編譯項目,而在AS中采用的是Gradle。
Eclipse在這我就不過多闡述了,我們要跟緊時代腳步,所以這里主要講下AS中項目對應目錄結構的功能與作用,新建一個項目,可得到如下所示:
.gradle和.idea
這兩個目錄下放置的都是AS自動生成的一些文件,所以這塊我們不用關心,在拷貝項目備份或者版本管理時候,可以忽略這兩個目錄。app
項目中的代碼、資源等內容幾乎都在這個目錄下,日常編寫代碼大部分也都在這個目錄下進行的,所以這個目錄的文件結構后面會單獨解析具體底層目錄。build
在AS高版本中這個目錄已經不存在,低版本中存在這個目錄,也是AS編譯時自動生成的文件,不用關心,在拷貝項目備份或者文件管理時候,同樣是可以忽略的目錄。gradle
在這個目錄下包含了gradle wrapper的配置文件,使用gradle wrapper的方式無需提前將gradle下載好,而是會自動根據本地的緩存情況決定是否需要聯網下載gradle。.gitignore
這個文件用來將指定的目錄或文件排除在版本控制(Git)之外的。build.gradle
這個文件是全局的gradle的構建腳本,通常這個文件中的內容是不需要修改的。后面會具有分析gradle構建腳本的內容。gradle.properties
這個文件是全局的gradle配置文件,在這里配置的屬性會影響到項目中所有的gradle編譯腳本。gradlew 和 gradlew.bat
這個兩個文件是用來在命令行界面(Terminal)中執行gradle命令的,其中gradlew是在Linux或Mac系統中使用的,gradlew.bat是在windows系統中使用的。HelloWorld.iml
iml文件是所有IntelliJ IDEA項目都會自動生成的一個文件(AS是基于IntelliJ IDEA開發的),用于標識這是由IntelliJ IDEA項目,不需要修改此文件,可以在備份或者版本控制時候忽略。local.properties
文件是用于指定本機中的Android SDK路徑,以及NDK路徑,通常不需要修改,除非本地環境發生改變時候。setting.gradle
這個文件同于指定項目中所有引入的模塊,由于此處只有app一個模塊,因此該文件這里只引入的app這一個模塊。通常情況都是自動完成的,只有手動導入模塊時候,可能需要手動去修改。
整個項目的外層結構基本到這有一個大致的了解,接下來說下app目錄,也就是我們代碼經常需要修改調整的目錄下的結構,如下所示:
build
這個目錄和外層的build目錄相似,主要也是包含了編譯自動生成的文件,同樣也無需關心,可以備份或者版本控制可以忽略。libs
項目中使用第三方jar包,需要把對應的jar包放在這個目錄下,放在這個目錄下的jar包會被自動添加到構建路徑里去。androidTest
此處用來編寫AndroidTest測試用例的,可以對項目進行一些自動化測試。java
此處用于編寫應用的主要邏輯Java代碼。res
這個目錄主要存放應用的UI布局字符串等資源,這個目錄相對比較復雜,在子目錄layout下主要存放應用的布局文件,而圖片根據不同的分辨率存放在以drawble-xxx目錄下,當然有些類似selector選擇器或者Shape自定義形狀等等這些還是放在drawble中,子目錄values下主要存放字符串、樣式以及主題等。
在這個目錄所有子目錄下有一個子目錄mipmap-xxx需要特別說明以下,mipmap是在Android Jelly Beans 4.3中提出來的,主要是為了讓程序能夠更好的兼容各種設備,在處理Launcher Icon圖片渲染方面更加強大。AndroidManifest.xml
這個文件是整個應用的配置文件,在程序中定義的所有四大組件都必須在這個文件里注冊,在這個文件配置需要的相應權限配置聲明。test
此處用來編寫Unit Test測試用例的,是對項目進行自動化測試的另外一種方式。.gitignore
這個文件用于app模塊內的指定的目錄或文件的排除在版本控制(Git)之外,作用與外層的.gitignore
,但一般都在外層的.gitignore
全局設置了。app.iml
IntelliJ IDEA項目自動生成的文件,不需要去修改與關心,備份或版本控制時候可以忽略。build.gradle
app模塊的gradle構建腳本,這個文件會指定很多項目構建相關的配置。proguard-rules.pro
這個文件用于指定項目代碼的混淆規則,當我們的代碼編寫打包成apk時候,如果不希望別人破解,通常會將代碼進行混淆,從而讓破解者難以閱讀,考慮安全點,一般還會對apk進行加固。
因為Android Studio是采用Gradle來構建項目的,所以這里對Gradle的配置文件進一步講解。Gradle是一個非常先進的項目構建工具,它使用了一種基于Groovy的領域特定語言(DSL)來聲明項目設置,摒棄了傳統基于XML(如Ant和Maven)的各種煩瑣配置。
這里先說說項目外層中build.gradle文件的配置,如下:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
這些代碼都是自動生成的,大部分情況下不需要我們去修改,但也得大概知道其意思。
首先兩處repositories
的閉包中聲明了google()、jcenter()配置,它們代表不同的代碼托管倉庫,很多的Android開源項目都會或多或少引用了谷歌提供開源項目,所以需要聲明google(),而很多的Android開源項目都會選擇將代碼托管到jcenter上,聲明了jcenter之后,我們就可以很方便的使用任何jcenter上的開源項目了。
接下來,dependencies閉包中使用了classpath聲明了一個Gradle插件。為什么要聲明這個插件呢?原來Gradle并不只是專門為構建Android項目而開發的,java、C++等很多項目都可以使用Gradle來構建。因此想要使用它來構建Android項目,則需要聲明com.android.tools.build:gradle:3.0.1'這個插件,其中,最后冒號后面部分是插件的版本號,例如我現在這個項目中使用的插件版本是3.0.1.
分析完外層的build.gradle文件后,還需要分析模塊里面的build.gradle文件,如下:
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion "26.0.2"
defaultConfig {
applicationId "com.anand.activitylifecycletest"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.0.0-beta1'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:0.5'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2'
}
這個文件相對復雜一些,首先第一行應用了一個插件,一般有兩種值可選:com.android.application
表示這是一個應用程序模塊,com.android.library
表示這是一個庫模塊。應用程序模塊與庫模塊最大的區別在于一個是可以直接運行的,一個只能作為代碼庫依附于別的應用程序模塊來運行。
緊接著是android
這個閉包,可以配置項目構建的各種屬性。其中,compileSdkVersion
用于指定項目的編譯版本,這里指定26表示使用Android 8.0系統的SDK編譯,buildToolsVersion
用于指定項目構建工具的版本,這里使用了26.0.2版本。
接著是嵌套下的defaultConfig
閉包,defaultConfig
閉包中可以對項目進行更多的配置。其中,applicationId
用于指定項目的包名,一般修改應用包名,可對這個配置進行修改。minSdkVersion
用于指定項目最低兼容的Android系統版本,這里指定成15表示最低兼容到Android 4.0系統。targetSdkVersion
指定的值表示在該目標版本上已經做過了充分測試,系統將會為其應用程序啟用一些最新的功能和特性。舉例說Android 6.0系統中引入了運行時權限這個功能,如果我們將targetSdkVersion
指定成23或者更高,那么系統就會認為你的程序已經做好充分測試,將為你啟用運行時權限,而如果將targetSdkVersion
指定成22,那么說明程序最高只在Android 5.1系統上做過充分的測試,Android 6.0系統中引入的新功能自然就不會啟用。剩下的versionCode
用于指定項目的版本號,versionName
用于指定項目版本名,這個兩個在安裝應用文件以及版本升級方面比較重要。testInstrumentationRunner
為谷歌推薦的
AndroidJUnitRunner
單元測試(這塊是Android Studio2.2以后推出的,這塊我也是第一次接觸,后期有學習再深入探索)
接著分析下buildTypes
閉包。buildTypes
閉包用于指定生成安裝文件的相關配置。通常情況下會有兩個子閉包,一個debug
,一個release
。debug
閉包用于指定生成測試版安裝文件的配置,release
閉包用于指定生成正式版安裝文件的配置。另外,debug
閉包是可以忽略不寫的,因此默認情況下我們看到代碼中只有一個release
閉包。接下來,我們來看下debug
、release
閉包中具體內容吧,minifyEnable
用于指定是否對項目代碼進行混淆操作,true
表示混淆,false
表示不混淆。proguardFiles
用于指定混淆時使用的規則文件,這里指定了兩個文件,第一個proguard-android.txt
是在Android SDK下\tools\proguard
目錄下,這里是所有項目的通用的混淆規則;第二個proguard-rules.pro
是在當前項目的根目錄下的,里面可以編寫當前項目特有的混淆規則。需要注意的是,通過AS直接運行項目生成都是測試版本安裝文件,除非手動切換BuildVariants
設置。
分析完android
閉包,緊接著分析最后一個dependencies
閉包。這個閉包主要作用在于指定當前項目所有的依賴關系。通常AS項目一共有3種依賴關系:本地依賴、庫依賴和遠程依賴。本地依賴可以對本地的Jar包、aar包或者目錄添加依賴關系,庫依賴可以對項目中的庫模塊添加依賴關系,遠程依賴則可以對jcenter庫上的開源項目添加依賴關系。
觀察dependencies
閉包中的配置,第一行implementation fileTree
就是一個本地依賴聲明,表示將 libs
目錄下所有.jar
后綴的文件都添加到項目的構建路徑當中。而第二行的implementation
則是遠程依賴聲明,com.android.support:appcompat-v7:26.0.0-beta1
就是一個標準的遠程依賴庫格式,其中com.android.support
是域名部分,用于和其他公司的庫做區分;appcompat-v7
是組名稱,用于和同一個公司中不同的庫做區分;26.0.0-beta1
是版本號,用于和同一個庫不同的版本做區分。加上這句聲明后,Gradle在構建項目時會首先檢查一下本地是否已經存在這個庫的緩存,如果沒有的話則會自動去互聯網下載,然后再添加到項目的構建路徑當中。至于庫依賴這里沒有使用到,它的基本格式是implementation project
后面加上要依賴的庫名稱,例如有一個庫模塊的名稱叫helper,那么添加這個庫依賴的聲明只需要加入implementation project(':helper')
即可。后面一些是聲明主要是為了聲明測試用例庫的,后期會單獨詳細說明下,具體參考Android 項目中的幾種單元測試用例。
Android 的日志工具使用
Android中使用的日志工具是Log(android.util.Log)
,這個類提供了5個方法來打印日志。
- Log.v()。用于打印那些最為瑣碎的、意義最小的日志信息。對應級別verbose,是Android日志里面級別最低的一種。
- Log.d()。用于打印一些調式信息,這些信息對你調試程序和分析問題有幫助的。對應級別debug,比verbose高一級。
- Log.i()。用于打印一些比較重要的數據。這些數據應該是開發者非常想要看到的,可以幫助開發者分析用戶行為數據。對應級別info,比debug高一級。
- Log.w()。用于打印一些警告信息,提示程序在這個地方可能會有潛在的風險,最好去修復一下這些出現警告的地方。對應級別warn,比info高一級。
- Log.e()。用于打印程序中的錯誤信息,比如程序進入到了catch語句當中。當有錯誤信息打印出來的時候,一般都代表你的程序出現嚴重問題了,必須盡快修復。對應級別error,比warn高一級。
關于為什么使用Log而不使用System.out疑問?
System.out.print
對應Java初學者開說應該很熟悉,在Eclipse中syso就可以快速打印出信息來,那么為什么Android不使用這個方法,而采用多級別的Log呢,主要的原因是打印不可控、打印時間無法確定、不能添加過濾器、日志沒級別區分。對于程序比較復雜的情況下,日志比較多的情況下,快速定位問題無法很快定位到。
關于Log日志一些快捷鍵操作可以參考《Android Studioc常用快捷鍵匯總》中的Tab組合快捷鍵。
除了快捷鍵, AS還為Log日志提供了locat方便我們過濾查詢日志,讓我們可以快速定位到對應的日志上。AS目前為開發者提供了3個過濾器,Show only selected application
表示只顯示當前選中程序中的日志,Firebase
是谷歌提供的一個分析工具,No Filters
相當于沒有過濾器,會把所有的日志都顯示出來。當然除了一首AS提供的三種過濾器,也可以自定義自己的過濾器,選擇Edit Filter Configuration
會彈出一個過濾器配置界面,可以自行配置自定義過濾器,在Log Tag中對需要過濾的tag進行配置。