安卓開發(1)——安卓概述
安卓簡介
安卓系統架構
也就是常說的四層架構:linux內核層(linux kernel),系統運行庫層(Library)、應用框架層(Application Framewordk)和應用層(Applications)。
Linux kernel
Linux內核層:這一層是為硬件提供底層的驅動,例如藍牙,Wi-Fi驅動等等。
Libraries
系統運行庫層:這一層通過C/C++庫來為Android系統提供了特性支持,來為上層提供支持。
Application Framework
主要提供了建構應用程序時可能用到的各種API。
Application
應用層,所以安裝在安卓手機上的應用程序都是屬於這一層的,比如手機上的一些聯系人,QQ,微信等應用。
安卓開發的四大組件
Activity,Service,BroadcastReceiver和ContentProvider。
Activity(活動):包含了所有在APP中可以看到的東西。
Service:是在后台運行的部分。
BroadcastReciver:廣播接受者,可以接受各處的廣播(如:短信,電話等等),也可以向外發出廣播。
ContentProvider:應用程序之間共享數據。(比如:微信通過讀取手機的聯系人來添加好友)
Android的開發環境
所需的工具:
JDK:用於處理java代碼。
AndroidSDK:是Google提供的Android開發工具包,提供Android要使用的API。
Android Studio:一個開發Android 的IDE。
如何搭建Android開發環境不是本博客的重點,想了解的,可以自行百度搜索。
第一個Android項目
創建項目
這里選擇一個Empty Activity
這里的Name就是app的名字,Package name是項目的包名,Android系統就是通過包名來區分不同的應用程序(application)的,所以包名必須得有唯一性。
Save Location表示項目保存地址。
Language這里可以選擇Kotlin和Java
Minimum SDK這里可以設置項目的最低兼容版本,也就是兼容Android的最低版本為多少。
點擊Finish就完成了第一個項目的創建
使用項目
創建虛擬機
Android系統開發的app,需要在Android系統上才能跑,Android Studio提供了Android的虛擬機,可以給我們用來測試APP。
在菜單中找到這三個案件,中間那個就是用來創建和啟動模擬器的。
然后開始創建模擬器:
這里根據自己的喜好來選就好(我用的是Pixei2)
然后選擇系統鏡像,推薦選擇最新版本,也就是第一個,如果沒有下載過該鏡像,需要點擊Download后才能點擊下一步。
使用虛擬機
單機想要啟動的虛擬機,就可以啟動該虛擬機了。
在虛擬機上運行寫好的項目app
先開啟虛擬機,開啟后,在該菜單欄里面選擇要啟動的虛擬機和項目:
然后再點擊右邊的運行按鈕就可以運行了。(左邊那個錘子是編譯項目的意思)
第一個Android項目就搞定了。
分析第一個Android程序
查看項目文件:
當一個項目創建的時候默認是采用Android模式的項目結構來查看,但是這個步數真正的目錄結構,而是被Android Studio轉換了的,單擊Android轉換為Project(項目)版本來查看(中英文可以能有出入)。
切換為project版本下的項目結構:
這個才是真實的項目結構。
分析項目文件:
.gradle和.idea | 存放的都是AS自動生成的文件,這個不用處理。 |
---|---|
app | 項目中的代碼和資源等主要內容都是存放在這個目錄的,開發工作也主要是在這個目錄下面。 |
build | 包含了一些在編譯時自動生成的文件。(不用關心) |
gradle | 這個目錄包含了gradle wrapper的配置文件,使用gradle wrapper的方式不需要提前將gradle下載好,而是先根據有沒有本地緩存的情況來決定要不要下載。可以點擊File->Settings->Build,Execution,Deployment->Gradle。 整個安卓的項目都是采用gradle來全程把控 |
.gitignore | 用來將指定的目錄或文件排除在版本控制之外。 |
.build.gradle | 全局的gradle構建腳本,通常是不用修改的。 |
gradle.properties | 全局gradle的構建腳本,通常不需要修改。有點類似於makefile |
gradlew和gradlew.bat | 這兩個文件是用來在命令行界面執行gradle命令的,其中gradlew是在linux上使用,gradlew.bat是用在windows系統上的。 |
HelloWorld.iml | iml文件是所有的IDEA項目都會自動生成的一個文件(AS是基於IDEA開發的),該文件只是用來標識是IDEA的項目文件。 |
local.properties | 該文件用來指定Android 的SDK的路徑,通常是自動生成的,除非Android SDK位置發生變化,不然是不用修改的。 |
setting.gradle | 用來指定項目中所有引入的模塊,通常情況下模塊的引入都是自動完成的,需要手動修改比較少。 |
分析app目錄
經過前面分析的項目文件可以知道,除了app目錄,大部分文件都是AS自動生成的,所以app文件下的內容才是重點。
build | 和外層的build一樣,包含的是一些編譯時自動生成的文件。 |
---|---|
libs | 如果項目中包含了第三方的jar包,就需要把這些jar包放到libs文件夾下 |
androidTest | 用來寫Android Test測試用例的 |
java | 放置所有java(Kotlin)代碼的,展開可以看到,AS自動生成了一個MainActivity文件 |
res | 在項目里使用的所有圖片、布局、字符串等資源都要存放到該目錄下。圖片放到drawable目錄下,布局放到layout目錄下,字符串放到value目錄下。 |
AndroidManifest.xml | 整個項目的配置文件,在程序中定義的所有四大組件都需要在這個文件里面注冊,還可以在這里面給應用程序添加權限聲明。 |
test | 用來編寫Unit Test測試用例,對項目進行自動化測試的一種方式。 |
.gitignore | 用於將app模塊內指定的目錄或文件排除在版本控制之外。 |
app.iml | IDEA自動生成的文件,僅僅來標識是個IDEA文件。 |
build.gradle | app模塊內部的gradle構建腳本,指定很多項目構建相關的配置。 |
proguard-rules.pro | 用於指定項目代碼的混淆規則,當代碼開發完成后,不希望被別人破解,通常會將代碼進行混淆, |
詳解app中的res
將res文件夾展開可以看到里面的文件還是挺多的,但是歸納一下就還好。
圖片 | 所有以drawable開頭的目錄都是用來存放圖片的 |
---|---|
應用圖標 | 所有以mipmap開頭的存放的都是應用圖標 |
配置 | 所有以values開頭的都是用來存放字符串、樣式、顏色等配置的。 |
布局 | 所有以layout開頭的目錄都是用來存放布局文件的。 |
之所以有這么多mipmap開頭的目錄,主要是為了兼容各種設備,drawable也是一樣,雖然AS沒有自動生成,但是為了更好兼容,我們也應該自己創建drawable-hdpi ... drawable-xxxhdpi等目錄。在寫程序的時候最好對同一個圖片能提供幾個不同分辨率的版本,分別放在這些目錄下面,但是大多數時候只會有一個圖片,就把所有的圖片放到drawable-xxxhdpi里面就好了,這個目錄對應的是最主流的設備分辨率。
打開values下的string,xml:
<resources>
<string name="app_name">HelloWorld</string>
</resources>
可以看到這里定義了一個應用程序名字的字符串,有兩種方式可以拿來引用它:
1:在代碼里面通過R.string.app_name可以獲得該字符串的引用
2:在X M L中通過 @string/app_name可以獲得該字符串的引用
其中的string部分是可以替換的,如果用的是圖片資源就可以替換成drawable,如果是應用圖標就可以替換成mipmap,布局文件就可以替換成layout
例如:AndroidManifest.xml文件中的內容
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.HelloWorld">
....
</activity>
</application>
詳解build.gradle文件
AS采用gradle來構建項目,gradle是一個比較先進的項目構建工具,基於Groovy領域特點語言來進行項目設置,拋棄了基於傳統的XML的各種繁瑣配置。(反正比較先進就行了。)
在我們這個HelloWorld項目中,有兩個build.gradle文件,一個是整體的build.gradle,一個是app目錄下的build.gradle文件。
詳解整體項目的build.gradle文件
先看整體項目的build.gradle文件:
buildscript {
ext.kotlin_version = "1.3.72"
repositories {
google()
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:4.1.1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
}
}
這些代碼都是自動生成的,看似復雜但是忽略語法查看關鍵代碼還是挺簡單的。
首先兩處的repositories都聲明了google()和jcenter(),這兩個分別對應兩個代碼倉庫,google()主要是包含谷歌自己的擴展依賴庫,jcenter()主要是包含一些開源的第三方庫,聲明了之后就可以使用它們所包含的依賴庫了。
在dependencies中聲明了gradke和kotlin的兩個插件,申明gradle是因為gradle並不是專門給Android開發出來的,如果要使用的話,肯定需要聲明gradle的插件,gradle后面的版本通常是和AS的版本相對應的,申明kotlin是因為這個Android項目是用的kotlin語言,如果采用的是java的話就不會有這個了。
詳解app下的build.gradle文件
查看app下的build.gradle源代碼:
plugins {
id 'com.android.application'
id 'kotlin-android'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.helloworld"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.material:material:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
第一個閉包plugins:
com.android.application:表示是一個應用程序模塊。 kotlin-android:就是一個kotlin的插件,如果要用kotlin來開發,這個插件是必須要的。
第二個閉包是一個很大的閉包 Android,該閉包中嵌套了defaultConfig,buildTypes,compileOptions,kotlinOptions 四個閉包。在Android閉包里面可以配置項目構建的各自屬性,其中compileSdkVersion用來指定項目的編譯版本,指定Android項目的SDK版本,buildToolsVersion用來指定項目構建工具的版本。
Android閉包里的defaulltConfig閉包:
applicationId "com.example.helloworld" //每個應用的唯一標識符,也就是在創建項目時的包名
minSdkVersion 21 //項目最低兼容的Android版本
targetSdkVersion 30 //該字段指定的值用來表示在當前目標版本上已經做好了充分的測試
//指定的值表示在哪一個sdk版本以及之前已經做好了充分的測試。
versionCode 1 //指定項目的版本號
versionName "1.0" //指定項目的版本名
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
//用來在當前項目中七點JUnit測試
Android閉包里的buildTypes閉包:
buildTypes閉包里通常會有兩個子閉包,release和debug,就相當於項目的兩個版本,debug默認可以不用寫。
buildTypes {
release {
minifyEnabled false //用來指定是否對項目的代碼進行混淆
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' //proguardFiles用來指定代碼的混淆規則
//proguard-android-optimize.txt是在<AndroidSDK>/tools/proguard目錄下的一個通用混淆規則
//proguard-rules.pro是在當前項目的根目錄下的,里面可以編寫當前項目特有的代碼混淆規則
}
}
Android剩下的兩個閉包:compileOptions,kotlinOptions都是用來指定java和jvm版本的,沒啥影響。
最后一個閉包:dependencies,這個閉包指定了項目的所有依賴關系。
在Android中的依賴有三種方式:本地依賴,庫依賴,遠程依賴。本地依賴可以對本地的jar包添加,庫依賴可以對項目中的庫模塊添加依賴,遠程依賴則是對於jcenter倉庫上的開源項目進行添加依賴。
implementation fileTree 是本地依賴申明
implementation 表示是一個遠程依賴
implementation project 表明是一個庫依賴
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.appcompat:appcompat:1.1.0'//一個標准的遠程依賴
//androidx.appcomat是域名用來區分其他公司的庫,appcompat是工程名,1.1.0是版本號。
implementation 'com.google.android.material:material:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
分析一個項目的運行流程
分析一下,這里寫的Helloworld項目是如何運行起來的。
首先查看AndroidManifest.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文件中注冊的四大組件是無法使用的),其中intent-filter代碼段里面的兩行代碼最為重要,其作用就是表示MainActivity是這個項目的主Activity,在手機上點擊應用圖標,首先啟動的就是該Activity。
凡是在APP中可以看到的東西,都是Android中的四大組件的Activity中的內容,因此在該HelloWorld項目中看到的彈出來的界面就是MainActivity,查看MainActivity的代碼:

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
可以很清楚地看到MainActivity是繼承了AppCompatActivity這個類的。AppCompatActivity是AndroidX提供的一個向下兼容的Activity,可以讓Activity在不同系統版本中的功能保持一致性。而Activity是Android提供的一個Activity基類,所有自己自定義的Activity都需要繼承於它或它的子類(AppCompatActivity就是它的子類)。然后可以看到該MainActivity類有一個onCreate()函數,這個方法是Activity組件創建時必須要執行的方法,而且只有兩行代碼,可以看到這里並沒有我們使用該APP顯示的HelloWorld字符串,那么顯示的HelloWorld到底在哪里呢?
Android程序設計講究邏輯和視圖分離, 因此一般不要再Activity里面直接編寫界面加邏輯的,更加通用的辦法是:在布局文件中編寫界面,然后再在Activity中引入進來。
在MainActivity類中的onCreate()方法中的第二行調用了setContentView()方法,就是這個方法給當前的Activity引入了一個activity_main布局,那么“Hello World!”就一定在該R.layout.activity_main里面定義的,前面有提到所有的資源在res下,所有的布局文件又在res下的layout里面,所以直接去查看布局文件:
切換成code(代碼)視角:

<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。
總結一個項目的運行流程:進入一個app首先是獲取AndroidManifest.xml文件中注冊的Activity組件,然后看到的是Activity里面的MainActivity,就好比一個C語言程序里面的main函數,然后根據MainActivity里面的代碼邏輯獲取得到布局文件最后展示出來。
如何使用日志工具
在Android里面的日志工具是非常重要的,特別是對於開發者來說,是非常重要的。
Android中的日志工具類是Log(android.util.Log),提供了5個方法來打印日志:
Log.v() | 打印最低級別的日志,對應級別是verbose |
---|---|
Log.d() | 打印一些調試信息,對應級別是debug,比verbose高一級 |
Log.i() | 打印一些比較重要的信息,可以分析用戶行為的數據,對應級別為info,比debug高一級 |
Log.w() | 打印警告信息,對應級別為warn比info高一級 |
Log.e() | 打印錯誤信息,對應級別為error |
在helloworld項目中使用日志工具:在MainActivity.kt里面添加Log.d("MainActivity","onCreate execute")
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d("MainActivity","onCreate execute")
}
}
再在Logcat下面就可以看到日志信息了。
通過過濾器來查看不同的Log信息。
總結