編輯:初級開發
隱式啟動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();
前言關鍵字: DigitalClock date formatandroid的DigitalClock並沒有設置輸出格式的屬性或方法,但是可以通過繼承重寫來實現,見正文
AppWidgetManager作為android平台上最主要的Widgets管理類,提供了更新AppWidget狀態,獲取已經安裝的Appwidget提供信息和其他的
在本章我們會接觸到這兩個單詞:Zygote [生物] 受精卵, 接合子, 接合體Spawn:產卵通過這兩個單詞,我們就可以大體知道Zygote是干什麼的了,就是叫老母雞
package com.example.android.apis.graphics;23.TextAlign: 設置Path路徑,貝賽爾曲線1: