Activity通信 之 把用户导向另外一个APP

本文介绍如何在Android应用中使用Intent来启动其他应用,包括创建Intent、验证接收应用的存在及显示应用选择器的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

android 最重要的一个特性就是可以在一个APP的界面,利用”action”动作把用户导向另外一个APP。比方说,你的APP想在地图上展示一个商业地址,你不需要自己去创建一个activity来显示这个地图。可以Intent来创建一个请求来在地图上展示这个地址,android系统会根据这个intent来启动相应的地图应用,显示你要看的这个地址。

就像我们在第一节:创建你的第一个APP 里面说的,你必须使用Intent 使得用户可以在你的app里面的activity之间跳转,一般都是创建一个明确里面定义了要启动的类名的intent。但是,如果我想要启动一个另外的app,比方说“访问一个地图”,那这里需要使用一个模糊的intent。

这一节说明下如何创建一个模糊的intent来执行特别的动作,用它来启动另外一个app里面符合这项动作的activity。

创建一个含蓄的Activity

函数的intent的不需要明确的指出要启动的activity类名,但是需要指定一个动作。这个动作指明了你想要做的事情,例如访问,编辑,发送或者获取某些内容。Intent也可以附加额外的数据信息给这个动作,比方说上面的你要查看的地图的地址,或者是要发送的邮件地址。根据你创建的Intent 类型,这个数据可以是Uri,或者是其他的一些类型,也有可能这个intent不需要任何数据。

如果要传入的数据是一个Uri,那么可以直接使用Intent的一个简单的构造函数。下面就是一个利用Uri指明要拨打的电话号码,利用Uri创建一个intent,进行拨打电话

Uri number = Uri.parse("tel:5551234");
Intent callIntent = new Intent(Intent.ACTION_DIAL, number);

然后可以调用startActivity(),把这个Intent作为参数,然后这个APP就对执行电话拨打,拨打上面指定的号码:5551234

下面是2组其他的Uri内容创建Intent动作的例子:

访问地图:

// Map point based on address
Uri 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 level
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);

访问一个网页:

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

其他的类型的模糊Intent需要”extra”数据,可以是不同类型的数据,比方说一个string类型的。可以使用putExtra()添加一个或者多个exta数据。

默认的,系统会根据intent里面的Uri来决定一个intent需要的合适MIME(多用途扩展)类型.如果没有使用Uri,那么需要用setType()来指定和这个intent的关联的数据类型。

设置MIME类型,能进一步的确定那种activity需要接收你的这个intent。

这里是一些添加extra数据来指定想要执行的动作的intent:

发送一个带有附件的邮件:

Intent emailIntent = new Intent(Intent.ACTION_SEND);
// The intent does not have a URI, so declare the "text/plain" MIME type
emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipients
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"));
// You can also attach multiple items by passing an ArrayList of Uris

创建一个日历事件:

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");

注意:这个日历事件仅仅在API 14之上才支持。

注意:在定义Intent的时候,尽可能的明确这个Intent的动作。比方说你想使用ACTION_VIEW intent来展示一张图片,你应该指定MIME类型:image/* . 这样可以防止那些同样接收ACTION_VIEW动作但是是用来访问其他的类型数据(比方说地图)的APP被触发.

验证存在一个APP可以接收指定的Intent

尽管android平台可以保证谋几个Intent是肯定可以被android内建的APP(如电话,邮件,或者日历)处理,但是我们应该在换起一个intent之前先判断是否有一个APP会支持接收这个intent.

警告:如果你用startActivity唤起一个Intent,但是没有一个APP可以接收处理这个Intent的时候,你的APP会奔溃。

判断是否有一个activity可以对这个intent做出回应,可以调用queryIntentActivities()获取一个有能力处理这个intent的activity列表。如果这个函数返回的list不是空,那么就可以放心的唤起这个intent.如下:

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

如果isIntentSafe是true,那么就是说至少有一个APP是可以接收处理这个intent的。如果是false,那么就是没有intent可以处理这个intent.

注意:一般来说,这个检查要在activity一开始启动的时候就执行,这样就可以在用户意图使用某种不支持的intent之前就禁止掉这个特性,比方说隐藏掉触动这个intent的按钮或者图标。如果你知道哪个APP可以支持某个intent,但是手机又没有安装,可以提供一个连接地址给用户去下载。关于这点,请阅读:link to your product on Google Play

利用Intent启动Activity

当创建好intent, 而且设置了extra信息,那就可以调用startActivity()把这个intent发送给系统。系统会识别出可以处理这个intent的activity,可能会有多个,系统会显示一个对话框,里面有多个可选的APP,这些APP里面都有可以处理这个intent的activity,你可以选择一个。

如图1所示:

这个就是一个对话框,里面有多个可以处理的传递给系统的intent的APP

如果只有一个activity支持处理这个intent,系统会直接启动这个对应的APP:

startActivity(intent);

下面是一个完整的例子,描述了如何创建一个访问地图的intent,判断是否有APP可以处理它:

// 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<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
boolean isIntentSafe = activities.size() > 0;
  
// Start an activity if it's safe
if (isIntentSafe) {
    startActivity(mapIntent);
}

显示一个APP选择器

当startActivity利用一个intent启动activity的时候,可能会有多个app会对这个intent做出反应,用户可以选择一个app作为默认启动(这个默认项可以在第一次启动的时候选额,看图1,下面的那个勾选框).这样做的好处是用户可以指定在执行某个常用的action的时候,直接启动那个默认的app,而不需要去反复选择。比方说访问网页(用户可能只想用某种浏览器打开),还有拍照(用户可以指定要启动的相机应用)。然而如果要进行的action可以被多个app处理,用户可能每次都想要自己的启动不同的APP,比方说分享动作,用户可能想通过多个APP来分享一条信息,你要显示给用户一个对话框,强迫用户每次去选择一个APP来处理这个动作,用户没办法在这个选择器里面进行设置默认的操作。

想要显示一个选择器,首先用createChooser()创建一个Intent,然后把这个intent传给startActivity()。如下:

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().getText(R.string.chooser_title);
// Create and start the chooser
Intent chooser = Intent.createChooser(intent, title);
startActivity(chooser);

这样就会显示出一个对话框,里面是可以响应传递给createChooser 那个intent的所有APP,可以为这个对话框设置一个标题,像上面用title设定。

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值