標籤:
Application Fundamentals
英文原文:http://developer.android.com/guide/components/fundamentals.html
採集日期:2014-04-16
搬遷自原部落格:http://blog.sina.com.cn/s/blog_48d491300101h41p.html
在本文中
- 應用程式組件
- 啟用組件
- Manifest 檔案
- 聲明組件
- 聲明應用程式的需求
- 應用程式資源
Android 應用程式是用 Java 語言編寫的。Android SDK 工具軟體會把代碼—連同資料、資源檔—一起編譯並放入 APK:Android 包中,這是個尾碼為.apk的打包檔案。APK 檔案裡包含了 Android 應用程式需要的所有內容,同時也是在 Android 裝置上安裝該應用程式所用到的安裝檔案。
安裝完成後,每個 Android 應用程式就獨立運行於各自的安全沙箱中:
- Android 作業系統是一個多使用者的 Linux 系統,其中的每個應用程式都是一個獨立的使用者。
- 預設情況下,系統將給每個應用程式賦予一個唯一的 Linux 使用者識別碼(該 ID 僅供系統使用,對應用程式是不可見的)。系統將對應用程式內的所有檔案分配許可權,只有賦予該應用程式的使用者識別碼 才能訪問這些檔案。
- 每個進程都擁有自己的虛擬機器(VM),因此不同應用程式的代碼是相互獨立啟動並執行。
- 預設情況下,每個應用程式運行於自己的 Linux 進程中。每當需要運行應用程式的某個組件時,Android 就會啟動進程,並在不再需要時或必須為其他應用程式騰出記憶體時關閉進程。
這樣,Android 系統實現了最小許可權原則。也就是說,每個應用程式預設只訪問必要的組件。這就建立了一種非常安全的環境,這裡的應用程式無法訪問未授權的系統內容。
不過,應用程式還是有很多方法與其他應用程式共用資料或訪問系統服務的:
- 可以讓兩個應用程式共用同一個 Linux 使用者識別碼,這樣它們就可以相互訪問檔案了。為了節省系統開銷,使用者識別碼 相同的應用程式還可以運行於同一個 Linux 進程中,並且共用同一個 VM(這些應用程式還須由同一個認證簽名)。
- 應用程式可以申請訪問裝置資料的許可權,諸如使用者通訊錄、簡訊、可掛載儲存(SD卡)、網路攝影機、藍芽等等。所有應用程式的許可權都必須在安裝時由使用者授權。
上面簡述了 Android 應用程式是如何在系統中啟動並執行。本文剩餘部分將介紹:
- 建立應用程式所需的主要組件。
- 用於聲明組件和所需硬體的 manifest 檔案。
- 與代碼分離的資源,使得應用程式可以根據各種硬體設定來友好地展示介面。
應用程式組件
組件(component)是搭建 Android 應用程式的基礎組件。每個組件都是一個獨立的進入點,系統可以通過它們進入你的應用程式。不是每個組件都是供使用者使用的入口,有些組件是相互依存的,但每個組件都作為實體運行並發揮特定的作用—每個組件都是唯一的組成部分,為應用程式的整體表現出力。
應用程式組件分為四種類型。每類組件實現不同的目標,擁有各不相同的從建立到消亡的生命週期。
下面介紹這四種類型的應用程式組件:
-
Activity
-
Activity代表一個包含了使用者介面的螢幕(視窗)。比如,一個 email 應用程式可能會包含一個顯示未讀郵件清單的 Activity、一個撰寫郵件的 Activity 及一個閱讀郵件的 Activity。雖然該 email 應用程式中由多個 Activity 一起構成了完整的使用者體驗,但是每個 Activity 都是相互獨立的。因此,另一個應用程式可以啟動其中任意一個 Activity(如果該 email 應用程式允許的話)。例如,為了讓使用者能分享照片,某個拍照應用可以啟動該 email 應用程式的 Activity 來撰寫一封新郵件。
Activity 實現為Activity對象的一個子類,更多內容請參閱開發指南中的Activity。
-
服務
-
服務 是一種後台啟動並執行組件,用於執行已耗用時間較長的操作,或是為遠程進程提供服務。服務不提供使用者介面。例如:當使用者使用其他應用程式時,服務可以在背景播放音樂,或者可以通過網路下載資料,這些都不需要用 Activity 與使用者進行互動。其他組件,比如 Activity,可以啟動並運行服務,也可以與之綁定以便互動。
服務是作為 Service 對象的子類來實現的,你可以在開發人員指南的Services 中瞭解更多內容。
-
Content Provider
-
Content Provider 管理著某個可共用的應用程式資料集。你可以把資料儲存在檔案系統、SQLite 資料庫、Web、或其他任何應用程式可訪問的持久性儲存上。通過 Content Provider,其他應用程式可以查詢甚至修改資料(如果 Content Provider 允許的話)。例如,Android 系統就提供了一個系統管理使用者通訊錄資訊的 Content Provider。這樣,任何擁有適當許可權的應用程式就都可以查詢該通訊錄 Content Provider 裡的某部分資料(比如
ContactsContract.Data),以便讀寫某個連絡人的資訊。
對於讀寫應用程式私人的資料而言,Content Provider 也很有用。比如,常式 Note Pad 就使用了一個 Content Provider 來儲存筆記。
Content Provider 是作為 ContentProvider的子類實現的,且必須實現一組標準的 API,以便其他應用程式能提交事務。詳情請參閱開發人員指南的 Content Providers 部分。
-
廣播接收器
-
廣播接收器 是一種響應系統級廣播資訊的組件。很多廣播都來源於系統 — 比如螢幕已關閉、電池電量低、拍了一張照片等訊息通知。應用程式也可以發起廣播 — 比如通知另一個程式所需資料已經下載到本地裝置並已可用。儘管廣播接收器不顯示使用者介面,但在廣播事件發生時它可以建立一條狀態列通知來通知使用者。不過,更多時候,廣播接收器僅僅是為其他組件充當“入口”,用於完成很少量的工作。例如,它可以初始化一個服務,根據廣播事件來完成某些任務。
廣播接收器是作為BroadcastReceiver對象的子類實現的,每條被分發的廣播都是一個Intent對象。更多資訊請參閱BroadcastReceiver類。
Android 系統有一條獨特的設計,就是任何應用程式都能啟動其他應用程式的組件。例如,假設你要讓使用者使用網路攝影機拍照,而其他應用程式已經實現這一功能,你的應用程式就可以直接使用,而不需要自行開發一個 Activity 來完成拍照功能。你甚至不必包含或連結網路攝影機應用的代碼,而只要啟動網路攝影機應用中的拍照 Activity 即可。拍攝完成後,照片甚至都會直接返回給你的應用程式以便使用。對於使用者而言,網路攝影機應用就像是你的應用程式中的一部分一樣。
當啟動一個組件時,系統會啟動相關應用程式的進程(如果該程式還未啟動並執行話),並且執行個體化組件所需的類。例如,如果你的應用程式啟動了網路攝影機應用中的拍照 Activity,則此 Activity 運行於網路攝影機應用的進程中,而不是你的應用程式的進程。因此,與其他大多數系統不同,Android 應用程式不存在一個單一的進入點(比如沒有main()函數)。
因為系統把每個應用程式都放入相互獨立的進程中運行,檔案許可權限制了對其他應用的訪問,你的應用程式不可能直接啟動其他應用的組件。但是 Android 系統可以這麼做。因此,要啟用其他應用的組件,你必須向系統分發一條訊息,其中設定了要啟用某個組件的 Intent。然後,系統就會為你啟動該組件。
啟用組件
在四種類型的組件中,有三種 — Activity、服務和廣播接收器 — 都是由名為 Intent 的非同步訊息啟用的。在運行時,Intent 與某個組件相互綁定(你可以將它們看作是來自其他組件的執行某個操作的請求訊息),無論此組件是屬於你的應用自身還是其他應用。
Intent 是用 Intent 對象建立的,定義了一個啟用某個或某類組件(Intent 分別是顯式或隱式的)的訊息。
對於 Activity 和服務而言,Intent 定義了所要執行的操作(比如:“查看”或“發送”資訊),並可以指定所操作資料的 URI(所要啟用的組件可能會需要知道)例如,某 Intent 可能會發送一個請求,要讓某個 Activity 顯示一張圖片或者開啟一個網頁。某些時候,你要啟動一個 Activity 並接收結果,這時 Activity 還要在 Intent 中返回結果(例如,你可以提交一個 Intent 來讓使用者選取某個連絡人並返回資料 — 返回的 Intent 包含了一個指向連絡人資訊的 URI)。
對於廣播接收器而言,Intent 只是簡單地定義了要廣播的訊息(例如,一條表示電量不足的廣播可以僅包含一個“電量不足”字串。
剩下一類組件 Content Provider,不是由 Intent 啟用的。而是由 ContentResolver 發出的請求啟動。Content Resolver 負責處理 Content Provider 所有的事務,因此需要執行事務的組件不必去調用ContentResolver對象的方法。這就在 Content Provider 和請求資料的組件之間建立一個抽象層(處於安全考慮)。
每種組件都有各自的啟用方法:
- 通過把
Intent 傳入 startActivity()或startActivityForResult()(如果需要返回結果的話),可以啟動某個 Activity (或者讓它執行某些新任務)。
- 通過把
Intent 傳入startService(),你可以啟動某個服務(或者給已有的服務發布新的指令)。或者可以把Intent 傳入bindService(),以綁定某個服務。
- 通過給
sendBroadcast()、sendOrderedBroadcast()或sendStickyBroadcast()之類的方法傳入一個 Intent ,你可以初始化一條廣播訊息。
- 通過調用
ContentResolver 的 query() 方法,你可以在 Content Provider 上執行一條查詢。
關於 Intent 的更多資訊,請參閱文檔Intents 和 Intent 過濾器。關於啟用組件的更多資訊,在以下文檔中也有涉及:Activity、服務、BroadcastReceiver和Content Provider。
Manifest 檔案
在啟動一個應用程式組件之前,Android 系統必須知道組件的存在,這是通過讀取應用程式的 AndroidManifest.xml 檔案(“Manifest”檔案)來實現的。該檔案必須位於項目的根目錄,應用程式必須在該檔案中聲明所有的組件。
除了聲明應用程式組件之外,Manifest 檔案還有其他一些用途,比如:
- 確定應用程式所需的使用者權限,如訪問 Internet 或 讀寫使用者通訊錄
- 聲明應用程式需要的最小版本API Level,表明應用程式將使用此版本的 API。
- 聲明應用程式的的硬體和軟體需求,諸如:網路攝影機、藍芽服務和多點觸屏。
- 應用程式需要連結的 API 庫(Android 系統 API 之外的庫),如:Google Maps library。
- 其他
聲明組件
Manifest 檔案的主要用途是把應用程式的組件告知系統。例如:Manifest 檔案可以聲明一個 Activity 如下:
<?xml version="1.0" encoding="utf-8"?><manifest ... > <application android:icon="@drawable/app_icon.png" ... > <activity android:name="com.example.project.ExampleActivity" android:label="@string/example_label" ... > </activity> ... </application></manifest>
在 < application > 元素中,android:icon 屬性指向了一個標識該應用程式的表徵圖資源,。
在 < activity > 元素中, android:name 屬性設定了 Activity 子類的完全限定類名, android:label 屬性設定了一個用作 Activity 標題的字串。
必須按照以下規則聲明應用程式的全部組件:
- 用於 Activity 的
< activity > 元素
- 用於服務的
< service > 元素
- 用於廣播接收器的
< receiver > 元素
- 用於 Content Provider 的
< provider > 元素
如果你的代碼中用到了某些 Activity、服務和 Content Provider,但沒有在 Manifest 檔案中聲明,那麼系統是看不見這些組件的,因此它們也就無法生效。 不過,廣播接收器既可以在 Manifest 檔案中進行聲明,也可以用代碼動態建立( 建立為 BroadcastReceiver 對象)並用 registerReceiver() 進行註冊。
關於構建 Manifest 檔案的更多資訊,請參閱文檔 AndroidManifest.xml 檔案
聲明組件的相容性
正如 啟用組件 部分所述,你可以用一個 Intent 來啟動Activity、服務和廣播接收器。你可以在 Intent 中使用顯式命名的目標組件(用組件的類名)啟動。 不過,Intent 真正的強大之處在於 隱式 Intent 的理念。 隱式 Intent 只要說明需執行的 Action 類型即可(還可附帶 Action 用到的資料),系統可籍此在裝置上尋找可執行此 Action 的組件並啟之。 如果同時存在多個組件都可以執行此 Action,則可以由使用者選用一個。
通過將接收到的 Intent 和其他應用程式的 Manifest 檔案給出中的 Intent 過濾器 進行比較,系統識別出可以響應 Intent 的組件。
當在應用程式的 Manifest 檔案中聲明 Activity 時,你還可以包含 Intent 過濾器,用於聲明該 Activity 可以響應來自其他應用程式的 Intent。 通過在組件聲明元素下添加一個子項目 < intent-filter > ,可以為該組件聲明一個 Intent 過濾器。
例如,如果你已經建立了一個 Email 應用程式,其中帶有一個撰寫新郵件的 Activity, 你就可以聲明一個響應”send“ 類型 Intent(用於發送新郵件)的 Intent 過濾器如下:
<manifest ... > ... <application ... > <activity android:name="com.example.project.ComposeEmailActivity"> <intent-filter> <action android:name="android.intent.action.SEND" /> <data android:type="*/*" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> </application></manifest>
然後,如果其他應用程式建立了一個 ACTION_SEND 類型的 Action,並傳給 startActivity(), 系統就可以啟動你的Activity,使用者就可以起草並發送一封 Email 了。
關於建立 Intent 過濾器的更多資訊,請參閱文檔 Intent 和 Intent 過濾器。
聲明應用程式需求
Android 支援多種裝置,這些裝置並不是全都提供相同的硬體設定。 為了防止在不提供相應硬體的裝置上安裝你的應用程式,清晰地定義一個設定檔相當重要,這在 Manifest 檔案中聲明軟硬體需求即可實現。 絕大部分聲明僅僅是報告性質的,系統不會去讀取它們。 但為了能讓使用者在搜尋應用程式時按照硬體裝置進行過濾,類似 Google Play 之類的外部服務將會讀取這些資訊。
例如,如果你的應用程式需要用到網路攝影機和 Android 2.1 以上的 API( API Level 7), 你就在 Manifest 檔案中進行如下聲明:
<manifest ... > <uses-feature android:name="android.hardware.camera.any" android:required="true" /> <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" /> ...</manifest>
現在,不提供網路攝影機的裝置和低於2.1版本的 Android 就無法通過 Google Play 安裝你的應用程式了。 Now, devices that do not have a camera and have an
不過,你還可以聲明應用程式要使用網路攝影機但不是必需使用。 這時,你的應用程式必須將 required 設為 "false" ,並且在運行時檢測是否存在網路攝影機,以便適時禁用與之有關的功能。
關於如何讓應用程式保持與各種裝置的相容性,文檔 裝置相容性 中給出了更為詳細的資訊。
應用程式資源
Android 應用程式並不僅僅由原始碼構成 — 還需要用到資源檔,片、音頻檔案和其他所有的可視化內容,這些都是與原始碼相分離的。 例如,你需要用 XML 檔案定義動畫、菜單、顏色、Activity 使用者介面的 Layout。 資源檔使你不用修改原始碼就可以方便地更換應用程式的外表 — 通過給出替代資源集 — ,你可以根據各種裝置配置(比如不同的語言和螢幕尺寸)來最佳化應用程式。
SDK 編譯工具會為 Android 項目中的每個資源都定義一個唯一的整數型 ID,以便從原始碼或 XML 格式的其他資源中引用該資源。 例如,假設應用程式中包含一個名為 logo.png 的圖片檔案(儲存在 res/drawable/ 目錄中), SDK 編譯工具將會建立一個名為 R.drawable.logo 的唯一ID,你可以用此 ID 來引用該圖片並把它放到使用者介面中去。
要將資源檔從原始碼中分離出來,要點之一是為各種裝置配置給出不同的替代資源。 例如,通過定義 XML 格式的用於使用者介面的字串,你可以把字串翻譯為其他語言並儲存到單獨的檔案中。 然後,根據資來源目錄名後面跟隨的語言標識符(如法語字串就是 res/values-fr/),以及使用者的語言設定, Android 系統將會把相應語言的字串應用到使用者介面中。
Android 對替代資源提供多種不同的 標識符。 為了定義某資源所需的裝置配置,標識符即為該資來源目錄名中的短字串。 再舉個例子,根據裝置的螢幕方向和尺寸,通常需要為 Activity 建立多種不同的 Layout。 比如,當裝置螢幕是縱向放置時(高度較大),也許需要讓按鈕縱向布局。 而當螢幕橫向放置時(寬度較大),按鈕就應該橫向對齊了。 要能根據螢幕方向來改變布局,你可以定義兩個 Layout,並用合適的標識符為 Layout 目錄命名。 這樣,系統就能根據當前裝置方向自動選用合適的 Layout。
關於應用程式可用的各種資源,以及如何為各種裝置配置建立替代資源,更多資訊請參閱 提供資源。
後續閱讀:
-
Intent 和 Intent 過濾器
-
有關用
Intent API 啟用諸如 Activity 和服務之類的應用程式組件、讓組件可被其他應用程式使用等內容。
-
Activity
-
有關建立
Activity 類的執行個體等內容。Activity 在應用程式中給出某個包含使用者介面的視窗。
-
提供資源
-
有關資源和原始碼分離的 Android 應用程式架構,包括為某種裝置配置提供替代資源等內容。
還可能感興趣:
-
裝置相容性
-
有關在各種型號裝置上運行 Android 的資訊,以及為每種裝置最佳化程式或者限制功能。
-
系統許可權
-
Android 通過一套授權系統對應用程式訪問某些 API 進行的限制,使用者由此授權系統同意應用程式使用這些 API。
Android開發-API指南-應用程式開發基礎