Android Intent篩檢程式

Android Intent 是承載一個意圖,即對象。將消息從一個組件傳到另一個組件,在應用程式或應用程式之外。Intent 之間溝通資訊的任何應用程式的三個核心組件 - 活動,服務和廣播接收器。

意圖本身是一個Intent對象,是一種被動的數據結構保持將要執行的動作的抽象描述。

例如,讓我們假設有一個Activity ,需要啟動電子郵件客戶端和發送電子郵件,使用Android設備。為了達到這個目的,Activity會隨著適當選擇器,一個ACTION_SEND發送到 Android Intent 解析器。指定的選擇器提供適當的介面供用戶選擇如何發送電子郵件數據。

例如,有一個Activity ,需要在 Android 設備上用Web流覽器打開網址。為了達到這個目的Activity將發送ACTION_WEB_SEARCH Intent 到Android Intent 解析器,並在Web流覽器中打開給定的URL。Intent 解析器解析通過一個活動列表,並選擇一個最合適的 Intent ,在這種情況下,就是Web流覽器活動。Intent通過網頁解析後,網頁流覽器啟動 Web 流覽器活動。

分開機制對於每種類型的組件提供意圖,如:活動,服務和廣播接收器。

S.N. 方法& 描述
1 Context.startActivity() 
Intent對象傳遞給此方法來啟動一個新的活動或獲得現有活動來做一些新的東西。
2 Context.startService() 
Intent對象傳遞給此方法來啟動服務或提供新的指令到一個持續的服務。
3 Context.sendBroadcast() 
Intent對象傳遞給這個方法消息給所有感興趣的廣播接收器。

Intent對象

Intent對象是成捆的資訊,這些資訊所使用的組件,它接收的意圖和Android系統中的資訊。

Intent對象可以基於它是什麼交流或要執行,包含以下組件:

動作

強制Intent對象是一個字串,命名要執行操作或廣播意圖,正在發生的動作和報告。動作在很大程度上決定意圖對象的其餘部分的結構如何。Intent類定義了一些動作常數對應不同的意圖。下麵列出的是 Android Intent標準動作

動作在一個Intent對象的 setAction() 方法可以設置,通過 getAction() 方法讀取。

數據

要採取動作的數據的URI和該數據的MIME類型。例如,如果動作字段ACTION_EDIT,在數據字段將包含要顯示的編輯的文檔的URI。

setData()方法指定數據僅作為URI的setType()指定它只能作為一個MIME類型,和setDataAndType()指定它作為一個URI和MIME類型。讀取的URI由getData()和getType()。

操作/數據對的一些例子是:

S.N. 動作/數據對和說明
1 ACTION_VIEW content://contacts/people/1 
顯示有關其識別字為“1”的人的資訊。
2 ACTION_DIAL content://contacts/people/1 
顯示電話撥號程式已填充的人。
3 ACTION_VIEW tel:123 
顯示電話撥號程式已填充的給定數。
4 ACTION_DIAL tel:123 
顯示電話撥號程式已填充的給定數。
5 ACTION_EDIT content://contacts/people/1 
編輯有關其識別字為“1”的人的資訊。
6 ACTION_VIEW content://contacts/people/ 
顯示人的列表,用戶可以流覽。

類別

類別是 Intent 對象一個可選部分,這是一個字串,其中包含應該處理這個 Intent 組件的附加資訊。 addCategory()方法將類別添加到 Intent對象,removeCategory() 刪除一個類別,GetCategories() 得到當前在對象的所有類別集合。下麵是 Android意圖標準類別 列表。

要查看詳細的 Intent篩檢程式可在下一小節,瞭解如何使用類別,選擇合適的活動對應的意圖。

附加設備

這是鍵-值對,可瞭解更多傳遞組件處理 intent 的資訊。額外內容設置和讀取使用 putExtras() 和 getExtras() 方法。這裏是一個 Android intent 標準額外數據列表。

標誌位

這些標誌是Intent對象可選部分,並指示Android系統如何啟動一個活動以及如何對待它在啟動後等等。

組件名稱

可選字段是一個 android 組件名稱的活動,服務或BroadcastReceiver類對象。如果它沒有被設置,Android使用Intent 對象的資訊,找到一個合適的目標,Intent 對象傳遞到指定類的一個實例。

組件名稱由setComponent(),setClass()設置,由 setClassName()和 getComponent()讀取。

Intents類型

有以下兩種類型的意圖支持到 Android 4.1版本

顯式意圖

顯示意圖指定目標組件的名稱,通常用於應用程式內部消息 - 比如一個活動啟動從​​服務或啟動一個組活動。例如:

// Explicit Intent by specifying its class name
Intent i = new Intent(this, TargetActivity.class);
i.putExtra("Key1", "ABC");
i.putExtra("Key2", "123");

// Starts TargetActivity
startActivity(i);

隱式意圖

這些意圖由其的名字指定目標組件,它們通常用於應用程式內部消息 - 例如一個活動啟動一個附屬服務或啟動一個姐妹的活動。例如:

// Implicit Intent by specifying a URI
Intent i = new Intent(Intent.ACTION_VIEW,
Uri.parse("http://www.example.com"));

// Starts Implicit Activity
startActivity(i); 

目標組件接收的意圖可以使用getExtras()方法來獲得組件發送額外的數據源。例如:

// Get bundle object at appropriate place in your code
Bundle extras = getIntent().getExtras();

// Extract data using passed keys
String value1 = extras.getString("Key1");
String value2 = extras.getString("Key2");

例子

下麵的例子展示了Android意圖的功能,啟動各種 Android 的內置應用。

步驟 描述
1 使用Eclipse IDE創建Android應用程式,並將其命名為IntentDemo在com.example.intentdemo包下。在創建這個專案,請確保目標SDK並編譯在Android SDK的最新版本為使用更高級別的API。
2 修改 src/MainActivity.java 檔,並添加代碼來定義相應的兩個按鈕,即兩個監聽器。啟動流覽器,並打開電話。
3 修改佈局XML檔res/layout/activity_main.xml添加三個按鈕的設置為線性佈局。
4 修改 res/values/strings.xml 中定義所需的常量值
5 運行該應用程式啟動Android模擬器來驗證應用程式所做的修改結果。

以下是修改主要活動檔 src/com.example.intentdemo/MainActivity.java 的內容:

package com.example.intentdemo;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      Button startBrowser = (Button) findViewById(R.id.start_browser);
      startBrowser.setOnClickListener(new View.OnClickListener() {
         public void onClick(View view) {
            Intent i = new Intent(android.content.Intent.ACTION_VIEW,
            Uri.parse("http://www.example.com"));
            startActivity(i);
         }
      });
      Button startPhone = (Button) findViewById(R.id.start_phone);
      startPhone.setOnClickListener(new View.OnClickListener() {
         public void onClick(View view) {
            Intent i = new Intent(android.content.Intent.ACTION_VIEW,
            Uri.parse("tel:9510300000"));
            startActivity(i);
         }
      });
   }
   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
      // Inflate the menu; this adds items to the action 
      // bar if it is present.
      getMenuInflater().inflate(R.menu.main, menu);
      return true;
   }

}

下麵是 res/layout/activity_main.xml 檔的內容:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:orientation="vertical" >

   <Button android:id="@+id/start_browser"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="@string/start_browser"/>

   <Button android:id="@+id/start_phone"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="@string/start_phone" />

</LinearLayout>

下麵 res/values/strings.xm 定義兩個新的常量的內容:

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">IntentDemo</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
    <string name="start_browser">Start Browser</string>
    <string name="start_phone">Start Phone</string>

</resources>

以下是 AndroidManifest.xml 檔的默認內容:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.intentdemo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.intentdemo.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

現在運行 IntentDemo應用程式。假設創建AVD同時做正確的環境設置。要從Eclipse運行的應用程式,打開一個專案的活動檔,並 從工具欄上單擊“Run” Eclipse Run Icon圖示。 Eclipse AVD安裝的應用程式,並啟動它,如果一切都設置和應用沒有問題,它會顯示以下模擬器窗口:

Android Intent Screen

現在點擊開始流覽按鈕,這將啟動一個流覽器配置並顯示 http://www.example.com 如下所示:

Android Intent Browser

類似的方式,可以啟動手機介面使用開始電話按鈕,這允許撥打已經給定的電話號碼。

Intent篩檢程式

