Android中Intent應用

什麼是Intent

在一個Android 應用中, Intent 是對執行某個操作的一個抽象描述, Intent 負責提供組件之間相互調用的相關信息傳遞,實現調用者和被調用者之間的解耦。

二、Intent 的屬性:

Intent是對執行某個操作的一個抽象描述,其描述的內容包括,對執行動作 Action 的描述、對操作數據的描述、還有 4 種附加屬性的描述。分別介紹如下:
 
 Action  ,對執行動作的描述,是個字符串,是對所將執行的動作的描述,在Intent 類中定義了一些字符串常量作爲標準動作,譬如:

public   static   final  String  ACTION_DIAL = "android.intent.action.DIAL" ;

public   static   final  String  ACTION_SENDTO  = "android.intent.action.SENDTO" ;

還可以自定義Action ,並定義相應的 Activity 來處理我們自定義的行爲。

data ,是對執行動作所要操作的數據的描述,Android 中採用 URI 來表示數據,譬如在聯繫人應用中, 指向聯繫人 1 URI 可能爲: content://contacts/1 ( content provider 提供的數據類型是 content)  。 結合 Action data 可以基本表達出意圖 ,

·  VIEW_ACTION content://contacts/1 — 顯示標識符爲 ”1″ 的聯繫人的詳細信息

·  EDIT_ACTION content://contacts/1 — 編輯標識符爲 ”1″ 的聯繫人的詳細信息

·  VIEW_ACTION content://contacts/ — 顯示所有聯繫人的列表

·  PICK_ACTION content://contacts/ — 顯示所有聯繫人的列表,並且允許用戶在列表中選擇一個聯繫人,然後把這個聯繫人返回給父 activity 。例如:電子郵件客戶端可以使用這個  Intent ,要求用戶在聯繫人列表中選擇一個聯繫人。

除了Action data 之外,還有 4 個屬性。

catagory 類別 ,是被請求組件的額外描述信息,Intent 類中也定義了一組字符串常量表示 Intent 不同的類別。完整的列表可以看 API 文檔中 Intent 類的相應部分。

public   static   final  String  CATEGORY_LAUNCHER  = "android.intent.category.LAUNCHER" ;

Public   static   final   String   CATEGORY_PREFERENCE  = "android.intent.category.PREFERENCE" ;

 

extra 附加信息, 除了data 之外,還可以通過 extra 附加信息, extra 屬性使用 Bundle 類型 進行數據傳遞,我們可以把 Bundle 當做 HashMap 來理解,附加數據可以通過  intent.putExtras()  和  intent.getExtras()  進行傳入和讀取。 就像這樣,獲取附加信息:  Bundle bundle = intent.getExtras();

添加附加信息: Bundle bundle = new Bundle(); intent.putExtras(bundle);

component 組件 ,顯式指定Intent 的目標組件的名稱。如果指定了 component 屬性,系統會直接使用它指定的組件,而非匹配查找。

type 數據類型, 顯式指定Intent 的數據類型,一般 Intent 的數據類型都能夠根據數據本身進行判定,但是通過設置這個屬性,可以強制採用顯式指定的類型和不再進行推導。

解析Intent

Intent是一種在不同組件之間傳遞的請求信息,是應用程序發出的請求和意圖,作爲一個完整的消息傳遞機制, Intent 不僅需要發送端,還需要接收端。

當指定了component 屬性後,就是顯式的指定了目標組件,也就是接收端。如果沒有明確指定目標組件,那麼 Android 系統會使用  Intent  裏的( action data category )三個屬性來尋找和匹配接收端。

IntentFilter

應用程序組件可以使用IntentFilter 來向系統說明自己可以響應和處理那些 Intent 請求。組件一般通過 AndroidManifest.xml 文件的 <Intent-Filter> 描述。

  < activity   android:name = ".ButtonDemo"

                   android:label = "@string/app_name" >

              < intent-filter >

                 < action   android:name = "android.intent.action.MAIN"   />

                 < category   android:name = "android.intent.category.LAUNCHER"   />

             </ intent-filter >

         </ activity >

 

Intent的用法

一、 顯式的 Intent(Explicit Intent)

²  同一個應用程序中的Activity切換

通常一個應用程序中需要多個 UI 屏幕,也就需要多個 Activity 類,並且在這些 Activity 之間進行切換,這種切換就是通過 Intent 機制來實現的。

在同一個應用程序中切換 Activity 時,我們通常都知道要啓動的 Activity 具體是哪一個,因此常用顯式的 Intent 來實現。下面的例子用來實現一個非常簡單的應用程序 IntentDemo ,它包括兩個 UI 屏幕也就是兩個 Activity—— IntentDemo 類和 TestView 類, IntentDemo 類有一個 按鈕用來啓動 Test View

程序的代碼非常簡單, IntentDemo類源代碼

package  com.wang.android.demo.intent;

import  android.app.Activity;

import  android.content.Intent;

