Intent对于Android应用的作用
Intent,翻译过来是“意图”,它是对Android应用程序“意图”的封装。例如ActivityA想启动ActivityB,那么“想启动ActivityB”就是ActivityA的意图;ActivityA想启动ServiceA,“想启动ServiceA”就是ActivityA的意图。
至于Android为什么不直接提供一个类似startActivity(Class activityClass)的方法来移动一个Activity,是因为这样做会背离Android的设计理念,造成一种硬编码耦合,不利于高层次的解耦。而Intent提供的编程模型,可以让应用程序只启动具有某种特征额组件,不会造成组件(Activity、Service、ContentProvider)之间的耦合。
Intent不仅可以封装应用程序需要启动某个组件的“意图”,还可以作为应用组件之间通信的重要媒介。例如两个Activity之间可以通过Bundle对象交换数据,而Intent刚好可以携带Bundle对象。
Intent对象如何启动系统组件
Android应用程序包含三种重要组件:Activity、Service、BroadcastReceiver,应用程序采用了一致的方式来启动他们——都是依靠Intent来进行启动的,Intent就封装了程序想要启动程序的意图,不仅如此,Intent还可用于与被启动组件交换信息。
下表显示一部分使用Intent启动不同组件的方法:
组件类型 | 启动方法 |
Activity | startActivity(Intent i) |
| startActivityForResult(Intent intent, int requestCode) |
Service | ComponentName startService(Intent service) |
| boolean bindService(Intent service, ServiceConnection conn, int flags) |
BroadcastReceiver | sendBroadcast(Intent intent) |
| sendBroadcast(Intent intent, String receiverPermission) |
| sendOrderedBroadcast(Intent intent, String receiverPermission) |
Intent对象大致包含Component, Action, Category, Data, Type, Extra和Flag这7中属性,其中Component用于明确指定需要启动的目标组件,而Extra用于“携带”需要交换的数据。下面详细介绍Intent对象各属性的作用。
Intent的属性及Intent-Filter配置
我们知道Intent是用来封装程序的启动意图的,但到底启动哪个组件,则取决于Intent的各个属性。
首先举个例子,有一个女孩儿要找男朋友,此时有两种方式来表达她的意图:
-
明确指出要找xxx做她的男朋友,比如找博主我^_^;
-
指出要找“高”、“富”、“帅”做男朋友,至于到底是谁不重要,只要是高富帅就行;
同样,Intent封装的意图与之类似:
-
显式Intent:通过Component属性明确指定要启动哪个组件;
-
隐式Intent:通过Action、Category属性指出需要启动符合条件的组件;
Component属性
该属性用来明确指定需要启动哪个组件,其构造函数如下:
-
ComponentName(Stringpkg, String cls):创建pkg所在包下的cls类所对应的组件;
-
ComponentName(Contextpkg, String cls):创建pkg所对应的包下的cls类所对应的组件;
-
ComponentName(Contextpkg, Class<?> cls):创建pkg所对应的包下的cls类所对应的组件;
下面是例子:
ComponentNamecomponentName =newComponentName(getApplicationContext(),ActivityB.class);
Intent intent =newIntent();
intent.setComponent(intent);
startActivity(intent);
除此之外,Intent也提供了快捷的方法和构造函数:
-
setClass(Contextpkg, Class<?> cls)
-
setClassName(Contextpkg, Class<?> cls)
-
setClassName(Stringpkg, String cls)
-
Intent(Contextcontext, Class<?> cls)
下面是例子:
Intent intent1 = new Intent(getApplicationContext(), ActivityB.class); startActivity(intent1); Intent intent2 = new Intent(); intent2.setClass(getApplicationContext(), ActivityB.class); startActivity(intent2);
Action、Category属性与Intent-Filter配置
Action、Category属性值都为字符串,其中Action表示Intent将要完成的一个抽象“动作”,Category用于为Action指定更加详细的类别信息或执行的环境,所以这两个属性一般会结合使用。
先通过一个例子来了解一下:
public class ActivityA extends Activity { public static final String ACTION_TEST = "com.gisirfive.ACTION_TEST"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Button button = new Button(this); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); intent.setAction(ACTION_TEST); startActivity(intent); } }); setContentView(button); } }
<application
……
<activity android:name=".ActivityB"> <intent-filter> <!--指定该Activity能响应Action为指定字符串的Intent--> <action android:name="com.gisirfive.ACTION_TEST"/> </intent-filter> </activity> </application>
该例子是在ActivityA中点击按钮,通过Action指定将要启动的组件。从代码我们可以知道,startActivity()将会启动ActivityB,但是ActivityA并不知道它会启动ActivityB,它只知道它“想要启动Action包含ACTION_TEST的组件”,这就是它的“意图”。
使用隐式Intent的好处是避免了硬编码的方式建立组件之间的交互。
上面程序中出现了Intent-Filter,我们知道它是放在组件(Android三个常用组件)里面使用的,通常可以包含如下子元素:
-
0个或多个<action../>元素
-
0个或多个<category…/>元素
-
0个或1个<data …/>元素
这里需要指出的是,虽然<intent-filter>可以包含多个Action元素,但是一个Intent对象最多只能包含一个Action属性,相当于“意图”只能包含一个抽象动作。相反,Intent可以包含多个Category(Intent默认包含一个Intent.CAETGORY_DEFAULT常量,其值为android.intent.category.DEFAULT),这相当于“意图”对这个抽象动作指定特定的执行环境。
指定Action、Category调用系统Activity
Intent不仅可以启动本应用内的程序组件,也可以启动Android系统的其他应用的程序组件,包括系统自带的程序组件——只要权限允许。
Android内部提供了大量标准Action、Category常量,其中用于启动Activity的标准Action常量及对应的字符串如下:
Action常量 | 对应字符串 | 简单说明 |
ACTION_MAIN | android.intent.action.MAIN | 应用程序入口 |
ACTION_VIEW | android.intent.action.VIEW | 显示指定数据 |
ACTION_ATTACH_DATA | android.intent.action.ATTACH_DATA | 指定某块数据将被附加到其他地方 |
ACTION_EDIT | android.intent.action.EDIT | 编辑指定数据 |
ACTION_PICK | android.intent.action.PICK | 从列表中选择某项并返回所选的数据 |
ACTION_CHOOSER | android.intent.action.CHOOSER | 显示一个Activity选择器 |
ACTION_GET_CONTENT | android.intent.action.GET_CONTENT | 让用户选择数据,并返回所选数据 |
ACTION_DIAL | android.intent.action.DIAL | 显示拨号面板 |
ACTION_CALL | android.intent.action.CALL | 直接向指定用户打电话 |
ACTION_SEND | android.intent.action.SEND | 向其他人发送数据 |
ACTION_SENDTO | android.intent.action.SENDTO | 向其他人发送消息 |
ACTION_ANSWER | android.intent.action.ANSWER | 应答电话 |
ACTION_INSERT | android.intent.action.INSERT | 插入数据 |
ACTION_DELETE | android.intent.action.DELETE | 删除数据 |
ACTION_RUN | android.intent.action.RUN | 运行数据 |
ACTION_SYNC | android.intent.action.SYNC | 执行数据同步 |
ACTION_PICK_ACTIVITY | android.intent.action.PICK_ACTIVITY | 用于选择Activity |
ACTION_SEARCH | android.intent.action.SEARCH | 执行搜索 |
ACTION_WEB_SEARCH | android.intent.action.WEB_SEARCH | 执行Web搜索 |
ACTION_FACTORY_TEST | android.intent.action.FACTORY_TEST | 工厂测试的入口点 |
标准Category常量及对应的字符串如下:
Category常量 | 对应字符串 | 简单说明 |
CATEGORY_DEFAULT | android.intent.category.DEFAULT | 默认的Category |
CATEGORY_BROWSABLE | android.intent.category.BROWSABLE | 指定该Activity能被浏览器安全调用 |
CATEGORY_TAB | android.intent.category.TAB | 指定该Activity作为TabActivity的Tab页 |
CATEGORY_LAUNCHER | android.intent.category.LAUNCHER | Activity显示顶级程序列表中 |
CATEGORY_INFO | android.intent.category.INFO | 用于提供包信息 |
CATEGORY_HOME | android.intent.category.HOME | 设置该Activity随系统启动而运行 |
CATEGORY_PREFERENCE | android.intent.category.PREFERENCE | 该Activity是参数面板 |
CATEGORY_TEST | android.intent.category.TEST | 该Activity是一个测试 |
CATEGORY_CAR_DOCK | android.intent.category.CAR_DOCK | 指定手机被插入汽车底座(硬件)时运行该Activity |
CATEGORY_DESK_DOCK | android.intent.category.DESK_DOCK | 指定手机被插入桌面底座(硬件)时运行该Activity |
CATEGORY_CAR_MODE | android.intent.category.CAR_MODE | 设置该Activity可在车载环境下使用 |
下面是一个返回桌面的例子:
private void fackBackHome(){ Intent intent = new Intent(); intent.setAction(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); startActivity(intent); }