詳解intent和intentfilter


1.Intent對象簡介

  Intent中文意思指"意圖",按照Android的設計理念,Android使用Intent來封裝程序的"調用意圖",不管啟動Activity、Service、BroadcastReceiver,Android都使用統一的Intent對象來封裝這一"啟動意圖"。此外,Intent也是應用程序組件之間通信的重要媒介。

  Android應用程序包含三種重要組件:Activity、Service、BroadcastReceiver,應用程序采用一致的方式啟動它們,都是依靠Intent來進行啟動的,Intent中封裝了程序要啟動的意圖。

  下面是Intent啟動不同組件的部分方法:

  Activity組件:startActivity(Intent intent);startActivityForResult(Intent intent,int requestCode);

  Service組件:startService(Intent intent);bindService(Intent intent,ServiceConnection conn,int flags);

  BroadcastReceiver組件:sendBroadcast(Intent intent);sendOrderedBroadcast(Intent intent,String receiverPermission);

2.intent的屬性及intentfilter的配置

  Intent的屬性大致包含:Component,Action,Category,Data,Type,Extra,Flag這7種屬性,其中Component用於明確指定需要啟動的組件,而Extra則用於"攜帶"需要交換的數據。

  2.1 Component屬性

    Intent的Component屬性需要接收一個ComponentName對象,ComponentName構造器包含如下對象:

    1>ComponentName(String pkg,String cls),

    2>ComponentName(Context pkg,String cls),

    3>ComponentName(Context pkg,Class<?> cls)

    創建pkg包下cls類對應的組件,上面的三個構造器本質上就是一個。查看第二個和第三個構造器源代碼:

1   public ComponentName(Context pkg, String cls) {
2         if (cls == null) throw new NullPointerException("class name is null");
3         mPackage = pkg.getPackageName();
4         mClass = cls;
5     }

    

1   public ComponentName(Context pkg, Class<?> cls) {
2         mPackage = pkg.getPackageName();
3         mClass = cls.getName();
4     }

 

    mpackage和mClass分別表示包名和類名,最終都是為了獲取包名和類名。注意這塊mClass是類的完整名稱(包名+類名)

    這說明創建一個ComponentName需要指定包名和類名就可以唯一確定一個組件類。這樣,應用程序可以根據給定的組件類啟動特定的組件。這里順便說下Intent包含的三個方法:

    1>setClass(Context context,Class<?> cls)

    2>setClassName(Context context,String className)

    3>setClassName(String packageName,String className)

    這三個方法其實本質上還是調用上面的三個方法,查看第一個源代碼:

1   public Intent setClass(Context packageContext, Class<?> cls) {
2         mComponent = new ComponentName(packageContext, cls);
3         return this;
4     }

    后面兩個也是調用不同的ComponentName構造方法,這里就不啰嗦了,自己可以看下源碼。

    TIP:

      Android應用的Context代表訪問該應用環境信息的接口,Android應用的包名作為應用的唯一標識,因此Android應用的Context對象和包名有一一對應的關系。

    指定Component屬性的Intent已經明確它要啟動的哪個組件,因此這種Intent也被稱為顯示"意圖".

  2.2 action、category屬性與intent-filter配置

    Intent的action、category屬性都是普通的字符串,其中action表示Intent需要完成的一個抽象"動作",而category則為action添加額外的類別信息,通常action和category一塊使用。

    需要指出的是,一個Intent中只能包含一個action屬性,但可以包含多個category屬性。當程序創建Intent時,該Intent默認啟動常量值為andorid.intent.category.DEFAULT的組件。

    下面寫一個Demo,從一個Activity(隱式)啟動另一個Activity,布局文件很簡單,activity_main添加一個按鈕,activity_other顯示一行字,這里就不寫出了:

    MainActivity類:

 1 package com.example.administrator.intentandintentfilterdemo;
 2 
 3 import android.content.Intent;
 4 import android.os.Bundle;
 5 import android.support.v7.app.ActionBarActivity;
 6 import android.view.View;
 7 
 8 public class MainActivity extends ActionBarActivity {
 9     private static final String FLAG_OTHER = "com.example.administrator.intentandintentfilterdemo.OTHERACTIVITY";
10     @Override
11     protected void onCreate(Bundle savedInstanceState) {
12         super.onCreate(savedInstanceState);
13         setContentView(R.layout.activity_main);
14     }
15 
16     public void start(View view){
17         Intent intent = new Intent();
18         intent.setAction(FLAG_OTHER);
19         intent.addCategory("android.intent.category.DEFAULT2");
20         startActivity(intent);
21     }
22 
23 
24 }
View Code

    OtherActivity類:

 1 package com.example.administrator.intentandintentfilterdemo;
 2 
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 
 6 /**
 7  * Created by Administrator on 2015/3/22.
 8  */
 9 public class OtherActivity extends Activity{
10     @Override
11     protected void onCreate(Bundle savedInstanceState) {
12         super.onCreate(savedInstanceState);
13         setContentView(R.layout.activity_other);
14     }
15 }
View Code

    AndroidManifest.xml:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 3     package="com.example.administrator.intentandintentfilterdemo" >
 4 
 5     <application
 6         android:allowBackup="true"
 7         android:icon="@drawable/ic_launcher"
 8         android:label="@string/app_name"
 9         android:theme="@style/AppTheme" >
