Intent詳解

轉載於http://fenglingdangyang.blog.sohu.com/231856618.html

隱式啓動Activity的intent到底發給哪個activity,需要進行三個匹配,一個是action,一個是category,一個是data,可以是全部或部分匹配

同樣適用於Service和BroadcastReceiver,下面是以Activity爲例

 

 

MainActivity.java --主Activity

TestActivity.java --需要隱式啓動的Activity

 

 

(1) 根據Action和Category來進行匹配

 

         <activity android:name=".TestActivity"  android:label="TestActivity">

        <intent-filter >

         <action android:name="cc.android/myaction.leo"/>

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

        </intent-filter>

        </activity>

        

在MainActivity.java裏啓動它:

intent.setAction( "cc.android/myaction.leo");

//不加下面這行也行,因爲intent的這個屬性默認值即系Intent.CATEGORY_DEFAULT

intent.addCategory(Intent.CATEGORY_DEFAULT);

startActivity( intent );

 

總結:

a.在某個Activity裏用startActivity()方法發送一個intent,這個intent設定了一些條件,比如用方法setAction(),addCategory()設定了兩個屬性,

  發送了這個intent之後,android會去系統裏保存的MainManifest.xml清單(假設這個系統存放全部apk清單的文件爲MainManifest.xml)裏查找符合這兩個屬性的activity,然後啓動它。

  查找過程是怎樣的呢?

  我猜測:在安裝某個apk的時候,android系統會把這個apk的清單文件裏內容複製一份至系統的某個清單文件裏(假如這個系統存放全部apk清單的文件爲MainManifest.xml)

  當 某個Activity用startActivity(intentOther)方法向系統發送了一個intent(假如爲intentOther),那麼 android系統會去查找這個MainManifest.xml裏註冊的<intent-filter >屬性,

  查找到符合這個 intentOther 的就啓動這個Activity,如果有多個這樣的Activity符合條件的話,就跳出一個對話框讓用戶選擇究竟要啓動哪一個

  

  上面那個自定義的Action字符串("cc.android/myaction.leo",當然也可以寫成這樣"cc.android.myaction.leo",同時AndroidManifest.xml裏也要寫成這樣)是系統唯一的,

  所以系統很容易就能匹配到。

  

  

 

b.任何一個需要隱式啓動的Activity都必須要有這項:<category android:name="android.intent.category.DEFAULT"/>

例外情況是:android.intent.category.MAIN和android.intent.category.LAUNCHER的filter中沒有必要加入android.intent.category.DEFAULT,當然加入也沒有問題

 

c.假如有兩個Activity,它們的在AndroidManifest.xml裏配置如下:

<activity android:name="MyActivityOne" android:label="@string/activityOne">

<intent-filter>

<action android:name="hello.leo.liao" />

<action android:name="hello.leo.leo" />

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

</intent-filter>

</activity>

 

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

<action android:name="hello.leo.liao" />

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

</intent-filter>

</activity>

 

在MainActivity.java裏發送一個intent:

intent.setAction( "hello.leo.liao");

//不加下面這行也行,因爲intent的這個屬性默認值即系Intent.CATEGORY_DEFAULT

intent.addCategory(Intent.CATEGORY_DEFAULT);

startActivity( intent );

 

這樣的話,android系統會跳出一個對話框讓你選擇啓動哪一個Activity(MyActivityOne還是MyActivityTwo)

如果把上面的intent.setAction( "hello.leo.liao");改爲intent.setAction( "hello.leo.leo");的話,就自動匹配到MyActivityOne

就是說如果category和action都相同的話,會跳出一個對話框讓用戶選擇要啓動哪一個activity;

如果category相同,而action不相同,就可以匹配到相應的activity

 

d.單單靠添加addCategory屬性不能匹配,如:

Intent intent = new Intent();

intent.addCategory(Intent.CATEGORY_DEFAULT);

intent.addCategory("android.intent.category.hello");

startActivity(intent);

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

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

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

</intent-filter>

</activity>

 

e.當匹配不上任何Activity的話,會發生異常,跳出對話框:很抱歉...某某應用程序意外停止,請重試。

 

f.Service和BroadcastReceiver 同理

 

 

(2) 根據Action和Data匹配

 

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

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

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

                <data android:scheme="x-id"></data>