import  android.os.Bundle;

import  android.view.View;

import  android.widget.Button;

public   class  IntentDemo  extends  Activity {

     public   void  onCreate(Bundle savedInstanceState) {

         super .onCreate(savedInstanceState);

        setContentView(R.layout. main );

        Button start_button=(Button)findViewById(R.id. Start );

        start_button.setOnClickListener( new  Button.OnClickListener(){

public   void  onClick(View v) {

Intent intent = new  Intent();

intent.setClass(IntentDemo. this , TestView. class );

startActivity(intent);

}});

    }

}

 

上面的代碼中,主要是爲“ Start  _ activity ”按鈕添加了 OnClickListener 使得按鈕被點擊時執行 onClick() 方法, onClick() 方法中則利用了 Intent 機制,來啓動 Test View ,關鍵的代碼是下面這 行:  

Intent intent = new  Intent();

intent.setClass(IntentDemo. this , TestView. class );

startActivity(intent);

 

這裏定義 Intent 對象時所用到的是 Intent 的構造函數之一:

Intent ( Context  packageContext,  Class <?> cls)

兩個參數分別指定 Context Class ,由於將 Class 設置爲 TestActivity.class ,這樣便顯式的指定了 Test View 類作爲該 Intent 接收者,通過後面的startActivity() 方法便可啓動 Test View

TestView.java類的源代碼:

package  com.wang.android.demo.intent;

 

import  android.app.Activity;

import  android.os.Bundle;

 

public   class  TestView  extends  Activity{

protected   void  onCreate(Bundle savedInstanceState) {

//  TODO  Auto-generated method stub

super .onCreate(savedInstanceState);

setContentView(R.layout. test_activity );

}

}

 

Test View 僅僅是調用 setContentView 來顯示 test_ View .xml 中的內容而已。  

下一步在 AndroidManifest.xml   文件中註冊 Activity AndroidManifest.xml   源代碼如下:

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

< manifest   xmlns:android = "http://schemas.android.com/apk/res/android"

       package = "com.wang.android.demo.intent"

       android:versionCode = "1"

       android:versionName = "1.0" >

     < application   android:icon = "@drawable/icon"   android:label = "@string/app_name" >

         < activity   android:name = ".IntentDemo"

                   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 = ".TestView" ></ activity >

     </ application >

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

</ manifest >  

I ntent 機制即使在 程序內部 顯式指定 接收者,也還是需要在 AndroidManifest.xml 中聲明。這個過程並不像一個簡單的函數調用,顯式的 Intent 也同樣 經過了Android 應用程序框架所提供的支持,從滿足條件的 Activity 中進行選擇,如果不在 AndroidManifest.xml 中進行聲明,則 Android 應用程序框架找不到所需要的 Activity

²  不同應用程序之間的Activity切換

上面的例子我們所做的是在同一應用程序中進行 Activity 的切換,那麼在不同的應用程序中,是否也能這麼做呢,答案是肯定的,不過對應的代碼要稍作修改。本例中我們需要兩個應用程序,可利用上例中的 IntentDemo 新建一個 IntentTest   應用程序。

IntentTest 源代碼:

package  com.android.demo.intent;

 

import  android.app.Activity;

import  android.content.Intent;

import  android.os.Bundle;

import  android.view.View;

import  android.widget.Button;

 

public   class  IntentTest  extends  Activity {

     /** Called when the activity is first created. */

     @Override

     public   void  onCreate(Bundle savedInstanceState) {

super .onCreate(savedInstanceState);

// 按照main.xml來渲染用戶界面

setContentView(R.layout. main );

Button start_button = (Button) findViewById(R.id. StartButton );

// 爲撥號按鈕設置一個點擊事件觀察者

start_button.setOnClickListener( new  Button.OnClickListener() {

// 實現監聽器接口的匿名內部類,其中監聽器本身是View類的內部接口

// 實現接口必須實現的onClick方法

@Override

public   void  onClick(View v) {

Intent intent =  new  Intent();

intent.setClassName( "com.wang.android.demo.intent" ,

"com.wang.android.demo.intent.TestView" );

// 去調用那些可以處理撥號行爲的Activity

startActivity(intent);

}

});

}

}

 

注意比較它與 IntentDemo t 的不同之處主要在於初始化 Intent 對象的過程:  

Intent intent =  new  Intent();

intent.setClassName( "com.wang.android.demo.intent" ,

"com.wang.android.demo.intent.TestView" );

 

這裏採用了 Intent 最簡單的不帶參數的構造函數,然後通過 setClassName() 函數來指定要啓動哪個包中的哪個 Activity 而不是像上例中的通過 Intent ( Context  packageContext,  Class <?> cls) 這個構造函數來初始化Intent 對象,這是因爲,要啓動的 TestActivity CrossIntentTest 不在同一個包中,要指定 Class 參數比較麻煩,所以通常啓動不同程序的 Activity 時便採用上面的 setClassName() 的方式  

