【Android基础】Android中的Intent详解

前言:

每个应用程序都有若干个Activity组成,每一个Activity都是一个应用程序与用户进行交互的窗口,呈现不同的交互界面。因为每一个Acticity的任务不一样,所以经常互在各个Activity之间进行跳转,在Android中这个动作是靠Intent来完成的。你通过startActivity()方法发送一个Intent给系统,系统会根据这个Intent帮助你找到对应的Activity,即使这个Activity在其他的应用中,也可以用这种方法启动它。

Intent的定义:

Intent是Android系统用来抽象描述要执行的一个操作,也可以在不同组件之间进行沟通和消息传递。

Intent意图可以是明确的指定组件的名称,这样你可以精确的启动某个系统组件,比如启动一个Activity。它也可以是模糊的,没有指定组件名称,只要是能够匹配到这个Intent的应用都可以接收到,比如发送一个拍照Intent,所有的拍照应用都会响应。

显式Intent和隐式Intent:

显式的Intent就是你已经知道要启动的组件名称,比如某个Activity的包名和类名,在Intent中明确的指定了这个组件(Activity),一般来说这种Intent经常用在一个应用中,因为你已经明确的知道要启动的组件名称。

隐式的Intent就是你不知道要启动的组件名称,只知道一个Intent动作要执行,比如:拍照,录像,查看地图。一般来说这种Intent用在不同的应用之间传递信息。

当你创建一个显式Intent来启动一个Activity或者Service时,系统会立刻启动那个组件通过你的Intent对象。

当你创建一个隐式Intent,系统会根据manifest file中的intent filter找匹配的组件,如果你发送的Intent匹配到一个intent filter,系统会把你的Intent传递给该filter对应的组件(Activity、Service等),并且启动它。如果找到多个匹配的intent filter对应的应用程序,则会弹出一个对话框让你选择哪个应用程序接受你的Intent。

注: 1、intent filter是一种应用程序manifest文件中的语法表达,就像是html的标签,它是一个系统组件标签(比如:Activity)的组成部分,可以说是子标签吧,这个系统组件接受什么样的intent就是用它来指定的,如果一个系统组件不写intent filter,那么它只能通过显式的intent来启动。 2、出于安全的角度,你的Service组件务必不要用隐式的intent filter来进行说明,因为用隐式的intent启动一个Service往往不能保证Service会被启动,并且用户也不知道哪个Service会响应你的Intent。从Android5.0(API 21),系统会抛出异常当你用隐式的Intent去调用bindService()方法。

创建一个Intent:

Android系统通过Intent对象携带的信息来确定启动哪个系统组件,比如:准确的组件名称,哪一个类别的组件会接收到这个intent,Intent还会携带其他的信息以便于组件正确的执行action。一个Intent主要包含以下信息:

  • Component name:

要启动的组件名称,在创建Intent的时候是可选的,但是它是显式Intent的重要标志,有它就意味着只有Component name匹配上的那个组件才能接收你发送出来的显示intent。如果不写那么你创建的Intent就是隐式的,系统会根据这个intent的其他信息(比如:action、data、category)来确定哪些组件来接收这个intent,所以如果你想明确的启动哪个组件,就通过component name来指定。

Intent的ComponentName属性是一个类的全称,包括包名,比如:com.example.ExampleActivity,你可以通过Intent的setComponent(),setClass(),setClassName()方法来设定,也可以通过Intent的构造方法来设定。

  • Action:

意图,一个字符串变量,用来指定Intent要执行的动作类别(比如:view or pick)。你可以在你的应用程序中自定义action,但是大部分的时候你只使用在Intent中定义的action。下面是启动Activity经常用的action:

  • ACTION_VIEW:

在调用startActivity()方法启动Activity时,用此action来呈现一些信息给用户,比如在相册中查看一张照片,显示一个地理位置在地图中。

  • ACTION_SEND:

也被称为"share"(共享)意图,在调用startActivity()方法启动Activity时,用此action来分享一些用户想要分享的数据给其他应用程序,比如邮件app或者社交app。

想要了解更多的action可以查看Intent源码或者api,在Intent中定义了很多action,除了在Android framework中,在别处也定义了很多action,比如在Settings应用中。

你可以通过Intent的setAction()方法或者Intent的构造方法来指定action。如果你要自定义action,最好是用你的包名做前缀,比如:

static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";

  • Data:

一个Uri对象,对应着一个数据,这个数据可能是MIME类型的。当创建一个intent时,除了要指定数据的URI之外,指定数据的类型(MIME type)也很重要,比如,一个activity能够显示照片但是无法播放视频,虽然启动Activity时URI格式很相似。指定MIME type是很重要的,它能够帮助系统找到最合适的那个系统组件来处理你的intent请求。然而,MIME type有时能够通过URI来推测出来,特别是当data是content:的URI,这样的data表明在设备中由ContentProvider提供。

只设置数据的URI可以调用setData()方法,只设置MIME类型可以调用setType()方法,如果要同时设置这两个可以调用setDataAndType()。

注意:如果要设置URI和MIME,不要调用setData()和setType(),因为会相互清除设置的参数数据,而是直接调用setDataAndType()。

  • Category:

一个包含Intent额外信息的字符串,表示哪种类型的组件来处理这个Intent。任何数量的Category 描述都可以添加到Intent中,但是很多intent不需要category,下面列举一些常用的category:

  • CATEGORY_BROWSABLE:

目标Activity允许从web页面上的链接(比如图片链接)启动来显示数据。

  • CATEGORY_LAUNCHER:

表示这个Activity是Activity栈最初的Activity,应用程序的主Activity,可以在桌面应用程序列表找到并启动它。

你可以通过调用addCagegory()方法来设置category。

以上Intent的属性(component name、action、data and category)都是Intent的特征属性,通过这些属性Android系统可以找到哪个应用组件将会被启动。

以下的属性是Intent的额外属性,这些属性不会影响到intent的处理和启动系统组件。

  • Extras:

Intent可以携带的额外key-value数据,你可以通过调用putExtra()方法设置数据,每一个key对应一个value数据。你也可以通过创建Bundle对象来存储所有数据,然后通过调用putExtras()方法来设置数据。对于数据key的名字要尽量用包名做前缀,然后再加上其他,这样来保证key的唯一性。

  • Flags:

用来指示系统如何启动一个Activity(比如:这个Activity属于哪个Activity栈)和Activity启动后如何处理它(比如:是否把这个Activity归为最近的活动列表中)。

创建显式Intent:

一个显式Intent明确的指定了要启动的组件名称,比如Activity名称或者Service的名称。创建一个显式的Intent必须定义Component属性,其他的属性可选。下面的例子是创建一个Service在app中,名字叫DownloadService,功能是从网络上下载文件,你可以通过下面的代码来启动它:

// Executed in an Activity, so 'this' is the Context
// The fileUrl is a string URL, such as "http://www.example.com/image.png"
Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
startService(downloadIntent);

创建隐式Intent:

一个隐式的Intent定义了将要执行的动作,任何在设备上的app都可以响应这个动作。用隐式Intent的非常的有用,当你的app不能处理某些请求动作时,但是系统中的其他应用有这个处理的能力,用户就能方便的利用其他应用完成这个操作。比如你用百度云盘下载了一个pdf文档,你在点击打开这个文档的时候百度云盘是无法打开的,但是也许你系统上安装有其他的能打开pdf文档的阅读器,这个时候就会弹出一个对话框,列举了可以打开pdf文档的应用程序,你可以自由选择一个应用程序打开你下载的文档。例如下面查看文档的例子:

// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType(HTTP.PLAIN_TEXT_TYPE); // "text/plain" MIME type

// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
    startActivity(sendIntent);
}

注意:也许你的设备中没有能够执行你的隐式Intent的应用,这个时候startActivity将会失败并且你的app会出现crash,最好的办法是在startActivity之前调用resolveActivity检查一下是否有Activity可以响应。 如果系统中有一个应用程序可以响应则会直接打开那个应用程序,如果系统中有多个app可以处理这个action则会弹出对话框让你选择哪个应用程序来处理。

总结:

以上内容主要说了Intent的定义、分类和属性解释,这样让你对Intent有一个详细的了解,为以后学习利用Intent在应用程序之间进行交流打下基础。

原文发布于微信公众号 - 程序员互动联盟(coder_online)

原文发表时间:2015-08-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏腾讯Bugly的专栏

《Android插件化技术——原理篇》

| 导语 插件化技术最早从2012年诞生至今,已经走过了5个年头。从最初只支持Activity的动态加载发展到可以完全模拟app运行时的沙箱系统,各种开源项目层...

7876
来自专栏面朝大海春暖花开

mysql树形结构递归查询

之前一直用的是Oracle,对于树形查询可以使用start with ... connect by 

1134
来自专栏xcywt

学习SQLite之路(四)

20160621 更新 参考: http://www.runoob.com/sqlite/sqlite-tutorial.html 1. SQLite   a...

1908
来自专栏前端杂货铺

js的并行加载以及顺序执行

重新温习了下这段内容,发现各个浏览器的兼容性真的是搞大了头,处理起来很是麻烦。 现在现总结下并行加载多个js的方法:   1,对于动态createElement...

2928
来自专栏比原链

剥开比原看代码16:比原是如何通过/list-transactions显示交易信息的

Gitee地址:https://gitee.com/BytomBlockchain/bytom

351
来自专栏何俊林

Android开发中,有哪些让你觉得相见恨晚的方法、类或接口?

前言:Android开发中,不是每一个api,我们都知道,一般情况,面对一个陌生的类,首先new出这个class,得到一到临时变量,然后class.xxx,看对...

1668
来自专栏Android 研究

APK安装流程详解16——Android包管理总结

如果你是Android 系统中的架构师,让你设计一个Android的安装系统中的PackageManagerService,你会怎么设计? 既然要设计,咱们要首...

923
来自专栏数据库

MySQL支持哪几类分区表?

Q 题目 MySQL支持哪几类分区表? A 答案 表分区是指根据一定规则,将数据库中的一张表分解成多个更小的,容易管理的部分。从逻辑上看,只有一张表,但是底层却...

2088
来自专栏小灰灰

Java实现几种简单的重试机制

背景 当业务执行失败之后,进行重试是一个非常常见的场景,那么如何在业务代码中优雅的实现重试机制呢? 设计 我们的目标是实现一个优雅的重试机制,那么先来看下怎么...

6468
来自专栏向治洪

XMPP客户端库Smack 4.0.6版开发之二

XMPP客户端库Smack 4.0.6版开发之二 三、Smack库的特征 1、极度简单易用,API功能强大 发送一条文本消息给某个用户只需几行代码: Abst...

1915

扫码关注云+社区