利用Intent来开展App间的主导交互,系统深远学习

日期:2019-09-07编辑作者:编程应用

Intent是Android中存放一个操作的抽象描述的数据结构,可用于在不同的组件以及不同的app间进行传递,是消息的载体,有显式和隐式之分(若两者都有则执行显式的),下图是隐式Intent的传递过程.

 

图片 1intent-filters.png

第7章 与其他应用程序交互

一个Android应用程序通常有几个activities。每个act显示一个用户接口允许用户执行一个指定的任务。用户从一个act到另一个 act,你的App必须使用一个Intent对象来定义你App想做些什么事。当你通过一个Intent调用startActivity()方法时,系统 会使用Intent来鉴定和启动合适的App组件。一个Intent可以明确的启动一个特定的组件(如一个特定的act实例)或隐式启动任何可以处理预定 动作的组件,本章我们将讲述怎么使用Intent来执行与其他Apps的一些交互,例如启动另一个App,从那个App接收结果。并使你的应用程序能够响 应来自其他App的intents。以下是内容预览:

  1. 发送一个用户名到另一个App

演示怎样创建隐含的可以执行一个动作的Intent来启动其他应用程序。

  1. 从一个Activity获得一个结果

演示怎样启动另一个activity并从这个actvity接收结果。

  1. 允许其他Apps启动你的Activity

演示怎样使你的activities被其他apps打开。

1.1 新建一个隐式的Intent对象

隐式Intent不需要声明目标组件的class name,但是要声明要执行的action,这个action就是你想要执行的操作,比如view,edit,send等等. 如果需要给这些action绑定数据,比如要传地址信息,邮件内容等,就需要用到Uri类型的数据,绑定到intent的对象中,如下示例:

// 拨打电话Uri number = Uri.parse("tel:5551234");Intent callIntent = new Intent(Intent.ACTION_DIAL, number);// 查看地图// Map point based on addressUri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");// Or map point based on latitude/longitude// Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z param is zoom levelIntent mapIntent = new Intent(Intent.ACTION_VIEW, location);// 访问网页Uri webpage = Uri.parse("http://www.android.com");Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);

当然Intent还有通过putExtra相关方法来传入数据,不过这个要接受和发送的双方都约定好才能使用,而Android系统默认的方式则是通过Uri并设置合适的MIME类型,这样系统才能找到合理的处理这个Intent的activities,如下示例:

// 发送一封带附件的emailIntent emailIntent = new Intent(Intent.ACTION_SEND);// The intent does not have a URI, so declare the "text/plain" MIME typeemailIntent.setType(HTTP.PLAIN_TEXT_TYPE);emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipientsemailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));// You can also attach multiple items by passing an ArrayList of Uris// 建立一个日历event,注意这个API 14及以上才支持Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);Calendar beginTime = Calendar.getInstance().set(2012, 0, 19, 7, 30);Calendar endTime = Calendar.getInstance().set(2012, 0, 19, 10, 30);calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis;calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis;calendarIntent.putExtra(Events.TITLE, "Ninja class");calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");
  • 注意: 准确的设置Intent的参数的意义在于系统能够准确的找到执行的组件,比如你想要查看图片,于是你使用了ACTION_VIEW的Intent,如果你再调用setType()设置类型为"image/*",那么其他的带ACTION_VIEW的Activity比如地图类的就不会被启动.

7.1 发送用户到另一个App

Android最重要的一个特性之一就是发送用户到另一个App并基于“动作”来执行它的能力。例如,如果你的app有商业地址想要显示在地图上, 你不得不在你的App中新建一个activity来显示地图。其实更好的办法是使用Intent发送一个查看地图的外部请求。Android系统会启动那 个能查看地址的App。通常,我们使用一个明确的Intent,它定义的明确的类名。然而,当你想有一个单独的应用程序执行时,如“查看地图”,你必须使 用一个隐式的Intent。本节讲述如何为一个特定的动作创建隐含的意图,以及怎样用它来启动执行另一个应用程序中的Activity。