另外我們還需要修改SimpleIntentTest 程序中的 AndroidManifest.xml 文件,爲 TestActivity 的聲明添加 Intent Filter  

         < activity   android:name = ".TestView" >

         < intent-filter >

         < action   android:name = "android.intent.action.DEFAULT" />

         </ intent-filter >

         </ activity >

對於不同應用之間的 Activity 的切換,這裏需要在 Intent Filter 中設置至少一個 Action ,否則其他的應用將沒有權限調用這個 Activity   設置Intent Filter Action 主要的目的,是爲了讓其他需要調用這個 Activity 的程序能夠順利的調用它。除了 Action 之外, Intent Filter 還可以設置 Category Data 等,用來更加精確的匹配 Intent Activity

隱式 Intent(Implicit Intent)

  如果 Intent 機制僅僅提供上面的顯式 Intent 用法的話,這種相對複雜的機制似乎意義並不是很大。確實, Intent 機制更重要的作用在於下面這種隱式的 Intent ,即 Intent 的發送者不指定接收者,很可能不知道也不關心接收者是誰,而由 Android 框架去尋找最匹配的接收者。

²  最簡單的隱式Intent

IntentDemo 稍做修改,做一個簡單的撥打電話的 demo 。源代碼如下:

package  com.wang.android.demo.intent;

 

import  android.app.Activity;

import  android.content.Intent;

import  android.net.Uri;

import  android.os.Bundle;

import  android.view.View;

import  android.widget.Button;

import  android.widget.EditText;

 

public   class  IntentDemo  extends  Activity {

/** Called when the activity is first created. */

@Override

public   void  onCreate(Bundle savedInstanceState) {

super .onCreate(savedInstanceState);

// 按照main.xml來渲染用戶界面

setContentView(R.layout. main );

// 獲取可編輯的電話號碼框和撥號按鈕

final  EditText phoneNumberEditText = (EditText) findViewById(R.id. PhoneNumberEditText );

Button dialing = (Button) findViewById(R.id. dialing );

// 爲撥號按鈕設置一個點擊事件觀察者

dialing.setOnClickListener( new  Button.OnClickListener() {

// 實現監聽器接口的匿名內部類,其中監聽器本身是View類的內部接口

// 實現接口必須實現的onClick方法

@Override

public   void  onClick(View v) {

// 獲得可編輯文本框中的值,也就是電話號碼

String phoneNumber = phoneNumberEditText.getText().toString();

// new Intent(行爲,數據),其中action_dial是撥號行爲,數據是電話號碼

Intent intent =  new  Intent(Intent. ACTION_DIAL , Uri

. parse ( "tel://"  + phoneNumber));

// 去調用那些可以處理撥號行爲的Activity

startActivity(intent);

}

});

}

}

Main.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" >

< EditText   android:id = "@+id/PhoneNumberEditText"   android:text = "請輸入電話號碼"   android:textSize = "15sp"

android:layout_width = "fill_parent"   android:layout_height = "wrap_content" ></ EditText >

< Button   android:id = "@+id/dialing"   android:text = "@string/dialing"

android:layout_width = "wrap_content"   android:layout_height = "wrap_content" ></ Button >

</ LinearLayout >

 

AndroidManifest.xml 源代碼:

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

< manifest   xmlns:android = "http://schemas.android.com/apk/res/android"

       package = "com.wang.android.demo.intent"

       android:versionCode = "1"

       android:versionName = "1.0" >

     < application   android:icon = "@drawable/icon"   android:label = "@string/app_name" >

         < activity   android:name = ".IntentDemo"

                   android:label = "@string/app_name" >

             < intent-filter >

                 < action   android:name = "android.intent.action.MAIN"   />

                 < category   android:name = "android.intent.category.LAUNCHER"   />

          < intent-filter >

< action   android:name = "android.intent.action.CALL_BUTTON"   ></ action >

< category   android:name = "android.intent.category.DEFAULT" >

            </ category >

</ intent-filter >

             </ intent-filter >

         </ activity >

     </ application >

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

 

</ manifest >  

 

²   增加一個接收者

事實上接收者如果希望能夠接收某些 Intent ,通過在 AndroidManifest.xml 中增加 Activity 的聲明,並設置對應的 Intent Filter Action ,才能被 Android 的應用程序框架所匹配。

AndroidManifest.xml 文件,將 IntentDemo 的聲明部分改爲:  

         < activity   android:name = ".IntentDemo"

                   android:label = "@string/app_name" >

             < intent-filter >

                 < action   android:name = "android.intent.action.MAIN"   />

                 < category   android:name = "android.intent.category.LAUNCHER"   />

           < intent-filter >

< action   android:name = "android.intent.action.CALL_BUTTON"   ></ action >

< category   android:name = "android.intent.category.DEFAULT" ></ category >

</ intent-filter >

             </ intent-filter >

         </ activity >

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章