</intent-filter>

</activity>

 

//Uri uri = Uri.parse("x-id://www.google.com/getDetails?id=123");//這個也可以

//Uri uri = Uri.parse("x-id");//這個不行

//Uri uri = Uri.parse("x-id://");這個可以

Uri uri = Uri.parse("x-id:");//這個可以

            Intent in = new Intent();

            in.setAction("android.intent.action.leo");//去掉這行不行,單靠data不能匹配

            in.addCategory(Intent.CATEGORY_DEFAULT);//可以去掉這行,因爲intent的默認category值即系Intent.CATEGORY_DEFAULT

            in.setData(uri);//去掉這行不行

            startActivity(in);

            

總結:如果在AndroidManifest.xml裏面指定了<data>這行,那麼,需要匹配到它的話,在代碼裏必須要設置intent的data,如上面的in.setData(uri)    

Data的語法:

<data android:host="string"

      android:mimeType="string"

      android:path="string"

      android:pathPattern="string"

      android:pathPrefix="string"

      android:port="string"

      android:scheme="string" />

      

Uri的格式:scheme://host:port/path or pathPrefix or pathPattern

 

如果scheme沒有指定,那其它的屬性均無效;

如果host沒有指定,那麼port,path,pathPrefix,pathPattern均無效;

 

如果在manifest裏這樣寫:<data android:scheme="something" android:host="project.example.com" />

那麼Uri uri = Uri.parse("something://project.example.com"); 纔可以匹配

 

再如:

<data android:scheme="something" android:host="project.example.com" android:port="80"/>

等同於這樣寫:

<data android:scheme="something"/>

<data android:host="project.example.com"/>

<data android:port="80"/>

那麼Uri uri = Uri.parse("something://project.example.com:80"); 纔可以匹配

 

不知爲何,下面這個不行:

<data android:scheme="content" android:host="com.example.project" android:port="200" android:path="folder/subfolder/etc"/>

Uri uri = Uri.parse("content://com.example.project:200/folder/subfolder/etc")

下面這樣也不行

<data android:scheme="content" android:host="com.example.project" android:port="200" android:path="folder"/>

Uri uri = Uri.parse("content://com.example.project:200/folder")

 

 

可以有多個data,只需匹配其中一個即可

 

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

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

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

                <data android:scheme="x-id"/>

                <data android:scheme="something"/>

</intent-filter>

</activity>

           Intent in = new Intent();

            in.setAction("android.intent.action.leo");

            in.addCategory(Intent.CATEGORY_DEFAULT);

            in.setData(Uri.parse("something:"));//或者用這個亦可in.setData(Uri.parse("x-id:"));            

            startActivity(in);      

            

(3)  根據action和data的mimeType屬性匹配          

 

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

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

<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />

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

</intent-filter>

</activity>

在java代碼裏這樣寫就可以匹配到這個activity:

            Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因爲Category默認值即系Intent.CATEGORY_DEFAULT

            in.setType("vnd.android.cursor.dir/vnd.google.note");

            startActivity(in); 

            

  單靠data的mimeType屬性不能匹配,就算這個mimeType是唯一的也不行(比如in.setType("leo.android.cursor.dir/vnd.google.leo");),需要有一個action配合   

  

  可以有多個mimeType,在java代碼裏只需匹配其中一個即可:

  <activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

  <intent-filter>

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

<data android:mimeType="leo.android.cursor.dir/vnd.google.leo" />

<data android:mimeType="leo.android.cursor.dir/vnd.google.liao" />

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

</intent-filter>

</activity>

這樣可以啓動MyActivityTwo這個Activity:

Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因爲Category默認值即系Intent.CATEGORY_DEFAULT

            in.setType("leo.android.cursor.dir/vnd.google.liao");

            startActivity(in);

      或者這樣也可以啓動MyActivityTwo這個Activity:   

      Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因爲Category默認值即系Intent.CATEGORY_DEFAULT

            in.setType("leo.android.cursor.dir/vnd.google.leo");

            startActivity(in);

     

  

  scheme和mimeType只能有其中一個,下面這樣通不過

  AndroidManifest.xml裏:

  <data android:scheme="something" android:host="project.example.com"

android:port="80"