7.1.1构建一个隐式的Intent

隐式intents不用申明启动组件的类名,但需要申明执行的动作。动作指定你想要做的事情,如view(查 看),edit(编辑),send(发送)或获得某事物。Intents经常包托一些与动作相关联的税局,如你想要查看的地址,或者你想要发送的 email信息。这取决于你想要创建的Intent所发送的数据,数据可能是一个Uri或intent根本不需要数据也能发送,如果你的数据是一个 Rri,下面有一个例子,使用Rri数据发起一个电话。如代码清单7-1所示:

Uri number = Uri.parse("tel:5551234");

Intent callIntent = new Intent(Intent.ACTION_DIAL, number);

 

代码清单7-1

当你的app通过startActivity()调用intent时,电话app根据给定的电话号码发起呼叫。

查看一个地图(代码清单7-2):

//基于地址的地图点
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
// 或基于经纬度的地图点
// Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z参数表示缩放级别
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);

 

代码清单7-2

 

查看一个web页面(代码清单7-3):

Uri webpage = Uri.parse("http://www.android.com");
Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);

 

代码清单7-3

其他种类的隐式intents需要”extra”数据来提供不同的数据类型,如一个字符串。你能使用putExtra()方法 来添加一个或更多extra 数据。默认的,系统通过基于Uri的intent来确定适当的MIME(Multipurpose Internet Mail Extensions)类型。如果你在intent中不包含一个Uri,你应该使用setType()来指定intent相关联的数据类型。设置MIME 类型来进一步指定activities将要接收的intent类型。下面是更多的一些使用extra数据的intents

发送带有附件的电子邮件(代码清单7-4):

图片 2

Intent emailIntent = new Intent(Intent.ACTION_SEND);
//没有Uri的intent,所以需要声明”text/plain”的MIME类型
emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // 收件人
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject");
emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text");
emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));
//你也可以通过一个Uri的ArrayList来附件多个items

图片 3

 

代码清单7-4

创建一个日历事件(代码清单7-5):

图片 4

Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI);

Calendar beginTime = Calendar.getInstance().set(2012, 0, 19, 7, 30);

Calendar endTime = Calendar.getInstance().set(2012, 0, 19, 10, 30);

calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis());

calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis());

calendarIntent.putExtra(Events.TITLE, "Ninja class");

calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");

图片 5

 

代码清单7-5

注意: 对于日历事件的intent只在API Level或更高版本下才支持

7.1.2 验证一个App接收的Intent

我们总是应该在调用一个intent之前先包含一个验证。这是一个好的习惯,因为如果你在你的App中调用intent后,如 果没有可用的设备,那么你的app会崩溃.为了验证那个activity可用,我们可以调用queryIntentActivities()来获得一个 list,如果返回的List不为空,那么你能安扎un个的使用intent.具体使用代码如代码清单7-6所示:

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

 

代码清单7-6

如isIntentSafe为true,那么表示至少有一个app能响应我们的intent。如果false,表示没有一个app能处理这个intent。

7.1.3 使用Intent启动一个Activity

你可以创建intent并设置extra的信息,然后调用startActivity()。如果系统识别有多个 activity能处理这个intent,那么它会显示一个对话框让你自主选择(如图7-1所示)。如果只有一个activity的话,系统会立即启动这 个activity。

图片 6 

图7-1 多个activity能处理intent时,显示对话框让用户选择

下面让我们看一下代码清单7-7,看它是怎么启动activity的:

图片 7

// 构建intent
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);

// 验证上面的mapIntent
PackageManager packageManager = getPackageManager();
List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
boolean isIntentSafe = activities.size() > 0;

// 如果它是安全的就启动这个activity
if (isIntentSafe) {
    startActivity(mapIntent);
}

图片 8

 

代码清单7-7

7.1.4 显示APP选择器

