1.0Android簡介
1.1Android系統(tǒng)結(jié)構(gòu)
Android大致可以分為4層架構(gòu):Linux內(nèi)核層、系統(tǒng)運行庫層、應用框架層和應用層。
- Linux內(nèi)核層:Android系統(tǒng)是基于Linux內(nèi)核的,這一層為Android設備的各種硬件提供了底層的驅(qū)動,如顯示驅(qū)動、音頻驅(qū)動、照相機驅(qū)動、藍牙驅(qū)動、Wi-Fi驅(qū)動、電源管理等。
- 系統(tǒng)運行庫層:這一層通過一些C/C++庫為Android系統(tǒng)提供了主要的特性支持。如SQLite庫提供了數(shù)據(jù)庫的支持,OpenGL|ES庫提供了3D繪圖的支持,Webkit庫提供了瀏覽器內(nèi)核的支持等。在這一層還有Android運行時庫,它主要提供了一些核心庫,允許開發(fā)者使用Java語言來編寫Android應用。另外,Android運行時庫中還包含了Dalvik虛擬機(5.0系統(tǒng)之后改為ART運行環(huán)境),它使得每一個Android應用都能運行在獨立的進程中,并且擁有一個自己的虛擬機實例。相較于Java虛擬機,Dalvik和ART都是專門為移動設備定制的,它針對手機內(nèi)存、CPU性能有限等情況做了優(yōu)化處理。
- 應用框架層:這一層主要提供了構(gòu)建應用程序時可能用到的各種API,Android自帶的一些核心應用就是使用這些API完成的,開發(fā)者可以使用這些API來構(gòu)建自己的應用程序。
-
應用層:所有安裝在手機上的應用程序都是屬于這一層的,比如系統(tǒng)自帶的聯(lián)系人、短信等程序,或者是你從Google Play上下載的小游戲,當然還包括你自己開發(fā)的程序。
Android系統(tǒng)架構(gòu)
1.2Android系統(tǒng)版本
最新的數(shù)據(jù)可以訪問http://developer.android.google.cn/about/dashboards
1.3Android四大組件
Android系統(tǒng)四大組件分別是Activity、Service、BroadcastReceiver和ContentProvider。
- Activity:是所有Android應用程序的門面,凡是在應用中你看得到的東西,都是放在Activity中的。
- Service:就比較低調(diào)了,你無法看到它,但它會在后臺默默地運行,即使用戶退出了應用,Service仍然是可以繼續(xù)運行的。
- BroadcastReceiver:允許你的應用接收來自各處的廣播消息,比如電話、短信等,當然,你的應用也可以向外發(fā)出廣播消息。
- ContentProvider:則為應用程序之間共享數(shù)據(jù)提供了可能,比如你想要讀取系統(tǒng)通訊錄中的聯(lián)系人,就需要通過ContentProvider來實現(xiàn)。
2.0Android文件結(jié)構(gòu)
- .gradle和.idea:這兩個目錄下放置的都是Android Studio自動生成的一些文件,無須關(guān)心,也不要去手動編輯。
- app:項目中的代碼、資源等內(nèi)容都是放置在這個目錄下的,后面的開發(fā)工作也基本是在這個目錄下進行的。
- build:這個目錄主要包含了一些在編譯時自動生成的文件,也不需要過多關(guān)心。
- gradle:這個目錄下包含了gradle wrapper的配置文件,使用gradle wrapper的方式不需要提前將gradle下載好,而是會自動根據(jù)本地的緩存情況決定是否需要聯(lián)網(wǎng)下載gradle。
Android Studio默認就是啟用gradle wrapper方式的,如果需要更改成離線模式,可以點擊Android Studio導航欄→File→Settings→Build, Execution,Deployment→Gradle,進行配置更改。
- .gitignore:這個文件是用來將指定的目錄或文件排除在版本控制之外的。
- build.gradle:這是項目全局的gradle構(gòu)建腳本,通常這個文件中的內(nèi)容是不需要修改的。
- gradle.properties:這個文件是全局的gradle配置文件,在這里配置的屬性將會影響到項目中所有的gradle編譯腳本。
- gradlew和gradlew.bat:這兩個文件是用來在命令行界面中執(zhí)行g(shù)radle命令的,其中g(shù)radlew是在Linux或Mac系統(tǒng)中使用的,gradlew.bat是在Windows系統(tǒng)中使用的。
- HelloWorld.imliml:這個文件是所有IntelliJ IDEA項目都會自動生成的一個文件(Android Studio是基于IntelliJ IDEA開發(fā)的),用于標識這是一個IntelliJ IDEA項目,不需要修改這個文件中的任何內(nèi)容。
- local.properties:這個文件用于指定本機中的Android SDK路徑,通常內(nèi)容是自動生成的,我們并不需要修改。除非你本機中的Android SDK位置發(fā)生了變化,那么就將這個文件中的路徑改成新的位置即可。
- settings.gradle:這個文件用于指定項目中所有引入的模塊。由于HelloWorld項目中只有一個app模塊,因此該文件中也就只引入了app這一個模塊。通常情況下,模塊的引入是自動完成的,需要我們手動修改這個文件的場景可能比較少。
2.1 app目錄下的文件結(jié)構(gòu)
除了app目錄之外,大多數(shù)的文件和目錄是自動生成的,并不需要進行修改。app目錄下的內(nèi)容才以后的工作重點,展開之后的結(jié)構(gòu)如圖
- build:這個目錄和外層的build目錄類似,也包含了一些在編譯時自動生成的文件,不過它里面的內(nèi)容會更加復雜。
- libs:如果你的項目中使用到了第三方jar包,就需要把這些jar包都放在libs目錄下,放在這個目錄下的jar包會被自動添加到項目的構(gòu)建路徑里。
- androidTest:此處是用來編寫Android Test測試用例的,可以對項目進行一些自動化測試。
- java:java目錄是放置我們所有Java代碼的地方(Kotlin代碼也放在這里),展開該目錄,你將看到系統(tǒng)幫我們自動生成了一個MainActivity文件。
- res:在項目中使用到的所有圖片、布局、字符串等資源都要存放在這個目錄下。圖片放在drawable目錄下,布局放在layout目錄下,字符串放在values目錄下。
- AndroidManifest.xml:這是整個Android項目的配置文件,在程序中定義的所有四大組件都需要在這個文件里注冊,另外還可以在這個文件中給應用程序添加權(quán)限聲明。
- test:此處是用來編寫Unit Test測試用例的,是對項目進行自動化測試的另一種方式。
- .gitignore:這個文件用于將app模塊內(nèi)指定的目錄或文件排除在版本控制之外,作用和外層的.gitignore文件類似
- app.iml:IntelliJ IDEA項目自動生成的文件,不需要關(guān)心或修改這個文件中的內(nèi)容。
- build.gradle:這是app模塊的gradle構(gòu)建腳本,這個文件中會指定很多項目構(gòu)建相關(guān)的配置。
- proguard-rules.pro:這個文件用于指定項目代碼的混淆規(guī)則,當代碼開發(fā)完成后打包成安裝包文件,如果不希望代碼被別人破解,通常會將代碼進行混淆,從而讓破解者難以閱讀。
2.2 res目錄下的文件結(jié)構(gòu)
- 所有以“drawable”開頭的目錄都是用來放圖片的
- 所有以“mipmap”開頭的目錄都是用來放應用圖標的
- 所有以“values”開頭的目錄都是用來放字符串、樣式、顏色等配置的
- 所有以“l(fā)ayout”開頭的目錄都是用來放布局文件的
之所以有這么多“mipmap”開頭的目錄,其實主要是為了讓程序能夠更好地兼容各種設備。drawable目錄也是相同的道理,雖然Android Studio沒有幫我們自動生成,但是我們應該自己創(chuàng)建drawable-hdpi、drawable-xhdpi、drawable-xxhdpi等目錄。
2.2.1使用資源
這里以strings.xml文件為例。
打開res/values/strings.xml文件,內(nèi)容如下所示:
<resources>
<string name="app_name">My Application</string>
</resources>
這里定義了一個應用程序名的字符串,有以下兩種方式來引用它。
- 在代碼中通過R.string.app_name可以獲得該字符串的引用。
- 在XML中通過@string/app_name可以獲得該字符串的引用。
基本的語法就是上面這兩種方式,其中string部分是可以替換的,如果是引用的圖片資源就可以替換成drawable,如果是引用的應用圖標就可以替換成mipmap,如果是引用的布局文件就可以替換成layout,以此類推。
3.0詳解build.gradle文件
不同于Eclipse,Android Studio是采用Gradle來構(gòu)建項目的。
Gradle是一個非常先進的項目構(gòu)建工具,它使用了一種基于Groovy的領(lǐng)域特定語言(DSL)來進行項目設置,摒棄了傳統(tǒng)基于XML(如Ant和Maven)的各種煩瑣配置。
可以看到,項目中有兩個build.gradle文件,一個是在最外層目錄下的,一個是在app目錄下的。
3.1最外層目錄的build.gradle
代碼如下:
buildscript {
ext.kotlin_version = '1.3.61'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
}
}
- 兩處repositories的閉包中都聲明了google()和jcenter()這兩行配置,它們分別對應了一個代碼倉庫。聲明了這兩行配置之后,我們就可以在項目中輕松引用任何google和jcenter倉庫中的依賴庫了。
google倉庫中包含的主要是Google自家的擴展依賴庫。
jcenter倉庫中包含的大多是一些第三方的開源庫。 - dependencies閉包中使用classpath聲明了兩個插件:一個Gradle插件和一個Kotlin插件。
com.android.tools.build:gradle:3.5.2,最后面的部分是插件的版本號,它通常和當前Android Studio的版本是對應的
另外一個Kotlin插件則表示當前項目是使用Kotlin進行開發(fā)的,如果是Java版的Android項目,則不需要聲明這個插件。Kotlin插件的版本號是1.3.61。
3.2 app目錄下的build.gradle
代碼如下:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 32
buildToolsVersion '28.0.3'
defaultConfig {
applicationId 'com.test.test'
minSdkVersion 21
targetSdkVersion 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.core:core-ktx:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
- 第一行應用了一個插件,一般有兩種值可選:<1>com.android.application表示這是一個應用程序模塊<2>com.android.library表示這是一個庫模塊。
二者最大的區(qū)別在于,應用程序模塊是可以直接運行的,庫模塊只能作為代碼庫依附于別的應用程序模塊來運行。 - 接下來的兩行應用了kotlin-android和kotlin-android-extensions這兩個插件。
<1>如果你想要使用Kotlin來開發(fā)Android項目,那么第一個插件就是必須應用的。
<2>第二個插件幫助我們實現(xiàn)了一些非常好用的Kotlin擴展功能。 - 緊接著是一個大的android閉包,在這個閉包中我們可以配置項目構(gòu)建的各種屬性。
<1>compileSdkVersion用于指定項目的編譯版本,這里指定成32表示使用Android API 32系統(tǒng)的SDK編譯。
<2>buildToolsVersion用于指定項目構(gòu)建工具的版本,版本是28.0.3。 - 閉包中又嵌套了一個defaultConfig閉包,defaultConfig閉包中可以對項目的更多細節(jié)進行配置。
<1>applicationId是每一個應用的唯一標識符,絕對不能重復。<2>minSdkVersion用于指定項目最低兼容的Android系統(tǒng)版本,這里指定成21表示最低兼容到Android 5.0系統(tǒng)。
<3>targetSdkVersion指定的值表示你在該目標版本上已經(jīng)做過了充分的測試,系統(tǒng)將會為你的應用程序啟用一些最新的功能和特性。比如Android 6.0系統(tǒng)中引入了運行時權(quán)限這個功能,如果你將targetSdkVersion指定成23或者更高,那么系統(tǒng)就會為你的程序啟用運行時權(quán)限功能,而如果你將targetSdkVersion指定成22,那么就說明你的程序最高只在Android 5.1系統(tǒng)上做過充分的測試,Android 6.0系統(tǒng)中引入的新功能自然就不會啟用了。
<4>versionCode用于指定項目的版本號。
<5>versionName用于指定項目的版本名。
<6>testInstrumentationRunner用于在當前項目中啟用JUnit測試,你可以為當前項目編寫測試用例,以保證功能的正確性和穩(wěn)定性。 - buildTypes閉包中用于指定生成安裝文件的相關(guān)配置,通常只會有兩個子閉包:一個是debug,一個是release。
<1>debug閉包用于指定生成測試版安裝文件的配置。
debug閉包是可以忽略不寫的,因此我們看到上面的代碼中就只有一個release閉包。
<2>release閉包用于指定生成正式版安裝文件的配置。
(1)minifyEnabled用于指定是否對項目的代碼進行混淆,true表示混淆,false表示不混淆。
(2)proguardFiles用于指定混淆時使用的規(guī)則文件,這里指定了兩個文件:
第一個proguard-android-optimize.txt是在<Android SDK>/tools/proguard目錄下的,里面是所有項目通用的混淆規(guī)則;
第二個proguard-rules.pro是在當前項目的根目錄下的,里面可以編寫當前項目特有的混淆規(guī)則。
注意:通過Android Studio直接運行項目生成的都是測試版安裝文件。
- dependencies閉包它可以指定當前項目所有的依賴關(guān)系。通常Android Studio項目一共有3種依賴方式:本地依賴、庫依賴和遠程依賴。
<1>本地依賴可以對本地的jar包或目錄添加依賴關(guān)系。
implementation fileTree就是一個本地依賴聲明,它表示將libs目錄下所有.jar后綴的文件都添加到項目的構(gòu)建路徑中。
<2>庫依賴可以對項目中的庫模塊添加依賴關(guān)系。
庫依賴聲明這里沒有用到,它的基本格式是implementationproject后面加上要依賴的庫的名稱,比如有一個庫模塊的名字叫helper,那么添加這個庫的依賴關(guān)系只需要加入implementation project(':helper')這句聲明即可。
<3>遠程依賴則可以對jcenter倉庫上的開源項目添加依賴關(guān)系。
implementation則是遠程依賴聲明,androidx.appcompat:appcompat:1.0.2就是一個標準的遠程依賴庫格式,加上這句聲明后,Gradle在構(gòu)建項目時會首先檢查一下本地是否已經(jīng)有這個庫的緩存,如果沒有的話則會自動聯(lián)網(wǎng)下載,然后再添加到項目的構(gòu)建路徑中。
androidx.appcompat是域名部分,用于和其他公司的庫做區(qū)分;
appcompat是工程名部分,用于和同一個公司中不同的庫工程做區(qū)分;
1.1.0是版本號,用于和同一個庫不同的版本做區(qū)分。
<4>剩下的testImplementation和androidTestImplementation都是用于聲明測試用例庫的。
4.0Android程序執(zhí)行流程
當我們創(chuàng)建一個默認的Android項目時,直接在虛擬機上運行,會顯示HelloWorld文字,那文字又是如何顯示的呢?
- 首先打開Android- Manifest.xml文件,從中可以找到如下代碼:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
這段代碼表示對MainActivity進行注冊,沒有在AndroidManifest.xml里注冊的Activity是不能使用的。
其中intent-filter里的兩行代碼非常重要,<actionandroid:name="android.intent.action.MAIN"/> 和<categoryandroid:name="android.intent.category.LAUNCHER" />表示MainActivity是這個項目的主Activity,在手機上點擊應用圖標,首先啟動的就是這個Activity。
- 再打開MainActivity,代碼如下所示:
package com.example.myapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
MainActivity是繼承自AppCompatActivity的。AppCompatActivity是AndroidX中提供的一種向下兼容的Activity,可以使Activity在不同系統(tǒng)版本中的功能保持一致性。而Activity類是Android系統(tǒng)提供的一個基類,我們項目中所有自定義的Activity都必須繼承它或者它的子類才能擁有Activity的特性(AppCompatActivity是Activity的子類)。然后可以看到MainActivity中有一個onCreate()方法,在onCreate()方法的第二行調(diào)用了setContentView()方法,給當前的Activity引入了一個activity_main布局。
- 布局文件定義在res/layout目錄下的,打開activity_main.xml文件并切換到Text視圖,代碼如下所示:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
可以看到代碼中有一個TextView,用于在布局中顯示文字。通過android:text="Hello World!"顯示Hello World!。這就是一個Android程序的執(zhí)行流程。