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

来源:互联网 发布:淘宝千人千面在哪里买 编辑:程序博客网 时间:2024/05/17 18:13

作者:郭孝星
微博:郭孝星的新浪微博
邮箱:allenwells@163.com
博客: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<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);boolean isIntentSafe = activities.size() > 0;

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

这里写图片描述

举例

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

// Build the intentUri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);// Verify it resolvesPackageManager packageManager = getPackageManager();List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);boolean isIntentSafe = activities.size() > 0;// Start an activity if it's safeif (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数据部分。

举例

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

@Overrideprotected 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">    <!-- filter for sending text; accepts SENDTO action with sms URI schemes -->    <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>    <!-- filter for sending text or images; accepts SEND action and text or image data -->    <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做出响应。

0 0