注意当你通过intent使用startActivity()启动activity时,如果有多个app响应,如果多个应用可 以处理我们的操作,并且用户可能想要每次启动不同的app,比如一个”分享”的动作,分享的渠道可能有多个app组成,这样用户每次可能使用不同的 app。那么我们可以使用createChooser()来创建显示选择器,如代码清单7-7所示,效果如图7-2所示:

图片 9

Intent intent = new Intent(Intent.ACTION_SEND);
...

// 用于标题的文本资源例如"Share this photo with"
String title = getResources().getText(R.string.chooser_title);
//创建并启动chooser
Intent chooser = Intent.createChooser(intent, title);
startActivity(chooser);

图片 10

 

代码清单7-8

 

图片 11 

图7-2 创建选择器后的效果

1.2. 验证是否有app能够接收你的Intent

虽然Android系统保证某些类型的Intent都至少有一个内置的app能够接收,但是由于Android系统的分散和自由,可能有的软件被删除等等原因,你想用Intent启动其他app的时候,一定要验证一下是否有app接收,如果你直接启动而没有app接收则app会crash(ActivityNotFoundException);

a. 可以使用PackageManager的queryIntentActivities()来验证,该方法需要一个Intent的参数,返回所有能够接收该intent的activity的信息,包在一个List里面,可以直接判断List的size是否大于0即可:

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

b. 也可以通过这个Intent的resolveActivity()方法来判断

// Verify the intent will resolve to at least one activityif (intent.resolveActivity(getPackageManager != null) { startActivity;}

7.2 从Activity获得结果

启动另一个activity并不一定是单向的。我们还可以启动另一个activity,并接收返回结果.。如果需要接收返回结 果,我们可以使用startActivityForResult()。L例如。你的应用启动一个摄像机app并接收拍摄照片的结果。当然,获得响应的 activity必须被设计为返回一个结果,当它这么做时,它发送一个intent对象的结果。你的activity在 onActivityResult()回调方法中会接收到这个intent。虽然我们可以使用明确的和隐式的intent,但这里实际建议你应该使用一个 明确的intent,以确保收到了预期的结果。

7.2.1 启动Activity

使用startActivityForResult()方法,需要传递一个额外的int参数。Int参数的意思 为”request code”,就是标识一个请求。当收到intent结果时,回调提供了相同的请求的代码,使应用程序可以正确识别结果,并决定如何处理它。例如,代码清单 7-9是说如何启动一个activity并允许用户选择一个联系人:

图片 12

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

图片 13

 

代码清单7-9

7.2.2 接收一个结果

让我们看一下代码清单7-10,它是怎样处理结果的:

图片 14

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // 检查响应的请求
    if (requestCode == PICK_CONTACT_REQUEST) {
        // 确保请求是成功的
        if (resultCode == RESULT_OK) {
            // Do something.

        }
    }
}

图片 15

 

代码清单7-10

为了成功地处理结果,你必须明白,intent结果的格式将是什么。例如,People app(早些版本叫Contacts app)始终用content URI返回结果并识别被选择的联系人,Camera app在返回一个Bitmap。

上面的代码清单7-10很简单,下面的代码清单7-11是上面的扩展,让我们看下怎样读取联系人数据

图片 16

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    //检查响应的请求
    if (requestCode == PICK_CONTACT_REQUEST) {
        //确保请求是成功的
        if (resultCode == RESULT_OK) {
            // 获得指向选定联系人的URI
            Uri contactUri = data.getData();
            //我们只需要号码(NUMBER)列 
            String[] projection = {Phone.NUMBER};

            // 在联系人中执行查询,获得NUMBER column
            // 我们不需要挑选或排序
            // 提示:  query()方法应该在单独的线程执行,避免阻塞UI线程
            // 考虑使用CursorLoader 执行查询
            Cursor cursor = getContentResolver()
                    .query(contactUri, projection, null, null, null);
            cursor.moveToFirst();

            // 从NUMBER column中检索电话号码
            int column = cursor.getColumnIndex(Phone.NUMBER);
            String number = cursor.getString(column);

            // 使用电话号码做些事情
        }
    }
}

