Android -- 應用基礎知識

Android -- 應用基礎知識


來源:應用基礎知識


Android 應用採用 Java 編程語言編寫。Android SDK 工具將您的代碼 — 連同任何數據和資源文件 — 編譯到一個 APK:Android 軟件包,即帶有 .apk 後綴的存檔文件中。一個 APK 文件包含 Android 應用的所有內容,它是基於 Android 系統的設備用來安裝應用的文件。


安裝到設備後,每個 Android 應用都運行在自己的安全沙箱內:

  • Android 操作系統是一種多用戶 Linux 系統,其中的每個應用都是一個不同的用戶;
  • 默認情況下,系統會爲每個應用分配一個唯一的 Linux 用戶 ID(該 ID 僅由系統使用,應用並不知曉)。系統爲應用中的所有文件設置權限,使得只有分配給該應用的用戶 ID 才能訪問這些文件;
  • 每個進程都具有自己的虛擬機 (VM),因此應用代碼是在與其他應用隔離的環境中運行;
  • 默認情況下,每個應用都在其自己的 Linux 進程內運行。Android 會在需要執行任何應用組件時啓動該進程,然後在不再需要該進程或系統必須爲其他應用恢復內存時關閉該進程。

Android 系統可以通過這種方式實現最小權限原則。也就是說,默認情況下,每個應用都只能訪問執行其工作所需的組件,而不能訪問其他組件。 這樣便營造出一個非常安全的環境,在這個環境中,應用無法訪問系統中其未獲得權限的部分。


不過,應用仍然可以通過一些途徑與其他應用共享數據以及訪問系統服務:

  • 可以安排兩個應用共享同一 Linux 用戶 ID,在這種情況下,它們能夠相互訪問彼此的文件。 爲了節省系統資源,可以安排具有相同用戶 ID 的應用在同一 Linux 進程中運行,並共享同一 VM(應用還必須使用相同的證書籤署)。
  • 應用可以請求訪問設備數據(如用戶的聯繫人、短信、可裝載存儲裝置 [SD 卡]、相機、藍牙等)的權限。 用戶必須明確授予這些權限。

以上內容闡述了有關 Android 應用在系統內存在方式的基礎知識。本文的其餘部分將向您介紹以下內容:

  • 用於定義應用的核心框架組件
  • 您用來聲明組件和應用必需設備功能的清單文件
  • 與應用代碼分離並允許您的應用針對各種設備配置適當優化其行爲的資源

應用組件


應用組件是 Android 應用的基本構建基塊。每個組件都是一個不同的點,系統可以通過它進入您的應用。 並非所有組件都是用戶的實際入口點,有些組件相互依賴,但每個組件都以獨立實體形式存在,併發揮特定作用 — 每個組件都是唯一的構建基塊,有助於定義應用的總體行爲。


共有四種不同的應用組件類型。每種類型都服務於不同的目的,並且具有定義組件的創建和銷燬方式的不同生命週期。


以下便是這四種應用組件類型:


Activity


Activity 表示具有用戶界面的單一屏幕。例如,電子郵件應用可能具有一個顯示新電子郵件列表的 Activity、一個用於撰寫電子郵件的 Activity 以及一個用於閱讀電子郵件的 Activity。 儘管這些 Activity 通過協作在電子郵件應用中形成了一種緊密結合的用戶體驗,但每一個 Activity 都獨立於其他 Activity 而存在。 因此,其他應用可以啓動其中任何一個 Activity(如果電子郵件應用允許)。 例如,相機應用可以啓動電子郵件應用內用於撰寫新電子郵件的 Activity,以便用戶共享圖片。


Service


服務是一種在後臺運行的組件,用於執行長時間運行的操作或爲遠程進程執行作業。 服務不提供用戶界面。 例如,當用戶位於其他應用中時,服務可能在後臺播放音樂或者通過網絡獲取數據,但不會阻斷用戶與 Activity 的交互。 諸如 Activity 等其他組件可以啓動服務,讓其運行或與其綁定以便與其進行交互。


ContentProvider


內容提供程序管理一組共享的應用數據。您可以將數據存儲在文件系統、SQLite 數據庫、網絡上或您的應用可以訪問的任何其他永久性存儲位置。 其他應用可以通過內容提供程序查詢數據,甚至修改數據(如果內容提供程序允許)。 例如,Android 系統可提供管理用戶聯繫人信息的內容提供程序。 因此,任何具有適當權限的應用都可以查詢內容提供程序的某一部分(如 ContactsContract.Data),以讀取和寫入有關特定人員的信息。

內容提供程序也適用於讀取和寫入您的應用不共享的私有數據。 例如,記事本示例應用使用內容提供程序來保存筆記。


BroadcastReceiver