android:mimeType="leo.android.cursor.dir/vnd.google.leo" />  

<data android:scheme="something" android:host="project.example.com"

android:port="80" />

<data android:mimeType="leo.android.cursor.dir/vnd.google.leo" />

 

java代碼裏:

匹配不上:

Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            Uri uri = Uri.parse("something://project.example.com:80");

            in.setData(uri);

            in.setType("leo.android.cursor.dir/vnd.google.leo");

            startActivity(in);                  

            

            這樣還是匹配不上:

            Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

//            Uri uri = Uri.parse("something://project.example.com:80");

//            in.setData(uri);

            in.setType("leo.android.cursor.dir/vnd.google.leo");

            startActivity(in);

            

            這樣還是匹配不上:

            Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            Uri uri = Uri.parse("something://project.example.com:80");

            in.setData(uri);

//            in.setType("leo.android.cursor.dir/vnd.google.leo");

            startActivity(in);

            

            

            

(4)   一個Activity裏可以有多對<intent-filter></intent-filter>  只要匹配其中一對,即可啓動這個Activity

 

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

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

<data android:scheme="something" android:host="project.example.com"

android:port="80" />

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

</intent-filter>

<intent-filter>

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

<data android:mimeType="leo.android.cursor.dir/vnd.google.leo" />

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

</intent-filter>

<intent-filter>

<action android:name="hello.hi.liao"></action>

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

</intent-filter>

</activity>

java代碼裏:

匹配第一對<intent-filter> 可以啓動MyActivityTwo這個Activity:

Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因爲Category默認值即系Intent.CATEGORY_DEFAULT

            Uri uri = Uri.parse("something://project.example.com:80");

            in.setData(uri);

            startActivity(in);

   匹配第二對<intent-filter> 也可以啓動MyActivityTwo這個Activity:    

   Intent in = new Intent();

   in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因爲Category默認值即系Intent.CATEGORY_DEFAULT

            in.setAction("android.intent.action.VIEW");

            in.setType("leo.android.cursor.dir/vnd.google.leo");

            startActivity(in);    

            

  匹配第三對<intent-filter> 也可以啓動MyActivityTwo這個Activity:      

  Intent in = new Intent();

            in.setAction("hello.hi.liao");

            in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因爲Category默認值即系Intent.CATEGORY_DEFAULT

            startActivity(in);      

            

            

            

全部總結:

1.  <action/>包含在 <intent-filter></intent-filter> 標籤對裏,而且是必不可少的!不管以哪一種方式來匹配,都不可缺少這個<action/> ,可以有多個,至少要有一個。

如有多個的,話只需要匹配其中一個即可找到這個activity

<action>裏的屬性值大多數是在Intent裏定義的,比如<action android:name="android.intent.action.VIEW"/>裏的屬性值就等於 Intent.ACTION_VIEW,

在這個Intent類裏以ACTION開頭定義的常量都是。當然,也可以自定義。  

 

2.  任何一個需要隱式啓動的Activity都必須要有這項:<category android:name="android.intent.category.DEFAULT"/>

例外情況是:android.intent.category.MAIN和android.intent.category.LAUNCHER的filter中沒有必要加入android.intent.category.DEFAULT,當然加入也沒有問題  

<category> 裏的屬性值大多數是在Intent裏定義的,比如  <category android:name="android.intent.category.DEFAULT"/>裏的屬性值就等於 Intent.CATEGORY_DEFAULT,

在這個Intent類裏以CATEGORY開頭定義的常量都是。當然,也可以自定義。  

3.一個Activity裏可以有多對<intent-filter></intent-filter>  只要匹配其中一對,即可啓動這個Activity

 

  

 

4.在<intent-filter></intent-filter>裏可以有多個<data android:mimeType="xxxx"/>,只需匹配其中一個即可.注意:不可以同時出現第5點的標籤對,即下面這條。

 

 

 

 

5. 在<intent-filter></intent-filter>裏可以有多個<data android:scheme="xxxx" android:host="yyyy" android:port="uuu"/>,只需匹配其中一個即可。

語法:

<data android:host="string"

      android:mimeType="string"

      android:path="string"

      android:pathPattern="string"

      android:pathPrefix="string"

      android:port="string"

      android:scheme="string" />

      可以分開寫,如:

      <data android:scheme="something" android:host="project.example.com" android:port="80"/>

等同於這樣寫:

<data android:scheme="something"/>

<data android:host="project.example.com"/>

<data android:port="80"/>

在java代碼裏,Uri的格式:scheme://host:port/path or pathPrefix or pathPattern

注意:不可以同時出現第4點的標籤對,即上面那條。

 

6.在<intent-filter></intent-filter>裏可以有多個<action android:name="xxxx"> ,只需匹配其中一個即可。

 

 

 

7.當匹配不上任何Activity的話,會發生異常,跳出對話框:很抱歉...某某應用程序意外停止,請重試。

 

 

 

8. 上面所說的全部適用於Service和BroadcastReceiver,只需把<activity ...></activity>換成<service ...></service>或<receiver ...></receiver>即可。

 

9.剛參考了一下packages\apps\HTMLViewer\AndroidManifest.xml,第4和第5條應該是不衝突纔對,但是實際測試中卻是衝突,暫時未到找原因。匹配方式請看:用於打開HTML文件的intent

 

 

 在被啓動的Activity(本例爲MyActivityTwo)裏接收數據:

Intent intent = getIntent();

String intentCategories = intent.getCategories()

String intentType = intent.getType();

Uri uri = intent.getData();

String uriScheme = uri.getScheme();

String uriPath = uri.getPath();

String uriHost = uri.getHost();

String uriEncodedPath = uri.getEncodedPath();

隱式啓動Activity的intent到底發給哪個activity,需要進行三個匹配,一個是action,一個是category,一個是data,可以是全部或部分匹配

同樣適用於Service和BroadcastReceiver,下面是以Activity爲例

 

 

MainActivity.java --主Activity

TestActivity.java --需要隱式啓動的Activity

 

 

(1) 根據Action和Category來進行匹配

 

         <activity android:name=".TestActivity"  android:label="TestActivity">

        <intent-filter >

         <action android:name="cc.android/myaction.leo"/>

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

        </intent-filter>

        </activity>

        

在MainActivity.java裏啓動它:

intent.setAction( "cc.android/myaction.leo");

//不加下面這行也行,因爲intent的這個屬性默認值即系Intent.CATEGORY_DEFAULT

intent.addCategory(Intent.CATEGORY_DEFAULT);

startActivity( intent );

 

總結:

a.在某個Activity裏用startActivity()方法發送一個intent,這個intent設定了一些條件,比如用方法setAction(),addCategory()設定了兩個屬性,

  發送了這個intent之後,android會去系統裏保存的MainManifest.xml清單(假設這個系統存放全部apk清單的文件爲MainManifest.xml)裏查找符合這兩個屬性的activity,然後啓動它。

  查找過程是怎樣的呢?

  我猜測:在安裝某個apk的時候,android系統會把這個apk的清單文件裏內容複製一份至系統的某個清單文件裏(假如這個系統存放全部apk清單的文件爲MainManifest.xml)

  當 某個Activity用startActivity(intentOther)方法向系統發送了一個intent(假如爲intentOther),那麼 android系統會去查找這個MainManifest.xml裏註冊的<intent-filter >屬性,

  查找到符合這個 intentOther 的就啓動這個Activity,如果有多個這樣的Activity符合條件的話,就跳出一個對話框讓用戶選擇究竟要啓動哪一個

  

  上面那個自定義的Action字符串("cc.android/myaction.leo",當然也可以寫成這樣"cc.android.myaction.leo",同時AndroidManifest.xml裏也要寫成這樣)是系統唯一的,

  所以系統很容易就能匹配到。

  

  

 

b.任何一個需要隱式啓動的Activity都必須要有這項:<category android:name="android.intent.category.DEFAULT"/>

例外情況是:android.intent.category.MAIN和android.intent.category.LAUNCHER的filter中沒有必要加入android.intent.category.DEFAULT,當然加入也沒有問題

 

c.假如有兩個Activity,它們的在AndroidManifest.xml裏配置如下:

<activity android:name="MyActivityOne" android:label="@string/activityOne">

<intent-filter>

<action android:name="hello.leo.liao" />

<action android:name="hello.leo.leo" />

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

</intent-filter>

</activity>

 

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

<action android:name="hello.leo.liao" />

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

</intent-filter>

</activity>

 

在MainActivity.java裏發送一個intent:

intent.setAction( "hello.leo.liao");

//不加下面這行也行,因爲intent的這個屬性默認值即系Intent.CATEGORY_DEFAULT

intent.addCategory(Intent.CATEGORY_DEFAULT);

startActivity( intent );

 

這樣的話,android系統會跳出一個對話框讓你選擇啓動哪一個Activity(MyActivityOne還是MyActivityTwo)

如果把上面的intent.setAction( "hello.leo.liao");改爲intent.setAction( "hello.leo.leo");的話,就自動匹配到MyActivityOne

就是說如果category和action都相同的話,會跳出一個對話框讓用戶選擇要啓動哪一個activity;

如果category相同,而action不相同,就可以匹配到相應的activity

 

d.單單靠添加addCategory屬性不能匹配,如:

Intent intent = new Intent();

intent.addCategory(Intent.CATEGORY_DEFAULT);

intent.addCategory("android.intent.category.hello");

startActivity(intent);

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

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

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

</intent-filter>

</activity>

 

e.當匹配不上任何Activity的話,會發生異常,跳出對話框:很抱歉...某某應用程序意外停止,請重試。

 

f.Service和BroadcastReceiver 同理

 

 

(2) 根據Action和Data匹配

 

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

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

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

                <data android:scheme="x-id"></data>

</intent-filter>

</activity>

 

//Uri uri = Uri.parse("x-id://www.google.com/getDetails?id=123");//這個也可以

//Uri uri = Uri.parse("x-id");//這個不行

//Uri uri = Uri.parse("x-id://");這個可以

Uri uri = Uri.parse("x-id:");//這個可以

            Intent in = new Intent();

            in.setAction("android.intent.action.leo");//去掉這行不行,單靠data不能匹配

            in.addCategory(Intent.CATEGORY_DEFAULT);//可以去掉這行,因爲intent的默認category值即系Intent.CATEGORY_DEFAULT

            in.setData(uri);//去掉這行不行

            startActivity(in);

            

總結:如果在AndroidManifest.xml裏面指定了<data>這行,那麼,需要匹配到它的話,在代碼裏必須要設置intent的data,如上面的in.setData(uri)    

Data的語法:

<data android:host="string"

      android:mimeType="string"

      android:path="string"

      android:pathPattern="string"

      android:pathPrefix="string"

      android:port="string"

      android:scheme="string" />

      

Uri的格式:scheme://host:port/path or pathPrefix or pathPattern

 

如果scheme沒有指定,那其它的屬性均無效;

如果host沒有指定,那麼port,path,pathPrefix,pathPattern均無效;

 

如果在manifest裏這樣寫:<data android:scheme="something" android:host="project.example.com" />

那麼Uri uri = Uri.parse("something://project.example.com"); 纔可以匹配

 

再如:

<data android:scheme="something" android:host="project.example.com" android:port="80"/>

等同於這樣寫:

<data android:scheme="something"/>

<data android:host="project.example.com"/>

<data android:port="80"/>

那麼Uri uri = Uri.parse("something://project.example.com:80"); 纔可以匹配

 

不知爲何,下面這個不行:

<data android:scheme="content" android:host="com.example.project" android:port="200" android:path="folder/subfolder/etc"/>

Uri uri = Uri.parse("content://com.example.project:200/folder/subfolder/etc")

下面這樣也不行

<data android:scheme="content" android:host="com.example.project" android:port="200" android:path="folder"/>

Uri uri = Uri.parse("content://com.example.project:200/folder")

 

 

可以有多個data,只需匹配其中一個即可

 

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

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

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

                <data android:scheme="x-id"/>

                <data android:scheme="something"/>

</intent-filter>

</activity>

           Intent in = new Intent();

            in.setAction("android.intent.action.leo");

            in.addCategory(Intent.CATEGORY_DEFAULT);

            in.setData(Uri.parse("something:"));//或者用這個亦可in.setData(Uri.parse("x-id:"));            

            startActivity(in);      

            

(3)  根據action和data的mimeType屬性匹配          

 

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

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

<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />

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

</intent-filter>

</activity>

