PA05
Android引入了一个名为Intent的概念来调用组件。
目录
5.1 Android Intent基础知识
将Intent作为一种调用组件的机件很容易理解,Android将多种理念融入到了Intent中。可以使用Intent从一个应用程序中调用外部应用程序。可以使用Intent从应用程序调用内部或外部组件。可以使用Intent触发事件,这样其他用户就可以通过与发布-订阅模型类似的方式进行响应。可以使用Intent发出警报。
什么是Intent?最简单的答案可能是,Intent是具有相关的数据负载的操作。
从最简单层面上讲,Intent是你可以告诉Android要执行(或调用)的一种操作。
public class BasicViewActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.some_view); } }//eof-class
some_view布局需要指向/res/layout目录中的有效布局文件。Android支持在描述文件中注册此活动,使其可供其他应用程序调用。注册代码类似于:
<activity android:name=".BasicViewActivity" android:label="Basic View Tests"> <intent-filter> <action android:name="com.androidbook.intent.action.ShowBasicView"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
这里的注册不仅涉及一个活动,还涉及可用于调用该活动的操作。指定了活动和它所注册的操作之后,可以使用Intent来调用此BasicViewActivity:
public static void invokeMyApplication(Activity parentActivity) { String actionName= "com.androidbook.intent.action.ShowBasicView"; Intent intent = new Intent(actionName); parentActivity.startActivity(intent); }
操作名称的一般约定为 <包名称>.intent.action.操作名称。
5.2 Android中可用的Intent
通过调用Android自带的一些应用程序,可以为Intent运行测试。网页 http://developer.android.com/guide/components/intents-filters.html 上记录了可用的Google应用程序和调用它们的Intent。
5.3 Intent的组成
确定Intent用途的方式是查看Intent对象包含的内容。Intent包含操作、数据(使用数据URI表示)、extra数据元素的键/值映射,以及一个显式类名(称为组件名称)。
当Intent带有组件名称时,它称为显式Intent。当Intent没有组件名称,但依赖于其他部分(比如操作和数据)时,它称为隐式Intent。二者之间存在细微的区别。
到目前为止,我们介绍了最简单的Intent,在这些Intent中,我们所需的只是操作的名称,ACTION_DIAL就是一个例子。与ACTION_DIAL不同,用于呼叫给定电话号码的Intent ACTION_CALL还接受一个名为Data的参数。此参数指向一个URI,该URI又指向所拨的电话号码:
public static void call(Activity activity) { Intent intent = new Intent(Intent.ACTION_CALL); intent.setData(Uri.parse("tel:555-555-5555")); activity.startActivity(intent); }
操作Intent.ACTION_CALL和Intent.ACTION_DIAL很容易让我们得出这样的错误假设:操作和它所调用的程序之间存在一对一的关系。为了推翻这一观点,下面举一反例:
public static void invokeWebBrowser(Activity activity) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("http://www.google.com")); activity.startActivity(intent); }
请注意,该操作只是简单地声明为ACTION_VIEW。Android如何知道要调用哪个活动来响应这样一个一般操作名称?在这些情况下,Android不仅依赖于一般操作名称,而且依赖于URI的性质。Android查看URI的方案(恰好是http),然后询问所有已注册的活动,看看哪个活动能理解此方案。在这些活动中,它询问哪个活动能处理VIEW,然后调用该活动。为此,浏览器活动应该为数据方案http注册了VIEW Intent。描述文件中的Intent声明可能类似于:
<activity…...> <intent-filter> <action android:name="android.intent.action.VIEW" /> <data android:scheme="http"/> <data android:scheme="https"/> </intent-filter> </activity>
除了主要的操作和数据特性,Intent还可以包括名为extra的附加特性。extra可以向收到Intent的组件提供更多信息。extra数据以键/值对的形式表示:键名称应该以包名称开头,值可以是任何基本的数据类型或任意对象。
//Get the Bundle from an Intent Bundle extraBundle = intent.getExtras(); // Place a bundle in an intent Bundle anotherBundle = new Bundle(); //populate the bundle with key/value pairs ... //set the bundle on the Intent intent.putExtras(anotherBundle);
可以使用许多方法来向包添加基本类型。下面给出了一些向extra数据添加简单数据类型的方法:
putExtra(String name, boolean value); putExtra(String name, int value); putExtra(String name, double value); putExtra(String name, String value);
以下是一些稍微复杂的extra数据:
//simple array support putExtra(String name, int[] values); putExtra(String name, float[] values); //Serializable objects putExtra(String name, Serializable value); //Parcelable support putExtra(String name, Parcelable value); //Add another bundle at a given key //Bundles in bundles putExtra(String name, Bundle value); //Add bundles from another intent //copy of bundles putExtra(String name, Intent anotherIntent); //Explicit Array List support putIntegerArrayListExtra(String name, ArrayList arrayList); putParcelableArrayListExtra(String name, ArrayList arrayList); putStringArrayListExtra(String name, ArrayList arrayList);
前面已经介绍了使用Intent启动活动的两种方式,介绍了使用显式操作启动活动,以及使用一般操作并借助数据URI来启动活动。Android还提供了一种更直接的方式来启动活动:指定活动的ComponentName,这是围绕对象的包名和类名的抽象。
不需要Intent过滤器,直接通过类名或组件名调用活动。前面已经解释,这种类型的Intent称为显式Intent。因为显式Intent指定一个调用的完全限定的Android组件,所以在调用该组件时会忽略该Intent的其他部分。