廣播接收器是一種用於響應系統範圍廣播通知的組件。 許多廣播都是由系統發起的 — 例如,通知屏幕已關閉、電池電量不足或已拍攝照片的廣播。應用也可以發起廣播 — 例如,通知其他應用某些數據已下載至設備,並且可供其使用。 儘管廣播接收器不會顯示用戶界面,但它們可以創建狀態欄通知,在發生廣播事件時提醒用戶。 但廣播接收器更常見的用途只是作爲通向其他組件的“通道”,設計用於執行極少量的工作。 例如,它可能會基於事件發起一項服務來執行某項工作。


Android 系統設計的獨特之處在於,任何應用都可以啓動其他應用的組件。 例如,如果您想讓用戶使用設備的相機拍攝照片,很可能有另一個應用可以執行該操作,那麼您的應用就可以利用該應用,而不是開發一個 Activity 來自行拍攝照片。 您不需要集成甚至鏈接到該相機應用的代碼,而是隻需啓動拍攝照片的相機應用中的 Activity。 完成拍攝時,系統甚至會將照片返回您的應用,以便您使用。對用戶而言,就好像相機真正是您應用的組成部分。

當系統啓動某個組件時,會啓動該應用的進程(如果尚未運行),並實例化該組件所需的類。 例如,如果您的應用啓動相機應用中拍攝照片的 Activity,則該 Activity 會在屬於相機應用的進程,而不是您的應用的進程中運行。因此,與大多數其他系統上的應用不同,Android 應用並沒有單一入口點(例如,沒有 main() 函數)。


由於系統在單獨的進程中運行每個應用,且其文件權限會限制對其他應用的訪問,因此您的應用無法直接啓動其他應用中的組件, 但 Android 系統卻可以。因此,要想啓動其他應用中的組件,您必須向系統傳遞一則消息,說明您想啓動特定組件的 Intent。 系統隨後便會爲您啓動該組件。


啓動組件


四種組件類型中的三種 — Activity、服務和廣播接收器 — 通過名爲 Intent 的異步消息進行啓動。Intent 會在運行時將各個組件相互綁定(您可以將 Intent 視爲從其他組件請求操作的信使),無論組件屬於您的應用還是其他應用。

Intent 使用 Intent 對象創建,它定義的消息用於啓動特定組件或特定類型的組件 — Intent 可以是顯式的,也可以是隱式的。

對於 Activity 和服務, Intent 定義要執行的操作(例如,“查看”或“發送”某個內容),並且可以指定要執行操作的數據的 URI(以及正在啓動的組件可能需要了解的信息)。 例如, Intent 傳達的請求可以是啓動一個顯示圖像或打開網頁的 Activity。 在某些情況下,您可以啓動 Activity 來接收結果,在這種情況下,Activity 也會在 Intent 中返回結果(例如,您可以發出一個 Intent,讓用戶選取某位聯繫人並將其返回給您 — 返回 Intent 包括指向所選聯繫人的 URI)。

對於廣播接收器, Intent 只會定義要廣播的通知(例如,指示設備電池電量不足的廣播只包括指示“電池電量不足”的已知操作字符串)。

Intent 不會啓動另一個組件類型 - ContentProvider,後者會在成爲 ContentResolver 的請求目標時啓動。 內容解析程序通過內容提供程序處理所有直接事務,使得通過提供程序執行事務的組件可以無需執行事務,而是改爲在 ContentResolver 對象上調用方法。 這會在內容提供程序與請求信息的組件之間留出一個抽象層(以確保安全)。

每種類型的組件有不同的啓動方法:

  • 您可以通過將 Intent 傳遞到 startActivity() 或 startActivityForResult()(當您想讓 Activity 返回結果時)來啓動 Activity(或爲其安排新任務)。
  • 您可以通過將 Intent 傳遞到 startService() 來啓動服務(或對執行中的服務下達新指令)。 或者,您也可以通過將 Intent 傳遞到 bindService() 來綁定到該服務。
  • 您可以通過將 Intent 傳遞到 sendBroadcast()、sendOrderedBroadcast() 或 sendStickyBroadcast() 等方法來發起廣播;
  • 您可以通過在 ContentResolver 上調用 query() 來對內容提供程序執行查詢。

清單文件


在 Android 系統啓動應用組件之前,系統必須通過讀取應用的 AndroidManifest.xml 文件(“清單”文件)確認組件存在。 您的應用必須在此文件中聲明其所有組件,該文件必須位於應用項目目錄的根目錄中。

除了聲明應用的組件外,清單文件還有許多其他作用,如:
  • 確定應用需要的任何用戶權限,如互聯網訪問權限或對用戶聯繫人的讀取權限
  • 根據應用使用的 API,聲明應用所需的最低 API 級別
  • 聲明應用使用或需要的硬件和軟件功能,如相機、藍牙服務或多點觸摸屏幕
  • 應用需要鏈接的 API 庫(Android 框架 API 除外),如 Google 地圖庫
  • 其他功能

聲明組件


清單文件的主要任務是告知系統有關應用組件的信息。例如,清單文件可以像下面這樣聲明 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> 元素
  • 內容提供程序的 <provider> 元素
