Intent详解

Author Avatar
罗炜光 7月 29, 2016
  • 在其它设备中阅读本文章

Intent简介

  1. Intent为组件的启动提供了一致的编程模型. 无论想要启动的组件是Activity, Service, 还是BroadcastReceiver, 都可以使用Intent封装启动的意图.

  2. 如果应用程序只是想启动具有某种特征的组件,并不想和某个具体的组件耦合,则可以通过在intent-filter中配置相应的属性进行处理

Intent的七大属性

  • ComponentName
  • Action
  • Category
  • Data
  • Type
  • Extra
  • Flag

ComponentName

ComponentName(组件名称)用于标识唯一的应用程序组件,即指明了期望的Intent组件,这种对象的名称是由目标组件的类名与目标组件的包名组合而成的。在Intent传递过程中,组件名称是一个可选项,当指定它时,便是显式的Intent消息,我们称为“显示意图”,当不指定它时,Android系统则会根据其他信息及IntentFilter的过滤条件选择相应的组件,我们称之为 “隐式意图”。

ComponetName对象的三种构造方法。

  • ComponentName(String pkg, String cls)
  • ComponentName(Context pkg, String cls)
  • ComponentName(Context pkg, Class<?> cls)

构造方法其实实质是设置包名与类名,其中包名指的是后面类名所在的那个包,而不是当前应用的包名。
如果调用的其他应用的组件,而那个组件必须在清单文件中设置android:exported=true,表示允许其他应用打开,否则会报“ java.lang.SecurityException: Permission Denial: starting Intent…”

Intent intent = new Intent();
ComponentName componentName = new ComponentName("luoweiguang.github.io.intentdemo2","luoweiguang.github.io.intentdemo2.MainActivity");
intent.setComponent(componentName);
startActivity(intent);

对于包含了过滤器的组件,意味着该组件可以提供给外部的其他应用来使用,它的exported属性默认为true,相反,如果一个组件不包含任何过滤器,那么意味着该组件只能通过指定明确的类名来调用,也就是说该组件只能在应用程序的内部使用,在这种情况下,exported属性的默认值是false。

Action

Intent通过定义Action属性(其实就是一段自定义的字符串),这样就可以把Intent与具体的某个Activity分离,实现了解耦。否则,每次跳转,都要写成类似new
Intent(MainActivity.this,NextActivity.class)这样的形式,也就是说必须将要跳转的目标Activity的名字写出来,这样的编码其实是“硬编码”,并没有实现松耦合。调用Intent对象的setAction()方法实现页面跳转虽然略微复杂(需要在AndroidManifest.xml文件中配置),但是实现了解耦。

Action 是一个用户定义的字符串,用于描述一个 Android 应用程序组件,一个 Intent Filter 可以包含多个 Action。

一条intent-filter元素至少应该包含一个action,否则任何Intent请求都不能和该intent-filter匹配

action区分大小写

Category

Intent中如果定义了category,那么不管有几个category,它都必须是Intent-filter中已定义的。

隐式调用一个组件时,必须设置一个 android:name=”android.intent.category.DEFAULT”否则会报“android.content.ActivityNotFoundException: No Activity found to handle Intent”错误

Intent隐形调用不能只设置Category,必须设置Action

Data与Type

<data
    android:mimeType="String"
    android:scheme="String"
    android:ssp="String"
    android:host="String"
    android:port="int"
    android:path="String"
    android:pathPattern="String"
    android:pathPrefix="String"
    android:sspPattern="String"
    android:sspPrefix="String"/>

data标签由minmeType和URI两部分组成

Type属性用于指定该Data所指定Uri对应的MIME类型,这种类型可以是任何自定义的MIME类型,只要符合abc/xyz格式的字符串即可

如果要为Intent指定完整的data,必须要调用setDataAndType方法,不能用setData再调用setType,因为这两个方法彼此会清除对方的值

当清单文件中设置了data时,intent必须要定义可匹配的data才行,清单文件中可定义多条data,当只要匹配其中一条即可

Extra

以Key-value对的形式发送给处理这个Intent对象的组件的附加信息。
能够添加类型包括基本数据类型(含基本数据类型的数组)、String(包含数组)、Parcelable(包含数组)、Serializable、Bundle、CharSequence、Intent

Intent  putExtra(String name, String[] value)
Intent  putExtra(String name, Parcelable value)
Intent  putExtra(String name, long value)
Intent  putExtra(String name, boolean value)
Intent  putExtra(String name, double value)
Intent  putExtra(String name, Parcelable[] value)
Intent  putExtra(String name, char value)
Intent  putExtra(String name, int[] value)
Intent  putExtra(String name, int value)
Intent  putExtra(String name, double[] value)               
Intent  putExtra(String name, short value)                  
Intent  putExtra(String name, long[] value)                     
Intent  putExtra(String name, boolean[] value)                  
Intent  putExtra(String name, short[] value)                    
Intent  putExtra(String name, String value)                     
Intent  putExtra(String name, Serializable value)               
Intent  putExtra(String name, float[] value)                    
Intent  putExtra(String name, Bundle value)                     
Intent  putExtra(String name, byte[] value)                     
Intent  putExtra(String name, CharSequence value)                  
Intent  putExtra(String name, char[] value)                     
Intent  putExtra(String name, byte value)                   
Intent  putExtras(Intent src)                   
Intent  putExtras(Bundle extras)

Flag

flag属性是一个int值, 用于通知android系统如何启动目标activity, 或者启动目标activity之后应该采取怎样的后续操作. 所有的flag都在Intent类中定义,具体见Intent中关于Activity的Flag

注意事项

当我们使用隐式调用时,应该判断以下是否有能匹配的,可以使用以下方法

  1. PackageManager的resolveActivity
  2. Intent的resolveActivity
  3. PackageManager的queryIntentActivities

参考资料

关于ComponentName的使用
Android开发教程:理解Intent和Intent Filter
Android开发艺术探索