图片 17

 

代码清单7-11

注意: Android 2.3 (API level 9)以前,在Contacts Provider执行一个查询需要申明READ_CONTACTS权限,虽然在2.3开始有一个临时的权限可以让你去读取Contacts Provider,但依旧不能查询。所以不管什么版本我们都申明READ_CONTACTS权限即可

1.3. 显示App候选框

调用startActivity()的时候:

  • 如果只有一个activity能执行,则系统会直接启动那个activity;
  • 如果有多个activity能执行,系统会显示一个dialog让用户来选择使用哪个activity来执行,并且带有一个"将此选择设置为默认"的选项,也就是如果你选择了"将此选择设置为默认"的选项后再点击相应的activity,那么这个intent以后都将直接由这个activity来执行,这种适用于打开网页这种需要保持使用某个app的activity来执行的情况.

但是还有一种情况,就是我就是要每次都要选择不同的activity来处理,比如分享,显然我不可能只分享到某个app,那要如何操作呢?这就需要用到APP Chooser,会每次都显示,让用户下选择.使用时只需调用Intent的createChooser()方法即可,示例代码如下:

Intent intent = new Intent(Intent.ACTION_SEND);...// Always use string resources for UI text.// This says something like "Share this photo with"String title = getResources().getString(R.string.chooser_title);// Create intent to show chooserIntent chooser = Intent.createChooser(intent, title);// Verify the intent will resolve to at least one activityif (intent.resolveActivity(getPackageManager != null) { startActivity;}

启动其他App的Activity是双向的,你可以传给别的Activity数据,你也可以接收它的返回结果,想要接收到结果则需要用startActivityForResult()来启动Intent,而不是startActivity(),然后在onActivityResult()的回调中接收.

  • 注意: 显式和隐式的Intent用startActivityForResult()都能启动,但是如果是在自己app内的交互,你应该要使用显式的Intent来确保能接收到期望的结果.

示例代码如下:

// 启动intentstatic final int PICK_CONTACT_REQUEST = 1; // The request code...private void pickContact() { Intent pickContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts")); pickContactIntent.setType(Phone.CONTENT_TYPE); // Show user only contacts w/ phone numbers startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);}// 接收和处理返回结果@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { // Check which request we're responding to if (requestCode == PICK_CONTACT_REQUEST) { // Make sure the request was successful if (resultCode == RESULT_OK) { // The user picked a contact. // The Intent's data Uri identifies which contact was selected. // Do something with the contact here (bigger example below) } }}

为了成功处理返回结果,你必须要知道返回的Intent的格式是什么,比如通讯录会返回带URI的结果,相机App会将Bitmap对象保存在"data"数据中返回,下面看下具体的通讯录返回的联系人数据:

@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; // Do something with the phone number... } }}

注意不同版本的通讯录的权限请求,详细参考Security and Permissions

上面两点讲的是如何启动其他App一起如何处理返回结果,现在要讲的时如何让其他App来启动你的Activity,要实现这个功能,你的Activity需要做一些准备,比如你想支持分享操作,需要设置ACTION_SEND,具体实现在Manifest中添加<intent-filter>元素并将相应action加入.

  • Tips: 系统对于Intent的操作是这样的:当你app安装的时候,系统会识别你在intent filter中的配置并将相应信息添加到系统内部的一个catalog,当一个app启动一个隐式的intent时,系统就会把intent中的信息拿出来去catalog中查找.

7.3 允许其他Apps启动你的Activity

在android平台上,如果你要集成facebook的社交功能,那么你可以使用facebokk提供的一个apk,里面集成了facebook 的众多功能,如分享信息照片等。在实际开发过程中,可能我们需要开发这样的一个类似的apk,别担心,android提供这样的功能并且很容易实现。

