Android Intent详解...

 

 
Intent 详解
一、 Intent 作用
Intent 是一个将要执行的动作的抽象的描述,一般来说是作为参数来使用,由 Intent 来协助完成 android 各个组件之间的通讯。比如说调用 startActivity() 来启动一个 activity, 或者由 broadcaseIntent() 来传递给所有感兴趣的 BroadcaseReceiver, 再或者由 startService()/bindservice() 来启动一个后台的 service. 所以可以看出来, intent 主要是用来启动其他的 activity 或者 service ,所以可以将 intent 理解成 activity 之间的粘合剂。
二、 Intent的构成
要在不同的 activity 之间传递数据,就要在 intent 中包含相应的东西,一般来说数据中最基本的应该包括:
          Action 用来指明要实施的动作是什么,比如说 ACTION_VIEW, ACTION_EDIT 等。具体的可以查阅 android SDK-> reference 中的 Android.content.intent 类,里面的 constants 中定义了所有的 action
          Data 要事实的具体的数据,一般由一个 Uri 变量来表示
 
下面是一些简单的例子:
ACTION_VIEW   content://contacts/1   // 显示 identifier 1 的联系人的信息。
ACTION_DIAL content://contacts/1   // 给这个联系人打电话
 
除了 Action data 这两个最基本的元素外, intent 还包括一些其他的元素,
          Category (类别) : 这个选项指定了将要执行的这个 action 的其他一些额外的信息,例如 LAUNCHER_CATEGORY 表示 Intent 的接受者应该在 Launcher 中作为顶级应用出现;而 ALTERNATIVE_CATEGORY 表示当前的 Intent 是一系列的可选动作中的一个,这些动作可以在同一块数据上执行。具体同样可以参考 android SDK-> reference 中的 Android.content.intent 类。以前我也写过一篇于 category 有关的文章,点击这里可以查看。
          Type (数据类型): 显式指定 Intent 的数据类型( MIME )。一般 Intent 的数据类型能够根据数据本身进行判定,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导。
          component (组件): 指定 Intent 的的目标组件的 类名称。通常 Android 会根据 Intent 中包含的其它属性的信息,比如 action data/type category 进行查找,最终找到一个与之匹配的目标组件。但是,如果 component 这个属性有指定的话,将直接使用它指定的组件,而不再执行上述查找过程。指定了这个属性以后, Intent 的其它所有属性都是可选的。
          extras (附加信息),是其它所有附加信息的集合。使用 extras 可以为组件提供扩展信息,比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、正文等保存在 extras 里,传给电子邮件发送组件。
下面是这些额外属性的几个例子:
ACTION_MAIN with category CATEGORY_HOME // 用来 Launch home screen. 以前我也写过一篇于与之有关的文章, 点击这里可以看到。
ACTION_GET_CONTENT with MIME type vnd.android.cursor.item/phone // 用来列出列表中的所有人的电话号码
综上可以看出, action data/type category extras 一起形成了一种语言,这种语言可以是 android 可以表达出诸如“给张三打电话”之类的短语组合。
三、 intent的解析
应用程序 的组件为了告诉 Android 自己能响应、处理哪些隐式 Intent 请求,可以声明一个甚至多个 Intent Filter 。每个 Intent Filter 描述该组件所能响应 Intent 请求的能力 —— 组件希望接收什么类型的请求行为,什么类型的请求数据。比如之前请求网页浏览器这个例子中,网页浏览器程序的 Intent Filter 就应该声明它所希望接收的 Intent Action WEB_SEARCH_ACTION ,以及与之相关的请求数据是网页地址 URI 格式。如何为组件声明自己的 Intent Filter? 常见的方法是在 AndroidManifest.xml 文件中用属性 < Intent-Filter> 描述组件的 Intent Filter
  前面我们提到,隐式 Intent(Explicit Intents) Intent Filter(Implicit Intents) 进行比较时的三要素是 Intent 的动作、数据以及类别。实际上,一个隐式 Intent 请求要能够传递给目标组件,必要通过这三个方面的检查。如果任何一方面不匹配, Android 都不会将该隐式 Intent 传递给目标组件。接下来我们讲解这三方面检查的具体规则。
  1.动作测试
   Java 代码
 < intent-filter> 元素中可以包括子元素 < action> ,比如:
      < intent-filter> < action android:name=”com.example.project.SHOW_CURRENT” />
 < action android:name=”com.example.project.SHOW_RECENT” />
