Android学习笔记--activity component:intents

    

   当接收到ContentResolver的请求时Content Provider被激活。其它的三个组件activityservicebroadcast receiver是通过一个叫做intents的异步消息来激活的。一个intent是一个承载消息内容的intent对象。对于activityservice来说,它声明了请求的操作名称以及操作的特殊的数据URI和另外一些信息。比如说,它可以承载对一个activity的请求,让它为用户显示一张图片,或者让用户编辑一些文本。而对于广播接收器而言,Intent对象指明了声明的行为。比如,它可以对所有感兴趣的对象声明照相按钮被按下。

     对于每种组件来说,激活的方法是不同的:

l           一个activity的运行(或者让它执行新的任务)是通过传递intent对给Context.startActivity()或者Activity.startActivityForResult()方法来实现的。响应的activity可以通过调用 getIntent() 方法来查看激活它的intentAndroid通过调用activityonNewIntent()方法来传递给它继发的intents
一个activity经常启动了下一个。如果它期望它所启动的那个activity返回一个结果,它会以调用startActivityForResult()来取代startActivity()。比如说,如果它启动了另外一个activity以使用户挑选一张照片,它也许想知道哪张照片被选中了。结果将会被封装在一个Intent对象中,并传递给发出调用的activityonActivityResult() 方法。

l           通过传递一个Intent对象至Context.startService()将启动一个服务(或给予正在运行的服务以一个新的指令)。Android调用服务的 onStart()方法并将Intent对象传递给它。
与此类似,一个Intent可以被调用组件传递给 Context.bindService()以获取一个正在运行的目标服务的连接。这个服务会经由onBind() 方法的调用获取这个Intent对象(如果服务尚未启动,bindService()会先启动它)。比如说,一个activity可以连接至前述的音乐回放服务,并提供给用户一个可操作的(用户界面)以对回放进行控制。这个activity可以调用 bindService() 来建立连接,然后调用服务中定义的对象来影响回放。
后面一节:远程方法调用将更详细的阐明如何绑定至服务。

l           应用程序可以凭借将Intent对象传递给 Context.sendBroadcast() Context.sendOrderedBroadcast(),以及Context.sendStickyBroadcast()和其它类似方法来产生一个广播。Android会调用所有对此广播有兴趣的广播接收器的 onReceive()方法,将intent传递给它们。

       

Intents and Intent Filters

 

   应用程序的三个核心组件activityservicebroadcast receiver是通过intents消息来激活的。Intent消息对于同一或不同应用程序组件之间的延时运行时绑定很容易。Intent本身是一个intent对象,是一个承载要执行的操作的描述的无源数据结构,或者是一些要声明或者发生事件的描述的广播。不同种类的组件传递intent使用的机制不同。

     在上述提到的每一种情况下Android系统都会去寻找相近的组件来响应intent,如果有必要的话也会对它进行实例化。在这些消息系统中不会出现重叠的现象,即Broadcast消息仅仅会被传送个给broadcast receiver,不会传递给activity或者service。同样一个intent消息通过startActivity()仅仅传递给activity而不会传递给其它的组件。

Intent Objects

一个intent对象就是信息的绑定。它包含一些对组件比较有用信息,而这个组件能够接收这个intent(例如执行的行为以及操作的数据)以及附加的一些对android系统有用的信息(如组件的应该处理如何启动一个目标activity的消息和结构的分类)。主要包含了以下几种:

u          Component name

u          Action

u          Data

u          Category

u          Extras

u          Flags

       

Intent Resolution

Intents可以分为以下两组:

l           Explicit intents:显性intent,指定了component属性的intent。通过指定具体的组件类,通知应用程序启动对应的组件。因为通常其他应用程序的开发者不会知道component name,所以explicit intent通常被用于应用程序内部的通信,如一个activity开始一个从属服务或者启动一个姐妹activity

通过setComponent(ComponentName)或者setClassContext,Class)来设置需要通信的component

l           Implicit intents:不会给component指定属性。常用来激活其它应用程序的组件。

Android给设计的目标类的实例提供一个explicit intent。在这个intent对象中除了一个用来决定哪个组件应该得到intent的组件名外没有任何东西。

对于直接IntentAndroid不需要去做解析,因为目标组件已经很明确,Android需要解析的是那些间接Intent,通过解析,将 Intent映射给可以处理此IntentActivityIntentReceiverService

Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Intent,最终找到匹配的Intent。在这个解析过程中,Android是通过Intentactiontypecategory这三个属性来进行判断的,判断方法如下:

如果Intent指明定了action,则目标组件的IntentFilteraction列表中就必须包含有这个action,否则不能匹配;

如果Intent没有提供type,系统将从data中得到数据类型。action一样,目标组件的数据类型列表中必须包含Intent的数据类型,否则不能匹配。

如果Intent中的数据不是content: 类型的URI,而且Intent也没有明确指定它的type,将根据Intent中数据的scheme (比如 http: 或者mailto: ) 进行匹配。同上,Intent scheme必须出现在目标组件的scheme列表中。

如果Intent指定了一个或多个category,这些类别必须全部出现在组建的类别列表中。比如Intent中包含了两个类别:LAUNCHER_CATEGORY ALTERNATIVE_CATEGORY,解析得到的目标组件必须至少包含这两个类别。

 

下面我们来看看这个实例:

<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>

 

  第一个activitycom.android.notepad.NotesList,它也是应用程序的主要入口。它提供了三个主要的功能,用三个intent-filter来描述:

1.     第一个为进入NotePad应用程序的顶级入口,标准的MAIN action表明是一个主要的入口点,LAUNCHER category 表明这个activity在应用程序启动时候列出。

   <intent-filter>

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

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

 </intent-filter>

 

2.     第二个intent-filter声明了这个activitynotes目录下可以做的一些事情。这里用<type>标签给出了所支持的类型,这个标签vnd.android.cursor.dir/vnd.google.note是一个URI,它来自没有或有多个能够恢复承载便筏信息的items,这些项目描述为vnd.android.cursor.dir而将承载便筏数据的描述为vnd.google.note这个activity允许用户查看和编辑数据目录(通过VIEW EDIT action,或者用户可以选择一个便筏并返回给调用者(通过PICK action)。这个activity在这里也提供了一个DEFAULT category,这就需要在没有明确给出组件名称的时候通过Context.startActivity()方法来处理activity

     <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 mimeType:name="vnd.android.cursor.dir/vnd.google.note" />

 </intent-filter>

 

3.     第三个filter描述了返回给调用者一个用户所选择的便筏的功能,用户不需要知道这个便筏来自哪里。GET_CONTENT actionPICK action很相似,它们都是要返回给调用者用户所选择的数据片。然而,这里调用者详细明确了他们所要的数据类型,而不是用用户选择的方式。

<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>

l           { action=android.app.action.MAIN }:与此Intent匹配的Activity,将会被当作进入应用的顶级入口。

l           { action=android.app.action.MAIN, category=android.app.category.LAUNCHER }:这是目前Launcher实际使用的 Intent,用于生成Launcher的顶级列表。

l           { action=android.app.action.VIEW data=content://com.google.provider.NotePad/notes }:显示"content://com.google.provider.NotePad/notes"下的所有便笺的列表,使用者可以遍历列表,并且察看某便笺的详细信息。

l           { action=android.app.action.PICK data=content://com.google.provider.NotePad/notes }:显示"content://com.google.provider.NotePad/notes"下的便笺列表,让用户可以在列表中选择一个,然后将选择的便笺的 URL返回给调用者。

l           { action=android.app.action.GET_CONTENT type=vnd.android.cursor.item/vnd.google.note }:和上面的actionpickIntent类似,不同的是这个Intent允许调用者(在这里指要调用NotesList的某个 Activity)指定它们需要返回的数据类型,系统会根据这个数据类型查找合适的 Activity(在这里系统会找到NotesList这个Activity),供用户选择便笺。

     第二个activitycom.android.notepad.NoteEditor,它给用户显示一个便筏,并且允许用户来编辑这个便筏。同样这里又两个filter来实现了这个activity的两个功能:

l           第一个功能是,当数据类型为 vnd.android.cursor.item/vnd.google.note时,允许用户查看和修改一个便签(action android.app.action.VIEWandroid.app.action.EDIT)。

<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>

 

l           第二个功能是,当数据类型为 vnd.android.cursor.dir/vnd.google.note,为调用者显示一个新建便笺的界面,并将新建的便笺插入到便笺列表中(actionandroid.app.action.INSERT)。

     <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>

 

有了这两个功能,下面的Intent就会被解析到NoteEditor这个activity

l           { action=android.app.action.VIEW data=content://com.google.provider.NotePad/notes/{ID}} :向用户显示标识为 ID的便笺。

l           { action=android.app.action.EDIT data=content://com.google.provider.NotePad/notes/{ID}}:允许用户编辑标识为ID的便笺。

l           { action=android.app.action.INSERT data=content://com.google.provider.NotePad/notes }:在“content://com.google.provider.NotePad/notes”这个便笺列表中创建一个新的空便笺,并允许用户编辑这个便签。当用户保存这个便笺后,这个新便笺的URI将会返回给调用者。

    最后一个Activitycom.google.android.notepad.TitleEditor,它允许用户编辑便笺的标题。

它可以被实现为一个应用可以直接调用(在Intent中明确设置component属性)的类,不过这里我们将为你提供一个在现有的数据上发布可选操作的方法。在这个 Activity的唯一的intent-filter中,拥有一个私有的action com.google.android.notepad.action.EDIT_TITLE,表明允许用户编辑便笺的标题。和前面的viewedit 动作一样,调用这个Intent 的时候,也必须指定具体的便笺(typevnd.android.cursor.item/vnd.google.note)。不同的是,这里显示和编辑的只是便笺数据中的标题。除了支持缺省类别(android.intent.category.DEFAULT),标题编辑器还支持另外两个标准类别: android.intent.category.ALTERNATIVEandroid.intent.category.SELECTED_ALTERNATIVE

    实现了这两个类别之后,其它 Activity就可以调用queryIntentActivityOptions(ComponentName, Intent[], Intent, int)查询这个Activity提供的action,而不需要了解它的具体实现;或者调用addIntentOptions(int, int, ComponentName, Intent[], Intent, int, Menu.Item[])建立动态菜单。需要说明的是,在这个intent-filter中有一个明确的名称(通过android:label= "@string/resolve_title"指定),在用户浏览数据的时候,如果这个Activity是数据的一个可选操作,指定明确的名称可以为用户提供一个更好控制界面。

有了这个功能,下面的Intent就会被解析到TitleEditor这个Activity
{ action=com.google.android.notepad.action.EDIT_TITLE data=content://com.google.provider.NotePad/notes/{ID}}
:显示并且允许用户编辑标识为ID的便笺的标题。

 

----------------------------------------------------------------------------------

 英语水平有限,仅供参考~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值