【Android应用开发技术:应用组件】Intent使用方法

作者:郭孝星
微博:郭孝星的新浪微博
邮箱:[email protected]
博客:http://blog.csdn.net/allenwells
Github:https://github.com/AllenWells

【Android应用开发技术:应用组件】章节列表

一 Intent验证

尽管Android系统会确保每一个确定的intent会被系统内置的app(such as the Phone, Email, or Calendar app)之一接收,但是我们还是应该在触发一个intent之前做验证是否有App接受这个intent的步骤,因为如果我们触发了一个intent,而且没有任何一个App会去接收这个intent,那么我们的App会崩溃。

为了验证是否有合适的Activity会响应这个Intent,需要执行queryIntentActivities()来获取到能够接收这个Intent的所有Activity的list。如果返回的List非空,那么我们就可以安全的使用这个Intent,如下所示:

PackageManager packageManager = getPackageManager();
List activities = packageManager.queryIntentActivities(intent, 0);
boolean isIntentSafe = activities.size() > 0;

当我们创建好了Intent并且设置好了extra数据,通过执行startActivity(intent)来发送到系统。如果系统确定有多个Activity可以handle这个Intent,它会显示出一个Dialog,让用户选择启动哪个App。如果系统发现只有一个App可以handle这个Intent,那么就会直接启动这个App,如下所示:

【Android应用开发技术:应用组件】Intent使用方法_第1张图片

举例

创建一个Intent来查看地图,验证有App可以handle这个Intent,然后启动它。

// Build the intent
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
// Verify it resolves
PackageManager packageManager = getPackageManager();
List activities = packageManager.queryIntentActivities(mapIntent, 0);
boolean isIntentSafe = activities.size() > 0;
// Start an activity if it's safe
if (isIntentSafe) {
    startActivity(mapIntent);
}

二 Intent发送

(1) 启动Activity

启动另外一个Activity并不一定是单向的。我们也可以启动另外一个Activity然后接受一个result回来。为了接收这个result,我们需要使用startActivityForResult(),而不startActivity(),如下所示:

举例

启动Activity来选择联系人

static final int PICK_CONTACT_REQUEST = 1;  // The request code
...
private void pickContact() {
    Intent pickContactIntent = new Intent(Intent.ACTION_PICK, new Uri("content://contacts"));
    pickContactIntent.setType(Phone.CONTENT_TYPE); // Show user only contacts w/ phone numbers
    startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);
}

(2) 接收Result

当用户完成了启动之后Activity操作之后,系统会调用你的Activity的onActivityResult()回调方法。这个方法有三个参数,如下所示:

  • 第一个通过startActivityForResult()传递的request code。
  • 第二个activity指定的result code。如果操作成功则是 RESULT_OK ,如果用户没有操作成功,而是直接点击回退或者其他什么原因,那么则是RESULT_CANCELED。
  • 第三个参数则是intent,它包含了返回的result数据部分。

举例

处理选择联系人返回结果。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // Check which request it is that we're responding to
    if (requestCode == PICK_CONTACT_REQUEST) {
        // Make sure the request was successful
        if (resultCode == RESULT_OK) {
            // Get the URI that points to the selected contact
            Uri contactUri = data.getData();
            // We only need the NUMBER column, because there will be only one row in the result
            String[] projection = {Phone.NUMBER};
            // Perform the query on the contact to get the NUMBER column
            // We don't need a selection or sort order (there's only one result for the given URI)
            // CAUTION: The query() method should be called from a separate thread to avoid blocking
            // your app's UI thread. (For simplicity of the sample, this code doesn't do that.)
            // Consider using CursorLoader to perform the query.
            Cursor cursor = getContentResolver()
                    .query(contactUri, projection, null, null, null);
            cursor.moveToFirst();
            // Retrieve the phone number from the NUMBER column
            int column = cursor.getColumnIndex(Phone.NUMBER);
            String number = cursor.getString(column);
            // Do something with the phone number...
        }
    }
}

三 Intent过滤

为了尽可能确切的定义Activity能够handle哪些Intent,每一个intent filter都应该尽可能详尽的定义好action与data。如果Activity中的Intent Filter满足以下Intent对象的标准,系统就能够把特定的Intent发送给Activity,如下所示:

  • Action:一个想要执行的动作的名称。通常是系统已经定义好的值,例如 ACTION_SEND 或者 ACTION_VIEW 。 在intent filt
    中用 指定它的值,值的类型必须为字符串,而不是API中的常量。
  • Data:Intent附带数据的描述。在intent filter中用 指定它的值,可以使用一个或者多个属性,可以只定义MIME type或者是只指定Uri prefix,也可以只定义一个Uri Scheme,或者是它们综合使用。
  • Note:如果不想handle Uri类型的数据,那么我们应该指定android:mimeType属性。例如text/plain或者image/jpeg。
  • Category:提供一个附加的方法来标识这个Activity能够handle的Intent。通常与用户的手势或者是启动位置有关。系统有支持几种不同的Categories,但是大多数都不怎么用的到。而且,所有的implicit intents都默认是CATEGORY_DEFAULT类型的。在Intent Filter中用指定它的值。

在intent filter中,我们可以在元素中定义对应的XML元素来声明Activity使用何种标准。

举例

当数据类型为文本或图像时会处理ACTION_SEND的Intent。

<activity android:name="ShareActivity">
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
        <data android:mimeType="image/*"/>
    intent-filter>
activity>

每一个发送出来的Intent只会包含一个Action与Data类型,但是handle这个Intent的Activity的是可以声明多个 、与的。如果任何的两对Action与Data是互相矛盾的,我们应该创建不同的Intent Filter来指定特定的Action与Type。

举例

Activity可以handle文本与图片,无论是ACTION_SEND还是ACTION_SENDTO的Intent。在这种情况下,我们需要为两个Action定义两个不同的Intent Filter。因为ACTION_SENDTO的Intent必须使用Uri类型来指定接收者使用send或sendTo的地址,如下所示:

<activity android:name="ShareActivity">
    
    <intent-filter>
        <action android:name="android.intent.action.SENDTO"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:scheme="sms" />
        <data android:scheme="smsto" />
    intent-filter>
    
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="text/plain"/>
    intent-filter>
activity>

注意:为了接收Intent, 我们需要在Intent Filter中包含CATEGORY_DEFAULT的category。startActivity()和startActivityForResult()方法将所有intent视为声明了CATEGORY_DEFAULT category。如果没有在Intent Filter中声明CATEGORY_DEFAULT,那么Activity将无法对隐式Intent做出响应。

你可能感兴趣的:(安卓技术,-,应用开发)