您包括在源代碼中,但未在清單文件中聲明的 Activity、服務和內容提供程序對系統不可見,因此也永遠不會運行。 不過,廣播接收器可以在清單文件中聲明或在代碼中動態創建(如 BroadcastReceiver 對象)並通過調用 registerReceiver() 在系統中註冊。

聲明組件功能


如上文啓動組件中所述,您可以使用 Intent 來啓動 Activity、服務和廣播接收器。 您可以通過在 Intent 中顯式命名目標組件(使用組件類名)來執行此操作。 不過,Intent 的真正強大之處在於隱式 Intent 概念。 隱式 Intent 的作用無非是描述要執行的操作類型(還可選擇描述您想執行的操作所針對的數據),讓系統能夠在設備上找到可執行該操作的組件,並啓動該組件。 如果有多個組件可以執行 Intent 所描述的操作,則由用戶選擇使用哪一個組件。

系統通過將接收到的 Intent 與設備上的其他應用的清單文件中提供的 Intent 過濾器進行比較來確定可以響應 Intent 的組件。

當您在應用的清單文件中聲明 Activity 時,可以選擇性地加入聲明 Activity 功能的 Intent 過濾器,以便響應來自其他應用的 Intent。 您可以通過將 <intent-filter> 元素作爲組件聲明元素的子項進行添加來爲您的組件聲明 Intent 過濾器。

例如,如果您開發的電子郵件應用包含一個用於撰寫新電子郵件的 Activity,則可以像下面這樣聲明一個 Intent 過濾器來響應“send” 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 操作的 Intent,並將其傳遞到 startActivity(),則系統可能會啓動您的 Activity,以便用戶能夠草擬併發送電子郵件。

聲明應用要求


基於 Android 系統的設備多種多樣,並非所有設備都提供相同的特性和功能。 爲防止將您的應用安裝在缺少應用所需特性的設備上,您必須通過在清單文件中聲明設備和軟件要求,爲您的應用支持的設備類型明確定義一個配置文件。 其中的大多數聲明只是爲了提供信息,系統不會讀取它們,但 Google Play 等外部服務會讀取它們,以便當用戶在其設備中搜索應用時爲用戶提供過濾功能。

例如,如果您的應用需要相機,並使用 Android 2.1(API 級別 7)中引入的 API,您應該像下面這樣在清單文件中以要求形式聲明這些信息:
<manifest ... >
    <uses-feature android:name="android.hardware.camera.any"
                  android:required="true" />
    <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" />
    ...
</manifest>
現在,沒有相機且 Android 版本低於 2.1 的設備將無法從 Google Play 安裝您的應用。

不過,您也可以聲明您的應用使用相機,但並不要求必須使用。 在這種情況下,您的應用必須將 required 屬性設置爲 "false",並在運行時檢查設備是否具有相機,然後根據需要停用任何相機功能。

應用資源


Android 應用並非只包含代碼 — 它還需要與源代碼分離的資源,如圖像、音頻文件以及任何與應用的視覺呈現有關的內容。 例如,您應該通過 XML 文件定義 Activity 用戶界面的動畫、菜單、樣式、顏色和佈局。 使用應用資源能夠在不修改代碼的情況下輕鬆地更新應用的各種特性,並可通過提供備用資源集讓您能夠針對各種設備配置(如不同的語言和屏幕尺寸)優化您的應用。

對於您的 Android 項目中包括的每一項資源,SDK 構建工具都會定義一個唯一的整型 ID,您可以利用它來引用應用代碼或 XML 中定義的其他資源中的資源。 例如,如果您的應用包含一個名爲 logo.png 的圖像文件(保存在 res/drawable/ 目錄中),則 SDK 工具會生成一個名爲 R.drawable.logo 的資源 ID,您可以利用它來引用該圖像並將其插入您的用戶界面。

提供與源代碼分離的資源的其中一個最重要優點在於,您可以提供針對不同設備配置的備用資源。 例如,通過在 XML 中定義 UI 字符串,您可以將字符串翻譯爲其他語言,並將這些字符串保存在單獨的文件中。 然後,Android 系統會根據向資源目錄名稱追加的語言限定符(如爲法語字符串值追加 res/values-fr/)和用戶的語言設置,對您的 UI 應用相應的語言字符串。

Android 支持許多不同的備用資源限定符。限定符是一種加入到資源目錄名稱中,用來定義這些資源適用的設備配置的簡短字符串。 再舉一例,您應該經常會根據設備的屏幕方向和尺寸爲 Activity 創建不同的佈局。 例如,當設備屏幕爲縱向(長型)時,您可能想要一種垂直排列按鈕的佈局;但當屏幕爲橫向(寬型)時,應按水平方向排列按鈕。 要想根據方向更改佈局,您可以定義兩種不同的佈局,然後對每個佈局的目錄名稱應用相應的限定符。 然後,系統會根據當前設備方向自動應用相應的佈局。

發佈了72 篇原創文章 · 獲贊 68 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章