Intent是一个需要进行的操作的抽象描述
1.通过startActivity
可以用来启动一个Activity
2.broadcastIntent
可以发送一些Intent到注册了BroadcastReceiver的具体部件
3.通过startService(Intent)或者
bindService(Intent, ServiceConnection, int)
启动或者绑定一个后台的Service
Intent提供了一种在不同Application之间进行绑定的能力,最能体现出来的是在启动一个Activity的时候,它可以被看作Activity之间的粘合剂。它基本上是一种用来抽象action的数据结构。
Intent Structure
在一个Intent中基础的信息字段包括: action:一个需要执行的操作,例如 ACTION_VIEW
, ACTION_EDIT
, ACTION_MAIN
,等。
data:需要被操作的数据,例如一个被保存在数据库的联系人信息,表现形式为一个Uri
一些action/data的数据对儿:
-
ACTION_VIEW
content://contacts/people/1 -- 打印一个定义为1的人的信息 -
ACTION_DIAL
content://contacts/people/1 -- 打开一个拨号器包含1的信息 -
ACTION_VIEW
tel:123 -- 打开一个拨号器包含所给的电话号码 -
ACTION_DIAL
tel:123 -- 打开一个拨号器填入所给电话号码 -
ACTION_EDIT
content://contacts/people/1 -- 编辑1的个人信息 -
ACTION_VIEW
content://contacts/people/ -- 打印一个联系人列表。这是一个典型的进入联系人Application顶层的例子,显示出所有联系人。选择一个特定的人去打印出来,通过一个新的Intent{ACTION_VIEW
content://contacts/N} 打开一个新的activity显示个人信息。
为了这些基础属性,有大量的二级属性你可以放在Intent中:
-
category -- 给一些操作执行时需要的额外的属性。例如
CATEGORY_LAUNCHER
意思是说他应该作为一个顶级的Application出现在Launcher中,CATEGORY_ALTERNATIVE
意思是说他应该包含一系列对数据的操作 -
type -- 指定一个Intent数据的具体类型。通常类型是由数据本身推断出来的。通过设置这些属性,你禁用那些推断,并指出具体的类型。
-
component -- 为Intent指定一个具体的部件名称。通常这个是根据Intent中其他的信息(the action, data/type, and categories)去匹配一个可以处理它的部件,如果这个属性被设置,那么就不需要去判断,部件被明确的指出。通过指出这些属性所有其他的Intent的属性变得可选。
-
extras -- 这是一个包含其他额外信息的Bundle。它能够为部件提供大量的信息。例如,如果我们有一个发送email的操作,我们可以包括其他的数据片段,主题、正文等。
这有一些你可以通过Intent指定这些额外的参数去定义的操作。
-
ACTION_MAIN
with categoryCATEGORY_HOME
-- 返回主屏幕。 -
ACTION_GET_CONTENT
with MIME typevnd.android.cursor.item/phone
-- 打印联系人电话号码列表,允许用户查看并且选择一个返回父Activity -
ACTION_GET_CONTENT
with MIME type */* and categoryCATEGORY_OPENABLE
-- 打印所有能够通过ContentResolver.openInputStream()打开的数据
,允许用户选择一个和一些其中的数据通过URI返回给调用者。这个可以用来向e-mail应用中添加一些数据作为附件。
在Intent类中定义了许多标准的action和category constants。但是应用本身也可以定自己的Intent,这些字符串用了java标准的编码规则,为了确保唯一性,例如 ACTION_VIEW
被称为"android.intent.action.VIEW"
把action、data types、categories 和 extra data 定义为系统通过短语进行表达的语言。一个应用可以通过扩展action、types 和 categories来扩展自己的语言,或者可以在自己的Activities中更改对这些短语的使用方法。
Intent Resolution
你会用到两种Intents的基本形式Explicit Intents 明确指出了需要运行的部件(通过 setComponent(ComponentName)
orsetClass(Context, Class)
),通常这种情况下不会包括一些其他的信息,只是简单地对用户与应用进行交互时launch内部的activity。
Implicit Intents 没有明确的指出部件,与之前的不同的是,它必须包含足够的信息,以此来让系统判断哪个可用的部件可以使用这个Intent
当使用Implicit Intents ,给了一个任意的Intent,我们需要知道应该怎么去处理它,这个工作是由Intent resolution线程去解决的,把Intent指向可以处理他的 Activity
, BroadcastReceiver
, or Service(
或者有时有多个activities/receivers )。
intent resolution 机制主要解决了Intent与在包中描述的 <intent-filter>之间匹配的问题。
有三个主要的信息提供给resolution用来判断:action, type, 和 category。通过这些信息,
PackageManager会
对每一个部件进行一次询问。最合适部件的判断是基于AndroidManifest.xml中的Intent信息:
-
The action,如果给定,必须有组件做为其句柄来列出。
-
The type 是从Intent的数据中获取到的,如果没有在Intent中给出。例如一些action,如果一个Intent中包含type(无论是明确或者是不明确的)必须有组件做为其句柄来列出。
- 如果数据不是一个
content:
URI 而且在Intent中没有明确类型, 例如 http: 或者mailto:又和Action一样,如果给定,必须有组件做为其句柄来列出 - The categories,如果使用, 必须在activity中列出category的句柄. 更确切地说, 如果你是用
CATEGORY_LAUNCHER
和CATEGORY_ALTERNATIVE
, 然后这个部件只会解决包含这两个categories的Intent. Activities 经常需要支持CATEGORY_DEFAULT
只有那样才能被Context.startActivity()发现
.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.notepad"> <application android:icon="@drawable/app_notes" android:label="@string/app_name"> <provider class=".NotePadProvider" android:authorities="com.google.provider.NotePad" /> <activity class=".NotesList" android:label="@string/title_notes_list"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.EDIT" /> <action android:name="android.intent.action.PICK" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.GET_CONTENT" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> </intent-filter> </activity> <activity class=".NoteEditor" android:label="@string/title_note"> <intent-filter android:label="@string/resolve_edit"> <action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.EDIT" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.INSERT" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" /> </intent-filter> </activity> <activity class=".TitleEditor" android:label="@string/title_edit_title" android:theme="@android:style/Theme.Dialog"> <intent-filter android:label="@string/resolve_title"> <action android:name="com.android.notepad.action.EDIT_TITLE" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.ALTERNATIVE" /> <category android:name="android.intent.category.SELECTED_ALTERNATIVE" /> <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> </intent-filter> </activity> </application> </manifest>
第一个Activity, com.android.notepad.NotesList
,提供我们进入app的主函数入口,他可以通过三个Intent模板的描述来做三件事:
<intent-filter> <action android:name="android.intent.action.MAIN
" /> <category android:name="android.intent.category.LAUNCHER
" /> </intent-filter>
提供一个顶级的入口给Note Pad应用:标准的MAIN action是一个主函数入口点(在Intent中不需要一些其他的信息),LAUNCHER category说明这个入口点需要被列在application launcher
<intent-filter> <action android:name="这里声明的东西是说activity可以在一个note的目录下做什么事情。支持的操作需要通过标签去声明,android.intent.action.VIEW
" /> <action android:name="android.intent.action.EDIT
" /> <action android:name="android.intent.action.PICK
" /> <category android:name="android.intent.category.DEFAULT
" /> <data mimeType:name="vnd.android.cursor.dir/vnd.google.note" /> </intent-filter>
vnd.android.cursor.dir/vnd.google.note
是一个URI用来获取我们在(vnd.android.cursor.dir
)下面的note pad数据(vnd.google.note
)。这个Activity允许用户去查看或者更改目录数据(通过VIEW或者EDIT的操作),或者选择一个详细的note并且返回给调用者(通过PICK操作)。注意,这里有默认提供的category:当没有明确说明部件名称时这里需要提供给Context.startActivity方法用来启动Activity
<intent-filter> <action android:name="这个filter描述了不需要知道Intent来源而返回给调用者一个选择的note.android.intent.action.GET_CONTENT
" /> <category android:name="android.intent.category.DEFAULT
" /> <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> </intent-filter>
vnd.android.cursor.dir/vnd.google.note
是一个URI用来获取我们在(vnd.android.cursor.dir
)下面的note pad数据(vnd.google.note
)。GET_CONTENT就像一个PICK 动作,activity会返回给调用者一段数据。这里,然而调用者明确指出了他们想要的数据类型,而不是用户将从这得到的。
根据给定的能力,下列的Intent可以传入到这个Activity中:
-
{ action=android.app.action.MAIN } 匹配所有可以当做Application顶级入口的Activity。
-
{ action=android.app.action.MAIN, category=android.app.category.LAUNCHER } 一个Intent被Launcher添加在顶级列表中
-
{ action=android.intent.action.VIEW data=content://com.google.provider.NotePad/notes } 打印在"content://com.google.provider.NotePad/notes"下面的所有notes,用户可以用来浏览目录。
-
{ action=android.app.action.PICK data=content://com.google.provider.NotePad/notes } 打印一个在"content://com.google.provider.NotePad/notes"下面的所有notes的列表,用户可以选择一个并得到它的URL
-
{ action=android.app.action.GET_CONTENT type=vnd.android.cursor.item/vnd.google.note } 很像PICK操作,但是允许调用者指定返回类型,那样系统会选择最接近的Activity去接受数据。
第二个Activity, com.android.notepad.NoteEditor,
给用户展示一个note,并允许用户去修改,他能做下面描述两件事:
<intent-filter android:label="@string/resolve_edit"> <action android:name="第一,Activity最基础的目的是让用户操作一个note,像 MIME typeandroid.intent.action.VIEW
" /> <action android:name="android.intent.action.EDIT
" /> <category android:name="android.intent.category.DEFAULT
" /> <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> </intent-filter>
vnd.android.cursor.item/vnd.google.note
. 描述的一样。Activity允许用户去查看或者标记它,之后我们支持DEFAULT category,这样允许Activity 在没有明确指出他的部件时Launch。
<intent-filter> <action android:name="第二个是可以通过Activity向目录中插入一个新的note。这个用来在用户创建新note时使用: INSERT 操作在note目录上执行,然后再该Activity创建新的note,之后添加到对应的content provider中去。android.intent.action.INSERT
" /> <category android:name="android.intent.category.DEFAULT
" /> <data android:mimeType="vnd.android.cursor.dir/vnd.google.note" /> </intent-filter>
根据给定的能力,下列的Intent可以传入到这个Activity中:
-
{ action=android.intent.action.VIEW data=content://com.google.provider.NotePad/notes/{ID} } 向用户展示出note内容 根据{ID}.
-
{ action=android.app.action.EDIT data=content://com.google.provider.NotePad/notes/{ID} }允许用户编辑内容通过 {ID}.
-
{ action=android.app.action.INSERT data=content://com.google.provider.NotePad/notes } 创建一个新的、空的note在"content://com.google.provider.NotePad/notes"目录下,允许用户编辑,如果保存修改,新创建的URI会返回给调用者。
<intent-filter android:label="@string/resolve_title"> <action android:name="com.android.notepad.action.EDIT_TITLE" /> <category android:name="android.intent.category.DEFAULT
" /> <category android:name="android.intent.category.ALTERNATIVE
" /> <category android:name="android.intent.category.SELECTED_ALTERNATIVE
" /> <data android:mimeType="vnd.android.cursor.item/vnd.google.note" /> </intent-filter>
vnd.android.cursor.item/vnd.google.note
)像之前的浏览和编辑一样,但是这里浏览和编辑的标题是在note数据里面。
为了支持像之前一样支持default category,我们的标题编辑器也需要支持两个或者其他标准的categories: ALTERNATIVE and SELECTED_ALTERNATIVE。实现这些categories,允许其他人去寻找没有直接了解到的其他特殊的action,通过
queryIntentActivityOptions(ComponentName, Intent[], Intent, int)
方法, 或者经常建立动态菜单选项通过 addIntentOptions(int, int, int, ComponentName, Intent[], Intent, int, MenuItem[])
。注意在Intent里面也以来一个明确的名字(android:label="@string/resolve_title")
用来更好控制用户看见的每个具体action对应的Activity
。
根据给定的能力,下列的Intent可以传入到这个TitleEditor Activity中:
{ action=com.android.notepad.action.EDIT_TITLE data=content://com.google.provider.NotePad/notes/{ID} } 打印并且允许用户去编辑note根据 {ID}.
Standard Activity Actions
这些流行的标准action Intent是用来launching activities(通常通过startActivity(Intent)
)。到目前为止最常用的是 ACTION_MAIN
和 ACTION_EDIT
.
ACTION_MAIN
ACTION_VIEW
ACTION_ATTACH_DATA
ACTION_EDIT
ACTION_PICK
ACTION_CHOOSER
ACTION_GET_CONTENT
ACTION_DIAL
ACTION_CALL
ACTION_SEND
ACTION_SENDTO
ACTION_ANSWER
ACTION_INSERT
ACTION_DELETE
ACTION_RUN
ACTION_SYNC
ACTION_PICK_ACTIVITY
ACTION_SEARCH
ACTION_WEB_SEARCH
ACTION_FACTORY_TEST
Standard Broadcast Actions
这些流行的标准action Intent是用来接收广播( 通常通过registerReceiver(BroadcastReceiver, IntentFilter)
或者在manifest中的 <receiver>标签)
ACTION_TIME_TICK
ACTION_TIME_CHANGED
ACTION_TIMEZONE_CHANGED
ACTION_BOOT_COMPLETED
ACTION_PACKAGE_ADDED
ACTION_PACKAGE_CHANGED
ACTION_PACKAGE_REMOVED
ACTION_PACKAGE_RESTARTED
ACTION_PACKAGE_DATA_CLEARED
ACTION_UID_REMOVED
ACTION_BATTERY_CHANGED
ACTION_POWER_CONNECTED
ACTION_POWER_DISCONNECTED
ACTION_SHUTDOWN
Standard Categories
这些流行的标准 categories是通过addCategory(String)来进一步明确Intent
CATEGORY_DEFAULT
CATEGORY_BROWSABLE
CATEGORY_TAB
CATEGORY_ALTERNATIVE
CATEGORY_SELECTED_ALTERNATIVE
CATEGORY_LAUNCHER
CATEGORY_INFO
CATEGORY_HOME
CATEGORY_PREFERENCE
CATEGORY_TEST
CATEGORY_CAR_DOCK
CATEGORY_DESK_DOCK
CATEGORY_LE_DESK_DOCK
CATEGORY_HE_DESK_DOCK
CATEGORY_CAR_MODE
CATEGORY_APP_MARKET
Standard Extra Data
这些流行的标准 fields是通过
putExtra(String, Bundle)来添加额外的数据。
EXTRA_ALARM_COUNT
EXTRA_BCC
EXTRA_CC
EXTRA_CHANGED_COMPONENT_NAME
EXTRA_DATA_REMOVED
EXTRA_DOCK_STATE
EXTRA_DOCK_STATE_HE_DESK
EXTRA_DOCK_STATE_LE_DESK
EXTRA_DOCK_STATE_CAR
EXTRA_DOCK_STATE_DESK
EXTRA_DOCK_STATE_UNDOCKED
EXTRA_DONT_KILL_APP
EXTRA_EMAIL
EXTRA_INITIAL_INTENTS
EXTRA_INTENT
EXTRA_KEY_EVENT
EXTRA_ORIGINATING_URI
EXTRA_PHONE_NUMBER
EXTRA_REFERRER
EXTRA_REMOTE_INTENT_TOKEN
EXTRA_REPLACING
EXTRA_SHORTCUT_ICON
EXTRA_SHORTCUT_ICON_RESOURCE
EXTRA_SHORTCUT_INTENT
EXTRA_STREAM
EXTRA_SHORTCUT_NAME
EXTRA_SUBJECT
EXTRA_TEMPLATE
EXTRA_TEXT
EXTRA_TITLE
EXTRA_UID