一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

關(guān)于Android隱式啟動Activity的分析和說明

 Ebric 2012-05-31

關(guān)于Android隱式啟動Activity的分析和說明
Android開發(fā)當(dāng)中我們知道,每個組件可以有一個或者多個intent filter。提到Intent filter我們就來了解下Intent filter,Intent filter有三個部分構(gòu)成,分別是action,data和category。Intent filter是在Android的主配置文件AndroidManifest.xml中注冊,主要用來指明Activity, Service, Broadcast reciver這三個組件可以響應(yīng)哪些隱式intents。

  下面通過代碼分析每個部分的功能。

  <intent-filter android:label="@string/Asen's blog">

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

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

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

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

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

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

  <data android:mimeType="video/mpeg" android:scheme="http".../>

  <data android:mimeType="audio/mpeg" android:content="com.example.project:200/folder/subfolder/etc"/>

  </intent-filter>

  每個action, category, data都是一行,如果有多個就寫多行。"android.intent.action.MAIN" and "android.intent.category.LAUNCHER"這兩個是程序入口點(diǎn)的filter必須部分。比如說短信這個應(yīng)用,當(dāng)你點(diǎn)擊MMS的圖標(biāo)程序啟動后,映入使用者的一個界面(所有收到的短信列表),這個短信列表界面就是程序的入口點(diǎn),通俗的講就是一個application啟動后顯示的第一個界面。另外,"android.intent.category.DEFAULT"這個category是用來指明組件是否可以接收到隱式Intents,所以說除了程序入口點(diǎn)這個filter不用包含DEFAULT category外,其余所有intent filter都要有這個category。

  data有兩部分構(gòu)成,一個是數(shù)據(jù)類型,另一個是URI。每個URI包括四個屬性參數(shù)(scheme,host, port, path),形如:scheme://host:port/path

  Intent filter和Intent相互配合,實(shí)現(xiàn)了Android系統(tǒng)四大組件之間的信使功能。



詳細(xì)例子說明

  舉個例子 content://com.examplproject:e.200/folder/subfolder/etc 這個列子中scheme是content,host是com.examplproject,port是200,path是folder/subfolder/etc


更多例子請參考:http://hi.baidu.com/wishwingliao/blog/item/0a38ccfce06f39e8fc037f85.html

隱式啟動Activity的intent到底發(fā)給哪個activity,需要進(jìn)行三個匹配,一個是action,一個是category,一個是data,可以是全部或部分匹配

同樣適用于Service和BroadcastReceiver,下面是以Activity為例

MainActivity.java --主Activity

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

(1) 根據(jù)Action和Category來進(jìn)行匹配

         <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");

//不加下面這行也行,因?yàn)閕ntent的這個屬性默認(rèn)值即系Intent.CATEGORY_DEFAULT

intent.addCategory(Intent.CATEGORY_DEFAULT);

startActivity( intent );

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

  發(fā)送了這個intent之后,android會去系統(tǒng)里保存的MainManifest.xml清單(假設(shè)這個系統(tǒng)存放全部apk清單的文件為MainManifest.xml)里查找符合這兩個屬性的activity,然后啟動它。

  查找過程是怎樣的呢?

  我猜測:在安裝某個apk的時候,android系統(tǒng)會把這個apk的清單文件里內(nèi)容復(fù)制一份至系統(tǒng)的某個清單文件里(假如這個系統(tǒng)存放全部apk清單的文件為MainManifest.xml)

  當(dāng)某個Activity用startActivity(intentOther)方法向系統(tǒng)發(fā)送了一個intent(假如為intentOther),那么android系統(tǒng)會去查找這個MainManifest.xml里注冊的<intent-filter >屬性,

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

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

  所以系統(tǒng)很容易就能匹配到。

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

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

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里發(fā)送一個intent:

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

//不加下面這行也行,因?yàn)閕ntent的這個屬性默認(rèn)值即系Intent.CATEGORY_DEFAULT

intent.addCategory(Intent.CATEGORY_DEFAULT);

startActivity( intent );

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

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

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

如果category相同,而action不相同,就可以匹配到相應(yīng)的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.當(dāng)匹配不上任何Activity的話,會發(fā)生異常,跳出對話框:很抱歉...某某應(yīng)用程序意外停止,請重試。

f.Service和BroadcastReceiver 同理

(2) 根據(jù)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);//可以去掉這行,因?yàn)閕ntent的默認(rèn)category值即系Intent.CATEGORY_DEFAULT

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

            startActivity(in);

總結(jié):如果在AndroidManifest.xml里面指定了<data>這行,那么,需要匹配到它的話,在代碼里必須要設(shè)置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)  根據(jù)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);//可去掉,因?yàn)镃ategory默認(rèn)值即系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);//可去掉,因?yàn)镃ategory默認(rèn)值即系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);//可去掉,因?yàn)镃ategory默認(rèn)值即系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);//可去掉,因?yàn)镃ategory默認(rèn)值即系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);//可去掉,因?yàn)镃ategory默認(rèn)值即系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);//可去掉,因?yàn)镃ategory默認(rèn)值即系Intent.CATEGORY_DEFAULT

            startActivity(in);      

全部總結(jié):

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

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

<action>里的屬性值大多數(shù)是在Intent里定義的,比如<action android:name="android.intent.action.VIEW"/>里的屬性值就等于 Intent.ACTION_VIEW,

在這個Intent類里以ACTION開頭定義的常量都是。當(dāng)然,也可以自定義。  

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

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

<category>里的屬性值大多數(shù)是在Intent里定義的,比如  <category android:name="android.intent.category.DEFAULT"/>里的屬性值就等于 Intent.CATEGORY_DEFAULT,

在這個Intent類里以CATEGORY開頭定義的常量都是。當(dāng)然,也可以自定義。  

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

4.在<intent-filter></intent-filter>里可以有多個<data android:mimeType="xxxx"/>,只需匹配其中一個即可.注意:不可以同時出現(xiàn)第5點(diǎn)的標(biāo)簽對,即下面這條。

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

注意:不可以同時出現(xiàn)第4點(diǎn)的標(biāo)簽對,即上面那條。

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

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

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

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

 在被啟動的Activity(本例為MyActivityTwo)里接收數(shù)據(jù):

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();

請參考:packages\apps\HTMLViewer\src\com\android\htmlviewer\HTMLViewerActivity.java

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产精品一区二区三区欧美| 亚洲欧美日韩国产自拍| 最新午夜福利视频偷拍| 亚洲专区中文字幕在线| 日韩成人免费性生活视频| 国产精品久久女同磨豆腐| 久久精品国产第一区二区三区| 精品欧美在线观看国产| 久久精品国产在热亚洲| 亚洲综合伊人五月天中文| 日本不卡在线一区二区三区| 欧美性高清一区二区三区视频 | 日本男人女人干逼视频| 欧美亚洲综合另类色妞| 91福利免费一区二区三区| 欧美性欧美一区二区三区| 日韩一区二区三区在线欧洲| 亚洲综合香蕉在线视频| 欧美一级片日韩一级片| 99视频精品免费视频| 国产肥妇一区二区熟女精品| 国产欧美一区二区久久| 在线观看视频成人午夜| 国产激情一区二区三区不卡| 日韩在线视频精品中文字幕| 日本女优一区二区三区免费| 久久黄片免费播放大全| 日韩中文字幕在线不卡一区| 蜜桃传媒在线正在播放| 风韵人妻丰满熟妇老熟女av| 高清亚洲精品中文字幕乱码| 四季精品人妻av一区二区三区| 黄色美女日本的美女日人| 欧美日韩精品人妻二区三区| 日韩欧美中文字幕av| 国产精品激情在线观看| 91日韩欧美国产视频| 日韩蜜桃一区二区三区| 国产中文字幕久久黄色片| 日本特黄特色大片免费观看| 国产欧洲亚洲日产一区二区|