在java代碼裏這樣寫就可以匹配到這個activity:

            Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因爲Category默認值即系Intent.CATEGORY_DEFAULT

            in.setType("vnd.android.cursor.dir/vnd.google.note");

            startActivity(in); 

            

  單靠data的mimeType屬性不能匹配,就算這個mimeType是唯一的也不行(比如in.setType("leo.android.cursor.dir/vnd.google.leo");),需要有一個action配合   

  

  可以有多個mimeType,在java代碼裏只需匹配其中一個即可:

  <activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

  <intent-filter>

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

<data android:mimeType="leo.android.cursor.dir/vnd.google.leo" />

<data android:mimeType="leo.android.cursor.dir/vnd.google.liao" />

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

</intent-filter>

</activity>

這樣可以啓動MyActivityTwo這個Activity:

Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因爲Category默認值即系Intent.CATEGORY_DEFAULT

            in.setType("leo.android.cursor.dir/vnd.google.liao");

            startActivity(in);

      或者這樣也可以啓動MyActivityTwo這個Activity:   

      Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因爲Category默認值即系Intent.CATEGORY_DEFAULT

            in.setType("leo.android.cursor.dir/vnd.google.leo");

            startActivity(in);

     

  

  scheme和mimeType只能有其中一個,下面這樣通不過

  AndroidManifest.xml裏:

  <data android:scheme="something" android:host="project.example.com"

android:port="80"

android:mimeType="leo.android.cursor.dir/vnd.google.leo" />  

<data android:scheme="something" android:host="project.example.com"

android:port="80" />

<data android:mimeType="leo.android.cursor.dir/vnd.google.leo" />

 

java代碼裏:

匹配不上:

Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            Uri uri = Uri.parse("something://project.example.com:80");

            in.setData(uri);

            in.setType("leo.android.cursor.dir/vnd.google.leo");

            startActivity(in);                  

            

            這樣還是匹配不上:

            Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

//            Uri uri = Uri.parse("something://project.example.com:80");

//            in.setData(uri);

            in.setType("leo.android.cursor.dir/vnd.google.leo");

            startActivity(in);

            

            這樣還是匹配不上:

            Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            Uri uri = Uri.parse("something://project.example.com:80");

            in.setData(uri);

//            in.setType("leo.android.cursor.dir/vnd.google.leo");

            startActivity(in);

            

            

            

(4)   一個Activity裏可以有多對<intent-filter></intent-filter>  只要匹配其中一對,即可啓動這個Activity

 

<activity android:name=".MyActivityTwo" android:label="@string/activityTwo">

<intent-filter>

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

<data android:scheme="something" android:host="project.example.com"

android:port="80" />

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

</intent-filter>

<intent-filter>

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

<data android:mimeType="leo.android.cursor.dir/vnd.google.leo" />

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

</intent-filter>

<intent-filter>

<action android:name="hello.hi.liao"></action>

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

</intent-filter>

</activity>

java代碼裏:

匹配第一對<intent-filter> 可以啓動MyActivityTwo這個Activity:

Intent in = new Intent();

            in.setAction("android.intent.action.VIEW");

            in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因爲Category默認值即系Intent.CATEGORY_DEFAULT

            Uri uri = Uri.parse("something://project.example.com:80");

            in.setData(uri);

            startActivity(in);

   匹配第二對<intent-filter> 也可以啓動MyActivityTwo這個Activity:    

   Intent in = new Intent();

   in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因爲Category默認值即系Intent.CATEGORY_DEFAULT

            in.setAction("android.intent.action.VIEW");

            in.setType("leo.android.cursor.dir/vnd.google.leo");

            startActivity(in);    

            

  匹配第三對<intent-filter> 也可以啓動MyActivityTwo這個Activity:      

  Intent in = new Intent();

            in.setAction("hello.hi.liao");

            in.addCategory(Intent.CATEGORY_DEFAULT);//可去掉,因爲Category默認值即系Intent.CATEGORY_DEFAULT

            startActivity(in);      

            

            

            

全部總結:

1.  <action/>包含在 <intent-filter></intent-filter> 標籤對裏,而且是必不可少的!不管以哪一種方式來匹配,都不可缺少這個<action/> ,可以有多個,至少要有一個。

如有多個的,話只需要匹配其中一個即可找到這個activity