7.3.1 添加一个Intent Filter

我们需要正确的定义intents,让activity能更好的处理。每一个intent filter应该添加具体的action类型和数据类型。系统可能会发送一个给定的intent到一个activity,如果activity有一个 intent filter并符合下列条件的intent对象:

  1. Action:

一个用来执行动作的字符串名字。例如ACTION_SEND或ACTION_VIEW。在intent filter中的<action>节点指定它。必须是全称,不能使用API常量。

  1. Data:

相关的intent中数据的描述。在intent filter中的<data>节点指定它。在这个节点中使用一个或多个属性,你能指定MIME类型,一个URI前缀,一个URI组合,或者是 以上内容的组合。如果你不需要申明指定的Uri数据,那你仅指定 android:mimeType属性即可,例如text/plain或image /jpeg。

  1. Category

提供一种额外的方法来表示activity处理的intent,通常与用户手势和开始位置相关。系统支持几种不同的类别,但大部分都很少使用,一般在intent filter中的<category>节点使用CATEGORY_DEFAULT。

下面让我们看一个例子,下面的<intent-filter>中定义的内容表示在处理ACTION_SEND的intent中使用的数据类型为文本或图像,如代码清单7-12:

图片 18

<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>

图片 19

 

代码清单7-12

每一个传入的intent只有一个动作和一种数据类型,但声明多 个<data>,<action>,<category>也是OK的,如果动作和数据类型相互排斥的话,你就应该分 开它们。加入你的activity处理文本和图像,并且使用ACTION_SEND和ACTION_SENDTO intents。这样就是错误的,在这种情况下你应该使用两个<intent-filter>来分开它们。因为SENDTO必须使用Uri数 据,并且需要sms和smsto的scheme。让我们看下代码清单7-13:

图片 20

<activity android:name="ShareActivity">
    <!—为发送文本过滤; 接收SENDTO action 使用 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>
    <!—为发送文本或图像过滤; 接收SEND action和文本或者图像数据 -->
    <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>

图片 21

 

代码清单7-13

为了接收隐式的intents,我们必须在<intent-filter>中定义CATEGORY_DEFAULT中,如果没声明,那么你的activity不能解决处理隐式的intents。

7.3.2 在Activity中处理intent

为了决定在你activity中想要处理的动作,你能在启动activity时读取intent。在启动activity时, 调用getIntent()方法来检索启动activity的intent。你能在任意时刻这么做,但最好在onCreate()或onStart()中 这样做。下面让我们看下代码清单7-14:

图片 22

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    //获得启动activity的intent
    Intent intent = getIntent();
    Uri data = intent.getData();

    // 解决intent类型想做什么
    if (intent.getType().indexOf("image/") != -1) {
        //处理图像数据
    } else if (intent.getType().equals("text/plain")) {
        // 处理文本
    }
}

图片 23

 

代码清单7-14

7.3.3 返回一个结果

如果你想要返回一个结果到你调用的activity,最简单的就是调用setResult()方法来指定结果代码和intent结果。当你的操作完 成时,用户如果想要返回到最开始的activity,调用finish()来关闭和destroy你的activity即可。如代码清单7-15所示:

// 创建intent来传递某种结果数据
Intent result = new Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri");
setResult(Activity.RESULT_OK, result);
finish();

 

我们可以只指定result code。通常是RESULT_OK或RESULT_CANCELED。你可以添加额外的intent或者不添加。默认的result code是RESULT_CANCELED。所以如果用户在你设置result之前执行Back键,那么最初的activity收到的就是 RESULT_CANCELED,这并不是我们预计的结果,这个细节请注意。

3.1 添加Intent Filter