< action android:name=”com.example.project.SHOW_PENDING” />
 < /intent-filter> 
  一条 < intent-filter> 元素至少应该包含一个 < action> ,否则任何 Intent 请求都不能和该 < intent-filter> 匹配。如果 Intent 请求的 Action < intent-filter> 中个某一条 < action> 匹配,那么该 Intent 就通过了这条 < intent-filter> 的动作测试。如果 Intent 请求或 < intent-filter> 中没有说明具体的 Action 类型,那么会出现下面两种情况。 
(1) 如果 < intent-filter> 中没有包含任何 Action 类型,那么无论什么 Intent 请求都无法和这条 < intent- filter> 匹配 ;
(2) 反之,如果 Intent 请求中没有设定 Action 类型,那么只要 < intent-filter> 中包含有 Action 类型,这个 Intent 请求就将顺利地通过 < intent-filter> 的行为测试。 
    2.类别测试
   Java 代码
 < intent-filter> 元素可以包含 < category> 子元素,比如:
      < intent-filter . . . >
      < category android:name=”android.Intent.Category.DEFAULT” />
      < category android:name=”android.Intent.Category.BROWSABLE” />
< /intent-filter> 
  只有当 Intent 请求中所有的 Category 与组件中某一个 IntentFilter < category> 完全匹配时,才会让该 Intent 请求通过测试, IntentFilter 中多余的 < category> 声明并不会导致匹配失败。一个没有指定任何类别测试的 IntentFilter 仅仅只会匹配没有设置类别的 Intent 请求。 
    3.数据测试
  数据在 < intent-filter> 中的描述如下:  Java 代码 
< intent-filter . . . >
      < data android:type=”video/mpeg” android:scheme=”http” . . . />
      < data android:type=”audio/mpeg” android:scheme=”http” . . . />
< /intent-filter> 
   元素指定了希望接受的 Intent 请求的数据 URI 和数据类型, URI 被分成三部分来进行匹配: scheme authority path 。其中,用 setData() 设定的 Inteat 请求的 URI 数据类型和 scheme 必须与 IntentFilter 中所指定的一致。若 IntentFilter 中还指定了 authority path ,它们也需要相匹配才会通过测试。
 4.简单例子说明
  讲解完 Intent 基本概念之后,接下来我们就使用 Intent 激活 Android 自带的电话拨号程序,通过这个实例你会发现,使用 Intent 并不像其概念描述得那样难。最终创建 Intent 的代码如下所示。
   Intent i = new