<action>裏的屬性值大多數是在Intent裏定義的,比如<action android:name="android.intent.action.VIEW"/>裏的屬性值就等於 Intent.ACTION_VIEW,

在這個Intent類裏以ACTION開頭定義的常量都是。當然,也可以自定義。  

 

2.  任何一個需要隱式啓動的Activity都必須要有這項:<category android:name="android.intent.category.DEFAULT"/>

例外情況是:android.intent.category.MAIN和android.intent.category.LAUNCHER的filter中沒有必要加入android.intent.category.DEFAULT,當然加入也沒有問題  

<category> 裏的屬性值大多數是在Intent裏定義的,比如  <category android:name="android.intent.category.DEFAULT"/>裏的屬性值就等於 Intent.CATEGORY_DEFAULT,

在這個Intent類裏以CATEGORY開頭定義的常量都是。當然,也可以自定義。  

3.一個Activity裏可以有多對<intent-filter></intent-filter>  只要匹配其中一對,即可啓動這個Activity

 

  

 

4.在<intent-filter></intent-filter>裏可以有多個<data android:mimeType="xxxx"/>,只需匹配其中一個即可.注意:不可以同時出現第5點的標籤對,即下面這條。

 

 

 

 

5. 在<intent-filter></intent-filter>裏可以有多個<data android:scheme="xxxx" android:host="yyyy" android:port="uuu"/>,只需匹配其中一個即可。

語法:

<data android:host="string"

      android:mimeType="string"

      android:path="string"

      android:pathPattern="string"

      android:pathPrefix="string"

      android:port="string"

      android:scheme="string" />

      可以分開寫,如:

      <data android:scheme="something" android:host="project.example.com" android:port="80"/>

等同於這樣寫:

<data android:scheme="something"/>

<data android:host="project.example.com"/>

<data android:port="80"/>

在java代碼裏,Uri的格式:scheme://host:port/path or pathPrefix or pathPattern

注意:不可以同時出現第4點的標籤對,即上面那條。

 

6.在<intent-filter></intent-filter>裏可以有多個<action android:name="xxxx"> ,只需匹配其中一個即可。

 

 

 

7.當匹配不上任何Activity的話,會發生異常,跳出對話框:很抱歉...某某應用程序意外停止,請重試。

 

 

 

8. 上面所說的全部適用於Service和BroadcastReceiver,只需把<activity ...></activity>換成<service ...></service>或<receiver ...></receiver>即可。

 

9.剛參考了一下packages\apps\HTMLViewer\AndroidManifest.xml,第4和第5條應該是不衝突纔對,但是實際測試中卻是衝突,暫時未到找原因。匹配方式請看:用於打開HTML文件的intent

 

 

 在被啓動的Activity(本例爲MyActivityTwo)裏接收數據:

Intent intent = getIntent();

String intentCategories = intent.getCategories()

String intentType = intent.getType();

Uri uri = intent.getData();

String uriScheme = uri.getScheme();

String uriPath = uri.getPath();

String uriHost = uri.getHost();

String uriEncodedPath = uri.getEncodedPath();







轉載於http://4ever000-1988.iteye.com/blog/1602061

 Android 中各個組件主要是通過Intent來通訊。

    Intent負責對應用中一次操作的動作、動作涉及數據、附加數據進行描述,Android則根據此Intent的描述,負責找到對應的組件,將 Intent傳遞給調用的組件,並完成組件的調用。 

    Intent在這裏起着一個媒體中介的作用,專門提供組件互相調用的相關信息,實現調用者與被調用者之間的解耦。 sdk文檔對其描述如下: 

    An intent is an abstract description of an operation to be performed. It can be used with startActivity to launch an Activity, broadcastIntent to send it to any interested BroadcastReceiver components, and startService(Intent) or bindService(Intent, ServiceConnection, int) to communicate with a background Service. 