为了让你Activity来处理合适的intent,你需要尽可能精细的设置好action和data的值. 系统的标准如下:

  • Action: 字符串,也就是intent filter中的<action>元素,指定activity要执行的action,可以设置一个或多个,当然如果不设置就无法被其他App启动了.
  • Data: 与intent绑定的数据的描述,也就是<data>元素,可以设置一个或多个,但是推荐的只设置 android:mimeType这个属性即可,比如"text/plain"或"image/jpeg".
  • Category: 给Intent提供另外一种分类的方式,也就是<category>元素,可以设置一个或多个,默认都是"CATEGORY_DEFAULT"

示例代码如下:

<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>

如果有任何两对action和data互斥,则需要添加一个独立的intent filter将它们分开,比如你的Activity要处理text和image,Action为ACTION_SEND和ACTION_SENDTO,就必须定义两个intent filter来将它们分开,因为ACTION_SENDTO一定要用Uri数据来适配接收者地址(如果混在一起写,未携带地址的Intent也能通过ACTION_SENDTO,进而启动你的Activity,这样就不能很好的处理了),如下示例:

<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,不然匹配不了.

具体可以参考Receiving Simple Data from Other Apps.

3.2 在你的Activity中处理接收到的Intent

用getIntent()方法拿到Intent对象,你应该在onCreate()或onStart()中来处理,如:

@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Get the intent that started this activity Intent intent = getIntent(); Uri data = intent.getData(); // Figure out what to do based on the intent type if (intent.getType().indexOf != -1) { // Handle intents with image data ... } else if (intent.getType().equals("text/plain")) { // Handle intents with text ... }}

3.3 返回结果

要给启动你的Activity的Activity放回结果很简单,只需调用setResult()方法然后结束时调用finish()方法即可.如下:

// Create intent to deliver some kind of result dataIntent result = new Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri"));setResult(Activity.RESULT_OK, result);finish();

返回结果中需要设置返回码,选RESULT_OK或RESULT_CANCELED(也可以自己给个任意int数值).

  • 注意:默认的返回码是RESULT_CANCELED,如果你没设置返回码就返回,默认就是该值.

如果不想返回数据,或者只想返回一个int类型的数据,那么可以直接设置返回码:

setResult(RESULT_COLOR_RED);finish();
  • 注意: 没必要去检查你的Activity是被startActivity()启动还是startActivityForResult()启动,如果启动你的intent可能需要返回,你就调用setResult()来设置相应的返回结果,对方接收不了就会被系统ignore掉.-----------------------------------------------------说了这么多你是不是想特别特别特别特别特别特别特别特别想知道如何检查你的Activity是被哪个启动的???反正我是特别想就对了..................... 可以用getCallingActivity()的返回值为空与否来判断.

总结

这篇讲的Intent都是比较基础的,也比较全面,对于Android其他部分的理解还是比较重要的.

Reference

  1. Interacting with Other Apps
  2. Sending the User to Another App
  3. Getting a Result from an Activity
  4. Allowing Other Apps to Start Your Activity
  5. How to know if an activity is called using startActivityForResult or simply called by using startActivity?
  6. Android中Intent对象与Intent Filter过滤匹配过程详解

本文由今晚最快开奖现场直播发布于编程应用,转载请注明出处:利用Intent来开展App间的主导交互,系统深远学习

关键词:

源码分析,Glide使用简介及流程分析

Glide 那篇小说将会为大家梳理一下Glide3.5版本的大旨流程,为了便利阅读,文章中的源码部分将轻松部分有关至极捕获...

详细>>

Android难题之——自定义View(上)

1、每个Activity包含一个Window对象(Window是abstract的,一般是由PhoneWindow实现)。2、PhoneWindow将DecorView设置为整个应用的...

详细>>

热修复热点框架简析,Android插件框架机制研商

笔者 百度任玉刚 插件化框架 途牛已上线使用帮衬代码能源文件以插件情势加入到host。 插件化的主干形式是将二个...

详细>>

阅读笔记,线程安全性

首先使代码正确运行,然后再提高代码速度。【正确编写并发程序的方法】 线程安全:当多个线程访问某个类(对象...

详细>>