Intent(Intent.ACTION_DIAL,Uri.parse(”tel://13800138000″));
  创建好 Intent 之后,你就可以通过它告诉 Android 希望启动新的 Activity 了。
   startActivity(i);
   Activity 启动后显示界面如下:
 
 
三、Intent的构造函数
公共构造函数:
1 Intent() 空构造函数
2 Intent(Intent o) 拷贝构造函数
3 Intent(String action) 指定 action 类型的构造函数
4 Intent(String action, Uri uri) 指定 Action 类型和 Uri 的构造函数, URI 主要是结合程序之间的数据共享 ContentProvider
5 Intent(Context packageContext, Class<?> cls) 传入组件的构造函数,也就是上文提到的
6 Intent(String action, Uri uri, Context packageContext, Class<?> cls) 前两种结合体
Intent 有六种构造函数, 3 4 5 是最常用的,并不是其他没用!
Intent(String action, Uri uri)  action 就是对应在 AndroidMainfest.xml 中的 action 节点的 name 属性值。在 Intent 类中定义了很多的 Action Category 常量。
示例代码二:
   1: Intent intent = new Intent(Intent.ACTION_EDIT, null);
   2: startActivity(intent);
示例代码二是用了第四种构造函数,只是 uri 参数为 null 。执行此代码的时候,系统就会在程序主配置文件 AndroidMainfest.xml 中寻找
<action android:name="android.intent.action.EDIT" /> 对应的 Activity ,如果对应为多个 activity 具有 <action android:name="android.intent.action.EDIT" /> 此时就会弹出一个 dailog 选择 Activity ,如下图:
  如果是用示例代码一那种方式进行发送则不会有这种情况。
三、利用 Intent Activity 之间传递数据
Main 中执行如下代码:
   1: Bundle bundle = new Bundle();
   2: bundle.putStringArray("NAMEARR", nameArr);
   3: Intent intent = new Intent(Main.this, CountList.class);
   4: intent.putExtras(bundle);
   5: startActivity(intent);
CountList 中,代码如下:
   1: Bundle bundle = this.getIntent().getExtras();
   2: String[] arrName = bundle.getStringArray("NAMEARR");
以上代码就实现了 Activity 之间的数据传递!
 
Android intent intent-filter

  
5. 总结说明
  这篇文章是我刚开始学习 Android 时看到的,当时理解的不是很深入,现在再回头看这篇文章总结的很详细,在这里与大家分享。
   1 ,掉 web 浏览器
   Java 代码
   Uri myBlogUri = Uri.parse("http://kuikui.javaeye.com");
   returnIt = new Intent(Intent.ACTION_VIEW, myBlogUri);
 
   2 ,地图
   Java 代码
   Uri mapUri = Uri.parse("geo:38.899533,-77.036476");
   returnIt = new Intent(Intent.ACTION_VIEW, mapUri);
 
   3 ,调拨打电话界面
   Java 代码
   Uri telUri = Uri.parse("tel:100861");
   returnIt = new Intent(Intent.ACTION_DIAL, telUri);
 
   4 ,直接拨打电话
   Java 代码
   Uri callUri = Uri.parse("tel:100861");
   returnIt = new Intent(Intent.ACTION_CALL, callUri);
 
   5 ,卸载
   Java 代码
   Uri uninstallUri = Uri.fromParts("package", "xxx", null);
   returnIt = new Intent(Intent.ACTION_DELETE, uninstallUri);
 
   6 ,安装
   Java 代码
   Uri installUri = Uri.fromParts("package", "xxx", null);
   returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);
 
   7 ,播放
   Java 代码
   Uri playUri = Uri.parse("file:///sdcard/download/everything.mp3");
   returnIt = new Intent(Intent.ACTION_VIEW, playUri);
 
   8 ,掉用发邮件
   Java 代码
   Uri emailUri = Uri.parse("mailto:shenrenkui@gmail.com");
   returnIt = new Intent(Intent.ACTION_SENDTO, emailUri);
 
   9 ,发邮件
   Java 代码
   returnIt = new Intent(Intent.ACTION_SEND);
   String[] tos = { "shenrenkui@gmail.com" };
   String[] ccs = { "shenrenkui@gmail.com" };
   returnIt.putExtra(Intent.EXTRA_EMAIL, tos);
   returnIt.putExtra(Intent.EXTRA_CC, ccs);
   returnIt.putExtra(Intent.EXTRA_TEXT, "body");
   returnIt.putExtra(Intent.EXTRA_SUBJECT, "subject");
   returnIt.setType("message/rfc882");
   Intent.createChooser(returnIt, "Choose Email Client");
  
   10 ,发短信
  Java 代码
   Uri smsUri = Uri.parse("tel:100861");
   returnIt = new Intent(Intent.ACTION_VIEW, smsUri);
   returnIt.putExtra("sms_body", "shenrenkui");
   returnIt.setType("vnd.android-dir/mms-sms");
 
   11 ,直接发邮件
   Java 代码
   Uri smsToUri = Uri.parse("smsto://100861");
   returnIt = new Intent(Intent.ACTION_SENDTO, smsToUri);
   returnIt.putExtra("sms_body", "shenrenkui");
 
   12 ,发彩信
   Java 代码
   Uri mmsUri = Uri.parse("content://media/external/images/media/23");
   returnIt = new Intent(Intent.ACTION_SEND);
   returnIt.putExtra("sms_body", "shenrenkui");
   returnIt.putExtra(Intent.EXTRA_STREAM, mmsUri);
   returnIt.setType("image/png");
 
  用获取到的 Intent 直接调用 startActivity(returnIt) ok 了。
 
下面,以 Android SDK 中的便笺例子来说明, Intent 如何定义及如何被解析。这个应用可以让用户浏览便笺列表、查看每一个便笺的详细信息。

Manifest.xml
Xml 代码   
1.         <manifest  xmlns:android = "http://schemas.android.com/apk/res/android"    
2.         package = "com.google.android.notepad" >    
3.              <application  android:icon = "@drawable/app_notes"    
4.         android:label = "@string/app_name" >    
5.              <provider  class = "NotePadProvider"    
6.         android:authorities = "com.google.provider.NotePad"  />    
7.              <activity  class = ".NotesList" ="@string/title_notes_list" >    
8.                <intent-filter>    
9.                  <action  android:value = "android.intent.action.MAIN" />    
10.               <category  android:value = "android.intent.category.LAUNCHER"  />    
11.             </intent-filter>    
12.             <intent-filter>    
13.               <action  android:value = "android.intent.action.VIEW" />    
14.               <action  android:value = "android.intent.action.EDIT" />    
15.               <action  android:value = "android.intent.action.PICK" />    
16.               <category  android:value = "android.intent.category.DEFAULT"  />    
17.               <type  android:value = "vnd.android.cursor.dir/vnd.google.note"  />    
18.             </intent-filter>    
19.             <intent-filter>    
20.               <action  android:value = "android.intent.action.GET_CONTENT"  />    
21.               <category  android:value = "android.intent.category.DEFAULT"  />    
22.               <type  android:value = "vnd.android.cursor.item/vnd.google.note"  />    
23.             </intent-filter>    
24.           </activity>    
25.           <activity  class = ".NoteEditor" ="@string/title_note" >    
26.             <intent-filter  android:label = "@string/resolve_edit" >    
27.               <action  android:value = "android.intent.action.VIEW" />    
28.               <action  android:value = "android.intent.action.EDIT" />    
29.               <category  android:value = "android.intent.category.DEFAULT"  />    
30.               <type  android:value = "vnd.android.cursor.item/vnd.google.note"  />    
31.             </intent-filter>    
32.             <intent-filter>    
33.               <action  android:value = "android.intent.action.INSERT" />    
34.               <category  android:value = "android.intent.category.DEFAULT"  />    
35.               <type  android:value = "vnd.android.cursor.dir/vnd.google.note"  />    
36.             </intent-filter>    
37.           </activity>    
38.           <activity  class = ".TitleEditor" ="@string/title_edit_title"   
39.      android:theme = "@android:style/Theme.Dialog" >    
40.             <intent-filter  android:label = "@string/resolve_title" >    
41.               <action  android:value = "com.google.android.notepad.action.EDIT_TITLE" />    
42.               <category  android:value = "android.intent.category.DEFAULT"  />    
43.               <category  android:value = "android.intent.category.ALTERNATIVE"  />    
44.               <category  android:value = "android.intent.category.SELECTED_ALTERNATIVE" />    
45.               <type  android:value = "vnd.android.cursor.item/vnd.google.note"  />    
46.             </intent-filter>    
47.           </activity>    
48.      </application>    
49.      </manifest>   
 

例子中的第一个 Activity com.google.android.notepad.NotesList ,它是应用的主入口,提供了三个功能,分别由三个 intent-filter 进行描述:
        1
、第一个是进入便笺应用的顶级入口( action android.app.action.MAIN )。类型为 android.app.category.LAUNCHER 表明这个 Activity 将在 Launcher 中列出。
        2
、第二个是,当 type vnd.android.cursor.dir/vnd.google.note (保存便笺记录的目录) 时,可以查看可用的便笺( action android.app.action.VIEW ),或者让用户选择一个便笺并返回给调用者( action android.app.action.PICK )。
        3
、第三个是,当 type vnd.android.cursor.item/vnd.google.note 时,返回给调用者一个用户选择的便笺( action android.app.action.GET_CONTENT ),而用户却不需要知道便笺从哪里读取的。 有了这些功能,下面的 Intent 就会被解析到 NotesList 这个 activity

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

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

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

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

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


        
第二个 Activity com.google.android.notepad.NoteEditor ,它为用户显示一条便笺,并且允许 用户修改这个便笺。它定义了两个 intent-filter ,所以具有两个功能。第一个功能是,当数据类型为 vnd.android.cursor.item/vnd.google.note 时,允许用户查看和修改一个便签( action android.app.action.VIEW android.app.action.EDIT )。第二个功能是,当数据类型为 vnd.android.cursor.dir/vnd.google.note ,为调用者显示一个新建便笺的界面,并将新建的便笺插 入到便笺列表中( action android.app.action.INSERT )。

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

    * { action=android.app.action.VIEW data=content://com.google.provider.NotePad/notes/{ID} }
:向用户显示标识为 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 }
:在 “content://com.google.provider.NotePad/notes” 这个便笺列表中创建一个新的空便笺,并允许用 户编辑这个便签。当用户保存这个便笺后,这个新便笺的 URI 将会返回给调用者。  


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

余额充值