上面已經看到了意圖如何用來調用一個活動。 Android操作系統使用篩檢程式來查明活動,服務和廣播接收器能夠處理指定的一組動作,類別。使用 <intent-filter> 元素在 manifest 檔中,列出了動作,類別和數據類型相關聯的活動,服務或廣播接收器。

以下是 AndroidManifest.xml 檔中的一部分,指定活動 com.example.intentdemo.CustomActivity 的兩個動作,類和數據,下麵是可以調用的一個例子:

<activity android:name=".CustomActivity"
   android:label="@string/app_name">
   <intent-filter>
      <action android:name="android.intent.action.VIEW" />
      <action android:name="com.example.intentdemo.LAUNCH" />
      <category android:name="android.intent.category.DEFAULT" />
      <data android:scheme="http" />
   </intent-filter>
</activity>

活動的定義是隨著上面提到的篩檢程式,活動將使用 android.intent.action.VIEW com.example.intentdemo.LAUNCH 動作提供其類別來調用這個活動,否則使用android.intent.category.DEFAULT

<data> 元素活動被稱為指定數據類型,上面的例子中自定義活動的數據以 "http://" 開始

有可能在只是一個意圖的情況下,可以通過一個以上的活動或服務的篩檢程式,用戶可能會被要求指定啟動哪個組件。可以發現如果沒有指定目標,則會引發異常。

以下測試 Android 檢查在調用活動前:

  • 如上圖所示,但這個列表不能為空,可能會列出多個篩檢程式<intent-filter>動作,一個篩檢程式必須至少包含一個<action>元素,否則會阻止所有意圖。如果有一個以上的動作列出,那麼Android將嘗試匹配在調用活動之前所提到的其中一個動作。

  • 篩檢程式<intent-filter>可能列出零個,一個或一個以上。如果沒有類被提到,Android也能通過這個測試,但如果超過一個類提到通過類的測試意圖,在篩檢程式中,每一個類中的Intent對象必須符合一個類。

  • 每個<data>元素可以指定一個URI和數據類型(MIME媒體類型)。單獨的屬性,如方案,主機,端口和路徑URI的每個部分。同時包含URI和數據類型的一個Intent對象通過測試,只有當它的類型在篩檢程式列出的類型相匹配數據類型的一部分。

例子

下麵是修改上面例子的一個例子。在這裏將看到 Android 如何解決衝突,如果一個意圖調用定義了兩個活動,接下來如何調用自定義活動使用一個篩檢程式,第三個是一個在例外情況下,如果 Android 不提交適當的活動意圖定義。

步驟 描述
1 使用Eclipse IDE創建 Android 應用程式,並將其命名為 IntentDemo 在一個包com.example.intentdemo下。在創建這個專案前,確保目標SDK編譯在Android SDK的最新版本或使用更高級別的API。
2 修改 src/MainActivity.java 檔,並添加代碼來定義相應的佈局檔中定義了三個按鈕的監聽器。
3 添加一個新的 src/CustomActivity.java 檔,將由不同的意圖來調用一個自定義的活動。
4 修改佈局XML檔res/layout/activity_main.xml 添加三個按鈕的線性佈局。
5 添加一個佈局XML檔res/layout/custom_view.xml,在其中添加一個簡單的<TextView>來顯示通過意圖傳遞的數據。
6 修改 res/values/strings.xml 定義所需的常量值
7 修改 AndroidManifest.xml 添加 <intent-filter> 定義規則,來自定義意圖調用活動。
8 運行該應用程式啟動Android模擬器,並確認在應用修改變化的結果。

以下是內容是修改了主要活動檔 src/com.example.intentdemo/MainActivity.java.

package com.example.intentdemo;

import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity {

   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      // First intent to use ACTION_VIEW action with correct data
      Button startBrowser_a = (Button) findViewById(R.id.start_browser_a);
      startBrowser_a.setOnClickListener(new View.OnClickListener() {
         public void onClick(View view) {
            Intent i = new Intent(android.content.Intent.ACTION_VIEW,
            Uri.parse("http://www.example.com"));
            startActivity(i);
         }
      });

      // Second intent to use LAUNCH action with correct data
      Button startBrowser_b = (Button) findViewById(R.id.start_browser_b);
      startBrowser_b.setOnClickListener(new View.OnClickListener() {
         public void onClick(View view) {
            Intent i = new Intent("com.example.intentdemo.LAUNCH",
            Uri.parse("http://www.example.com"));
            startActivity(i);
         }
      });

      // Third intent to use LAUNCH action with incorrect data
      Button startBrowser_c = (Button) findViewById(R.id.start_browser_c);
      startBrowser_c.setOnClickListener(new View.OnClickListener() {
         public void onClick(View view) {
            Intent i = new Intent("com.example.intentdemo.LAUNCH",
            Uri.parse("https://www.example.com"));
            startActivity(i);
         }
      });

   }

   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
   // Inflate the menu; this adds items to the 
   // action bar if it is present.
   getMenuInflater().inflate(R.menu.main, menu);
   return true;
   }

}

以下是修改的主要活動檔的內容 src/com.example.intentdemo/CustomActivity.java.

package com.example.intentdemo;

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.widget.TextView;

public class CustomActivity extends Activity {
   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.custom_view);

      TextView label = (TextView) findViewById(R.id.show_data);

      Uri url = getIntent().getData();
      label.setText(url.toString());
   }

}

以下是 res/layout/activity_main.xml 檔的內容:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:orientation="vertical" >

   <Button android:id="@+id/start_browser_a"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="@string/start_browser_a"/>

   <Button android:id="@+id/start_browser_b"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="@string/start_browser_b"/>

   <Button android:id="@+id/start_browser_c"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="@string/start_browser_c"/>

</LinearLayout>

下麵是 res/layout/custom_view.xml 檔的內容:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"    >

   <TextView android:id="@+id/show_data"
   android:layout_width="fill_parent"
   android:layout_height="400dp"/>

</LinearLayout>

下麵 res/values/strings.xml 檔內容中定義兩個新的常量: 

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">IntentDemo</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
    <string name="start_browser_a">Start Browser with VIEW action</string>
    <string name="start_browser_b">Start Browser with LAUNCH action</string>
    <string name="start_browser_c">Exception Condition</string>

</resources>

以下是 AndroidManifest.xml 檔的默認內容:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.intentdemo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.intentdemo.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.example.intentdemo.CustomActivity"
            android:label="@string/app_name">
           <intent-filter>
              <action android:name="android.intent.action.VIEW" />
              <action android:name="com.example.intentdemo.LAUNCH" />
              <category android:name="android.intent.category.DEFAULT" />
              <data android:scheme="http" />
           </intent-filter>
        </activity>
    </application>

</manifest>

要運行IntentDemo應用程式。假設創建了AVD並設置了環境。要從 Eclipse 運行應用程式,打開一個專案的活動檔,從工具欄上單擊“Run” Eclipse Run Icon 圖示。 Eclipse AVD安裝的應用程式並啟動它,如果一切設置和應用都沒有問題,它會顯示以下模擬器窗口:

Android Custom Activity

現在,開始第一個按鈕“Start Browser with VIEW Action”。這裏定義了自定義活動篩檢程式“android.intent.action.VIEW”,並且已經有一個默認的活動,由Android啟動Web流覽器視圖定義動作,所以android 顯示以下兩個選項來選擇要啟動的活動。

Android Two Activities

現在,如果選擇流覽器,那麼Android將啟動網頁流覽器並打開 example.com 網站,但如果選擇“IndentDemo”選項,那麼Android將啟動CustomActivity什麼也不做,只不過是捕捉傳遞的數據,並顯示在文本視圖如下:

Android Custom Activity Runs

現在使用“後退”按鈕,並點擊“Start Browser with LAUNCH Action”按鈕,這裏 Android 應用篩檢程式來選擇定義活動,只需啟動自定義活動,再次顯示以下畫面:

Android Custom Activity Runs

同樣,返回使用“後退”按鈕,並點擊“Exception Condition”按鈕,在這裏Android試圖找出一個有效的篩檢程式,對於給定intent,它沒有找到一個有效活動定義,因為在這個時候,已經數據使用HTTPS,而不是HTTP,雖然是一個正確的動作,但是Android拋出一個異常,並顯示以下畫面:

Android Exception Screen
 

上一篇: Android碎片/片段 下一篇: Android UI佈局