An Intent provides a facility for performing late runtime binding between the code in different applications. Its most significant use is in the launching of activities, where it can be thought of as the glue between activities. It is basically a passive data structure holding an abstract description of an action to be performed. The primary pieces of information in an intent are: 
    1. startActivity 
    2. broadcastIntent 
    3. startService() 

    4. bindService() 
    Intent的各個屬性:

    1. action ,是要執行的動作(action)的一個簡要描述,如VIEW_ACTION(查看)、EDIT_ACTION(修改)等,Android爲我們定義了一套標準動作。

    2. data,是執行動作要操作的數據(data),Android中採用指向數據的一個URI來表示。

    3. category,被執行動作的附加信息。例如 LAUNCHER_CATEGORY 表示Intent 的接受者應該在Launcher中作爲頂級應用出現;而ALTERNATIVE_CATEGORY表示當前的Intent被加進ALTERNATIVE intent列表裏面,用戶可以啓動。

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

    5. component(組件),指定Intent的的目標組件的類名稱。通常 Android會根據Intent 中包含的其它屬性的信息,比如action、data/type、category進行查找,最終找到一個與之匹配的目標組件。但是,如果 component這個屬性有指定的話,將直接使用它指定的組件,而不再執行上述查找過程。指定了這個屬性以後,Intent的其它所有屬性都是可選的。

    6. extras(附加信息),是其它所有附加信息的集合。使用extras可以爲組件提供擴展信息,比如,如果要執行“發送電子郵件”這個動作,可以將電子郵件的標題、正文等保存在extras裏,傳給電子郵件發送組件。

    在應用中,我們可以以兩種形式來使用Intent:  

    1:顯式Intent:指定了component屬性的Intent(調用setComponent(ComponentName)或者setClass(Context, Class)來指定)。通過指定具體的組件類,通知應用啓動對應的組件。

    2:隱式Intent:沒有指定comonent屬性的Intent。這些Intent需要包含足夠的信息,這樣系統才能根據這些信息,在在所有的可用組件中,確定滿足此Intent的組件。 

    應用程序的組件爲了告訴Android系統自己能響應、處理哪些隱式Intent請求,可以聲明一個甚至多個IntentFilter。每個IntentFilter描述該組件所能響應Intent請求的能力——組件希望接收什麼類型的請求行爲,什麼類型的請求數據。比如:網頁瀏覽器程序的IntentFilter就應該聲明它所希望接收的Intent Action是WEB_SEARCH_ACTION,以及與之相關的請求數據是網頁地址URI格式。 

    隱式Intent和IntentFilter進行比較時的三要素是Intent的Action、Data以及Category。實際 上,一個隱式Intent請求要能夠傳遞給目標組件,必要通過這三個方面的檢查。如果任何一方面不匹配,Android都不會將該隱式Intent傳遞給 目標組件。 

    對於直接Intent,Android不需要去做解析,因爲目標組件已經很明確,Android需要解析的是那些間接Intent,通過解析,將 Intent映射給可以處理此Intent的Activity、IntentReceiver或Service。 

    Intent解析機制主要是通過查找已註冊在AndroidManifest.xml中的所有IntentFilter及其中定義的Intent,最終找到匹配的Intent。在這個解析過程中,Android是通過Intent的action、type、category這三個屬性來進行判斷的,判斷方法如下: 

    1.如果Intent指明定了action,則目標組件的IntentFilter的action列表中就必須包含有這個action,否則不能匹配。 
    2.如果Intent沒有提供type,系統將從data中得到數據類型。和action一樣,如果Intent指明定了type,目標組件的數據類型列表中必須包含Intent的數據類型,否則不能匹配。 
    3.如果Intent中的數據不是content: 類型的URI,而且Intent也沒有明確指定它的type,將根據Intent中數據的scheme (比如 http: 或者mailto: ) 進行匹配。同上,Intent 的scheme必須出現在目標組件的scheme列表中。 
    4.如果Intent指定了一個或多個category,這些類別必須全部出現在組件的類別列表中。比如Intent中包含了兩個類別:LAUNCHER_CATEGORY 和 ALTERNATIVE_CATEGORY,解析得到的目標組件必須至少包含這兩個類別。Activities will very often need to support the CATEGORY_DEFAULT so that they can be found by Context.startActivity(). 
    5.如果category 指定了ALTERNATIVE and SELECTED_ALTERNATIVE.則可以通過queryIntentActivityOptions(ComponentName, Intent[], Intent, int),查詢Activity的action,addIntentOptions(int, int, int, ComponentName, Intent[], Intent, int, MenuItem[])增加action等信息。

 


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