10         <activity
11             android:name=".MainActivity"
12             android:label="@string/app_name" >
13             <intent-filter>
14                 <action android:name="android.intent.action.MAIN" />
15 
16                 <category android:name="android.intent.category.LAUNCHER" />
17             </intent-filter>
18         </activity>
19 
20         <activity
21             android:name=".OtherActivity"
22             android:label="@string/app_name" >
23             <intent-filter>
24                 <action android:name="com.example.administrator.intentandintentfilterdemo.OTHERACTIVITY"/>
25                 <action android:name="com.example.administrator.intentandintentfilterdemo.TEMP"/>
26                 <category android:name="android.intent.category.DEFAULT2"/>
27                 <category android:name="android.intent.category.DEFAULT"/>
28             </intent-filter>
29         </activity>
30     </application>
31 
32 </manifest>
View Code

 

    如果我們不在intent-filter中配置默認category屬性,那么就會報異常。從中可以看出只要配置文件中intent-filter包含action、category就可以啟動目標組件。切記,在intent-filter中要配置默認的category。

  2.3 data、type屬性與intent-filter配置

    Data屬性通常用於向action提供操作的數據。一個Data屬性接收一個Uri對象,Uri通常通過如下字符串來表示:

    content://com.android.linzi:80/student/1

    Uri總滿足如下格式:

    scheme://host:port/path

    上面content是scheme部分,com.android.linzi是host部分,80是prot部分,/student/1是path部分

    Type屬性用於指定該Data所指定的MIME類型,這種類型可以是任何自定義的類型,只要符合abc/xyz格式的字符串即可。

    由於Data屬性和Type屬性關系比較微妙,這兩個屬性可以相互覆蓋,所以希望既有Data屬性又有Type屬性時應該調用Intent的setDataAndType()方法。

    對上面代碼稍作修改

    MainActivity類:

   

1   public void start(View view){
2         Intent intent = new Intent();
3         intent.setAction(FLAG_OTHER);
4         intent.addCategory("android.intent.category.DEFAULT2");
5 //        intent.setData(Uri.parse("content://com.example.linzi:80/hanfeng/1"));
6 //        intent.setType("image/jpg");
7         intent.setDataAndType(Uri.parse("content://com.example.linzi:80/hanfeng/1"),"image/jpg");
8         startActivity(intent);
9     }

    如果將第7行換成5、6行就會報異常,Data和Type會相互覆蓋

    AndroidManifest.xml:

    

 1 <activity
 2             android:name=".OtherActivity"
 3             android:label="@string/app_name" >
 4             <intent-filter>
 5                 <action android:name="com.example.administrator.intentandintentfilterdemo.OTHERACTIVITY"/>
 6                 <action android:name="com.example.administrator.intentandintentfilterdemo.TEMP"/>
 7                 <category android:name="android.intent.category.DEFAULT2"/>
 8                 <category android:name="android.intent.category.DEFAULT"/>
 9                 <data
10                     android:scheme="content"
11                     android:host="com.example.linzi"
12                     android:path="/hanfeng/1"
13                     android:port="80"
14                     android:mimeType="image/jpg"/>
15             </intent-filter>
16         </activity>

  2.4 Extra屬性 

    Intent的Extra屬性通常用於在多個Activity之間進行數據交換,Extra屬性應該是一個Bundle對象,它可以用來存儲多組key-value值。

    可以通過putExtra()方法存放數據,putExtra()方法本質上也是通過Bundle來存儲數據的,下面是其源碼。(這里不做多的介紹,具體請參考前面寫的關於Activity的博文)

1 public Intent putExtra(String name, boolean value) {
2         if (mExtras == null) {
3             mExtras = new Bundle();
4         }
5         mExtras.putBoolean(name, value);
6         return this;
7     }

  2.5 Flag屬性

    Intent的Flag屬性用於為該Intent添加額外的控制旗標,Intent可調用addFlags()方法為其添加控制旗標

    Android為Intent提供了大量的Flag,每個Flag都有特定的功能,具體請參考Android API文檔。

3.總結:

  在啟動Android Activity、Service、BroadcastReceiver等組件時,總需要借助Intent來實現(顯示和隱式),Android Intent封裝了應用程序的啟動意圖,但這種意圖並未與其它任何組件藕合,這樣可以很好的為增強程序的可擴展性和可維護性。應當熟悉component、action、category、data、type各屬性的功能和用法。

 

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM