PA05

来自tomtalk
跳转至: 导航搜索

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的其他部分。

5.4 练习使用ACTION_PICK

5.5 练习使用GET_CONTENT操作

5.6 挂起的Intent