robert和android的区别,Android中的Intent的各种强大

在一个Android应用中,主要是由四种组件组成的,这四种组件可参考“Android应用的构成”。

而这四种组件是独立的,它们之间可以互相调用,协调工作,最终组成一个真正的Android应用。

在这些组件之间的通讯中,主要是由Intent协助完成的。

Intent

负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将

Intent传递给调用的组件,并完成组件的调用。

因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的解耦。

例如,在一个联系人维护的应用中,当我们在一个联系人列表屏幕(假设对应的Activity为listActivity)上,点击某个联系人后,希望能够跳出此联系人的详细信息屏幕(假设对应的Activity为detailActivity)

为了实现这个目的,listActivity 需要构造一个

Intent,这个Intent用于告诉系统,我们要做“查看”动作,此动作对应的查看对象是“某联系人”,然后调用startActivity

(Intent intent),

将构造的Intent传入,系统会根据此Intent中的描述,到ManiFest中找到满足此

Intent要求的Activity,系统会调用找到的Activity,即为detailActivity,最终传入

Intent,detailActivity则会根据此Intent中的描述,执行相应的操作。

决定哪个Activity来运行的过程称为Intent解析。Intent解析的目的是通过下面的过程找到可能匹配得最好的Intent

Filter:

1. Android把安装的包中可获得的Intent Filter放到一个列表中。

2. 动作和与正在解析的Intent的种类不关联的Intent Filter会从列表中删除。

2.1. 动作匹配指Intent

Filter包含特定的动作或没有指定的动作。一个Intent Filter有一个或多个定义的动作,如果没有任何一个能与Intent指定的动作匹配的话,这个Intent Filter在算作是动作匹配检查失败。

2.2.

种类匹配更为严格。Intent Filter必须包含所有在解析的Intent中定义的种类。一个没有特定种类的Intent Filter只能与没有种类的Intent匹配。

3. 最后,Intent的数据URI中的部分会与Intent Filter中的data标签比较。如果Intent Filter定义scheme,host/authority,path或mimetype,这些值都会与Intent的URI比较。任何不匹配都会导致Intent Filter从列表中删除。

没有指定data值的Intent Filter会和所有的Intent数据匹配。

3.1. mimetype是正在匹配的数据的数据类型。当匹配数据类型时,你可以使用通配符来匹配子类型(例如,earthquakes/*)。如果Intent Filter指定一个数据类型,它必须与Intent匹配;没有指定数据的话全部匹配。

3.2. scheme是URI部分的协议——例如,http:,mailto:,tel:。

3.3. host-name或“data authority”是介于URI中scheme和path之间的部分(例如,www.google.com)。匹配主机名时,Intent Filter的scheme也必须通过匹配。

3.4. 数据path是紧接在“data authority”的后面(例如,/ig)。path只在scheme和host-name部分都匹配的情况下才匹配。

4.

如果这个过程中多于一个组件解析出来的话,它们会以优先度来排序,可以在Intent Filter的节点里添加一个可选的标签。最高等级的组件会返回。

Android本地的应用程序组件和第三方应用程序一样,都是Intent解析过程中的一部分。它们没有更高的优先度,可以被新的Activity完全的代替,这些新的Activity宣告自己的Intent Filter能响应相同的动作请求。

使用Intent Filter,应用程序组件告诉Android,它们能为其它程序的组件的动作请求提供服务,包括同一个程序的组件、本地的或第三方的应用程序。

为了注册一个应用程序组件为Intent处理者,在组件的manifest节点添加一个intent-filter标签。

在Intent Filter节点里使用下面的标签(关联属性),你能指定组件支持的动作、种类和数据:

❑ action

使用android:name特性来指定对响应的动作名。动作名必须是独一无二的字符串,所以,一个好的习惯是使用基于Java包的命名方式的命名系统。

❑ category

使用android:category属性用来指定在什么样的环境下动作才被响应。每个Intent

Filter标签可以包含多个category标签。你可以指定自定义的种类或使用Android提供的标准值,如下所示:

❑ ALTERNATIVE

你将在这章的后面所看到的,一个Intent Filter的用途是使用动作来帮忙填入上下文菜单。ALTERNATIVE种类指定,在某种数据类型的项目上可以替代默认执行的动作。例如,一个联系人的默认动作时浏览它,替代的可能是去编辑或删除它。

❑ SELECTED_ALTERNATIVE

与ALTERNATIVE类似,但ALTERNATIVE总是使用下面所述的Intent解析来指向单一的动作。SELECTED_ALTERNATIVE在需要一个可能性列表时使用。

❑ BROWSABLE

指定在浏览器中的动作。当Intent在浏览器中被引发,都会被指定成BROWSABLE种类。

❑ DEFAULT

设置这个种类来让组件成为Intent

Filter中定义的data的默认动作。这对使用显式Intent启动的Activity来说也是必要的。

❑ GADGET

通过设置GADGET种类,你可以指定这个Activity可以嵌入到其他的Activity来允许。

❑ HOME

HOME

Activity是设备启动(登陆屏幕)时显示的第一个Activity。通过指定Intent Filter为HOME种类而不指定动作的话,你正在将其设为本地home画面的替代。

❑ LAUNCHER

使用这个种类来让一个Activity作为应用程序的启动项。

❑ data

data标签允许你指定组件能作用的数据的匹配;如果你的组件能处理多个的话,你可以包含多个条件。你可以使用下面属性的任意组合来指定组件支持的数据:

❑ android:host

指定一个有效的主机名(例如,com.google)。

❑ android:mimetype

允许你设定组件能处理的数据类型。例如,

android:value=”vnd.android.cursor.dir/*”/>能匹配任何Android游标。

❑ android:path

有效地URI路径值(例如,/transport/boats/)。

❑ android:port

特定主机上的有效端口。

❑ android:scheme

需要一个特殊的图示(例如,content或http)。

接下来的代码片段显示了如何配置Activity的Intent Filter,使其以在特定数据下的默认的或可替代的动作的身份来执行SHOW_DAMAGE动作。(创建地震内容将在下一章节。)

Java代码 a4c26d1e5885305701be709a3d33442f.png

android:label=”View Damage”>

android:name=”com.paad.earthquake.intent.action.SHOW_DAMAGE”>

android:name=”android.intent.category.ALTERNATIVE_SELECTED”

/>

一、抽象描述要描述什么

在Android参考文档中,对Intent的定义是执行某操作的一个抽象描述(确实很抽象)。我们先来看看这里的抽象描述,到底描述了什么。

首先,是要执行的动作(action)的一个简要描述,如

VIEW_ACTION(查看)、EDIT_ACTION(修改)等,Android为我们定义了一套标准动作:

复制内容到剪贴板

代码:

MAIN_ACTION

VIEW_ACTION

EDIT_ACTION

PICK_ACTION

GET_CONTENT_ACTION

DIAL_ACTION

CALL_ACTION

SENDTO_ACTION

ANSWER_ACTION

INSERT_ACTION

DELETE_ACTION

RUN_ACTION

LOGIN_ACTION

CLEAR_CREDENTIALS_ACTION

SYNC_ACTION

PICK_ACTIVITY_ACTION

WEB_SEARCH_ACTION

此外,我们还可以根据应用的需要,定义我们自己的动作,并可定义相应的Activity来处理我们的自定义动作。

其次,是执行动作要操作的数据(data),Android中采用指向数据的一个

URI来表示,如在联系人应用中,一个指向某联系人的URI可能为:content://contacts/1。

这种URI表示,通过 ContentURI这个类来描述,具体可以参考android.net.ContentURI类的文档。

以联系人应用为例,以下是一些action / data对,及其它们要表达的意图:

复制内容到剪贴板

代码:

VIEW_ACTION content://contacts/1-- 显示标识符为"1"的联系人的详细信息

EDIT_ACTION content://contacts/1-- 编辑标识符为"1"的联系人的详细信息

VIEW_ACTION content://contacts/-- 显示所有联系人的列表

PICK_ACTION content://contacts/--

显示所有联系人的列表,并且允许用户在列表中选择一个联系人,然后把这个联系人返回给父activity。例如:电子邮件客户端可以使用这个

Intent,要求用户在联系人列表中选择一个联系人

另外,除了action和data这两个重要属性外,还有一些附加属性:

category(类别),被执行动作的附加信息。例如 LAUNCHER_CATEGORY 表示Intent

的接受者应该在Launcher中作为顶级应用出现;而ALTERNATIVE_CATEGORY表示当前的Intent是一系列的可选动作中的一个,这些动作可以在同一块数据上执行。

type(数据类型),显式指定Intent的数据类型(MIME)。一般Intent的数据类型能够根据数据本身进行判定,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导。

component(组件),指定Intent 的的目标组件的类名称。通常 Android会根据Intent

中包含的其它属性的信息,比如action、data/type、category进行查找,最终找到一个与之匹配的目标组件。但是,如果

component这个属性有指定的话,将直接使用它指定的组件,而不再执行上述查找过程。指定了这个属性以后,Intent的其它所有属性都是可选的。

extras(附加信息),是其它所有附加信息的集合。使用extras可以为组件提供扩展信息,比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。

总之,action、 data/type、category和extras 一起形成了一种语言。

这种语言使系统能够理解诸如“查看某联系人的详细信息”之类的短语。

随着应用不断的加入到系统中,它们可以添加新的action、 data/type、category来扩展这种语言。

应用也可以提供自己的Activity来处理已经存在的这样的“短语”,从而改变这些“短语”的行为。

二、 Android如何解析Intent

在应用中,我们可以以两种形式来使用Intent:

*

直接Intent:指定了component属性的Intent(调用

setComponent(ComponentName)或者setClass(Context,

Class)来指定)。通过指定具体的组件类,通知应用启动对应的组件。

例如:ComponentName aComponentName=new

ComponentName("com.android.email.activity", "Welcome.class");

intent.setComponent(aComponentName);

*

*

间接Intent:没有指定comonent属性的Intent。这些Intent需要包含足够的信息,这样系统才能根据这些信息,在在所有的可用组件中,确定满足此Intent的组件。

对于直接Intent,Android不需要去做解析,因为目标组件已经很明确,Android需要解析的是那些间接Intent,通过解析,将

Intent映射给可以处理此Intent的Activity、IntentReceiver或Service。

Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Intent,最终找到匹配的Intent。在这个解析过程中,Android是通过Intent的action、type、category这三个属性来进行判断的,判断方法如下:

*

如果Intent指明定了action,则目标组件的IntentFilter的action列表中就必须包含有这个action,否则不能匹配;

*

*

如果Intent没有提供type,系统将从data中得到数据类型。和action一样,目标组件的数据类型列表中必须包含Intent的数据类型,否则不能匹配。

*

*

如果Intent中的数据不是content:

类型的URI,而且Intent也没有明确指定它的type,将根据Intent中数据的scheme (比如 http:

或者mailto: ) 进行匹配。同上,Intent 的scheme必须出现在目标组件的scheme列表中。

*

*

如果Intent指定了一个或多个category,这些类别必须全部出现在组建的类别列表中。比如

Intent中包含了两个类别:LAUNCHER_CATEGORY 和

ALTERNATIVE_CATEGORY,解析得到的目标组件必须至少包含这两个类别。

三、应用例子

以下,以Android

SDK中的便笺例子来说明,Intent如何定义及如何被解析。这个应用可以让用户浏览便笺列表、查看每一个便笺的详细信息。

xml 代码

复制内容到剪贴板

代码:

Xml代码 a4c26d1e5885305701be709a3d33442f.png

例子中的第一个Activity是

com.google.android.notepad.NotesList,它是应用的主入口,提供了三个功能,分别由三个

intent-filter进行描述:

1、第一个是进入便笺应用的顶级入口(action为android.app.action.MAIN)。类型为

android.app.category.LAUNCHER表明这个Activity将在Launcher中列出。

2、第二个是,当type为vnd.android.cursor.dir/vnd.google.note(保存便笺记录的目录)时,可以查看可用的便笺(action为android.app.action.VIEW),或者让用户选择一个便笺并返回给调用者(action为

android.app.action.PICK)。

3、第三个是,当type为vnd.android.cursor.item/vnd.google.note时,返回给调用者一个用户选择的便笺(action为android.app.action.GET_CONTENT),而用户却不需要知道便笺从哪里读取的。有了这些功能,下面的

Intent就会被解析到NotesList这个activity:

复制内容到剪贴板

代码:

{ action=android.app.action.MAIN

}:与此Intent匹配的Activity,将会被当作进入应用的顶级入口。

{ action=android.app.action.MAIN,

category=android.app.category.LAUNCHER }:这是目前Launcher实际使用的

Intent,用于生成Launcher的顶级列表。

{ action=android.app.action.VIEW

data=content://com.google.provider.NotePad/notes

}:显示"content://com.google.provider.NotePad/notes"下的所有便笺的列表,使用者可以遍历列表,并且察看某便笺的详细信息。

{ action=android.app.action.PICK

data=content://com.google.provider.NotePad/notes

}:显示"content://com.google.provider.NotePad/notes"下的便笺列表,让用户可以在列表中选择一个,然后将选择的便笺的

URL返回给调用者。

{ action=android.app.action.GET_CONTENT

type=vnd.android.cursor.item/vnd.google.note

}:和上面的action为pick的Intent类似,不同的是这个Intent允许调用者(在这里指要调用NotesList的某个

Activity)指定它们需要返回的数据类型,系统会根据这个数据类型查找合适的

Activity(在这里系统会找到NotesList这个Activity),供用户选择便笺。

第二个

Activity是com.google.android.notepad.NoteEditor,它为用户显示一条便笺,并且允许用户修改这个便笺。

它定义了两个intent-filter,所以具有两个功能。

第一个功能是,当数据类型为

vnd.android.cursor.item/vnd.google.note时,允许用户查看和修改一个便签(action为

android.app.action.VIEW和android.app.action.EDIT)。

第二个功能是,当数据类型为

vnd.android.cursor.dir/vnd.google.note,为调用者显示一个新建便笺的界面,并将新建的便笺插入到便笺列表中(action为android.app.action.INSERT)。

有了这两个功能,下面的Intent就会被解析到NoteEditor这个activity:

复制内容到剪贴板

代码:

{ action=android.app.action.VIEW

data=content://com.google.provider.NotePad/notes/{ID}} :向用户显示标识为

ID的便笺。

{ action=android.app.action.EDIT

data=content://com.google.provider.NotePad/notes/{ID}}:允许用户编辑标识为ID的便笺。

{ action=android.app.action.INSERT

data=content://com.google.provider.NotePad/notes

}:在“content://com.google.provider.NotePad/notes”这个便笺列表中创建一个新的空便笺,并允许用户编辑这个便签。当用户保存这个便笺后,这个新便笺的URI将会返回给调用者。

最后一个Activity是

com.google.android.notepad.TitleEditor,它允许用户编辑便笺的标题。

它可以被实现为一个应用可以直接调用(在Intent中明确设置component属性)的类,不过这里我们将为你提供一个在现有的数据上发布可选操作的方法。

在这个 Activity的唯一的intent-filter中,拥有一个私有的action:

com.google.android.notepad.action.EDIT_TITLE,表明允许用户编辑便笺的标题。

和前面的 view和edit 动作一样,调用这个Intent

的时候,也必须指定具体的便笺(type为vnd.android.cursor.item/vnd.google.note)。不同的是,这里显示和编辑的只是便笺数据中的标题。

除了支持缺省类别(android.intent.category.DEFAULT),标题编辑器还支持另外两个标准类别:

android.intent.category.ALTERNATIVE和

android.intent.category.SELECTED_ALTERNATIVE。

实现了这两个类别之后,其它

Activity就可以调用queryIntentActivityOptions(ComponentName, Intent[],

Intent, int)查询这个Activity提供的action,而不需要了解它的具体实现;

或者调用 addIntentOptions(int, int, ComponentName, Intent[], Intent,

int,

Menu.Item[])建立动态菜单。需要说明的是,在这个intent-filter中有一个明确的名称(通过android:label=

"@string/resolve_title"指定),在用户浏览数据的时候,如果这个Activity是数据的一个可选操作,指定明确的名称可以为用户提供一个更好控制界面。

有了这个功能,下面的Intent就会被解析到TitleEditor这个Activity:

复制内容到剪贴板

代码:

{ action=com.google.android.notepad.action.EDIT_TITLE

data=content://com.google.provider.NotePad/notes/{ID}}:显示并且允许用户编辑标识为ID的便笺的标题

以下是常见的intent调用:

1,掉web浏览器

Java代码

Uri myBlogUri = Uri.parse("http://kuikui.javaeye.com");

returnIt = new Intent(Intent.ACTION_VIEW, myBlogUri);

Uri myBlogUri = Uri.parse("http://kuikui.javaeye.com");

returnIt = new Intent(Intent.ACTION_VIEW, myBlogUri);

2,地图

Java代码

Uri mapUri = Uri.parse("geo:38.899533,-77.036476");

returnIt = new Intent(Intent.ACTION_VIEW, mapUri);

Uri mapUri = Uri.parse("geo:38.899533,-77.036476");

returnIt = new Intent(Intent.ACTION_VIEW, mapUri);

3,调拨打电话界面

Java代码

Uri telUri = Uri.parse("tel:100861");

returnIt = new Intent(Intent.ACTION_DIAL, telUri);

Uri telUri = Uri.parse("tel:100861");

returnIt = new Intent(Intent.ACTION_DIAL, telUri);

4,直接拨打电话

Java代码

Uri callUri = Uri.parse("tel:100861");

returnIt = new Intent(Intent.ACTION_CALL, callUri);

Uri callUri = Uri.parse("tel:100861");

returnIt = new Intent(Intent.ACTION_CALL, callUri);

5,卸载

Java代码

Uri uninstallUri = Uri.fromParts("package", "xxx", null);

returnIt = new Intent(Intent.ACTION_DELETE, uninstallUri);

Uri uninstallUri = Uri.fromParts("package", "xxx", null);

returnIt = new Intent(Intent.ACTION_DELETE, uninstallUri);

6,安装

Java代码

Uri installUri = Uri.fromParts("package", "xxx", null);

returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED,

installUri);

Uri installUri = Uri.fromParts("package", "xxx", null);

returnIt = new Intent(Intent.ACTION_PACKAGE_ADDED,

installUri);

7,播放

Java代码

returnIt = new Intent(Intent.ACTION_VIEW, playUri);

returnIt = new Intent(Intent.ACTION_VIEW, playUri);

8,掉用发邮件

Java代码

Uri emailUri = Uri.parse("mailto:shenrenkui@gmail.com");

returnIt = new Intent(Intent.ACTION_SENDTO, emailUri);

Uri emailUri = Uri.parse("mailto:shenrenkui@gmail.com");

returnIt = new Intent(Intent.ACTION_SENDTO, emailUri);

9,发邮件

Java代码

returnIt = new Intent(Intent.ACTION_SEND);

String[] tos = { "shenrenkui@gmail.com" };

String[] ccs = { "shenrenkui@gmail.com" };

returnIt.putExtra(Intent.EXTRA_EMAIL, tos);

returnIt.putExtra(Intent.EXTRA_CC, ccs);

returnIt.putExtra(Intent.EXTRA_TEXT, "body");

returnIt.putExtra(Intent.EXTRA_SUBJECT, "subject");

returnIt.setType("message/rfc882");

Intent.createChooser(returnIt, "Choose Email Client");

returnIt = new Intent(Intent.ACTION_SEND);

String[] tos = { "shenrenkui@gmail.com" };

String[] ccs = { "shenrenkui@gmail.com" };

returnIt.putExtra(Intent.EXTRA_EMAIL, tos);

returnIt.putExtra(Intent.EXTRA_CC, ccs);

returnIt.putExtra(Intent.EXTRA_TEXT, "body");

returnIt.putExtra(Intent.EXTRA_SUBJECT, "subject");

returnIt.setType("message/rfc882");

Intent.createChooser(returnIt, "Choose Email Client");

10,发短信

Java代码

Uri smsUri = Uri.parse("tel:100861");

returnIt = new Intent(Intent.ACTION_VIEW, smsUri);

returnIt.putExtra("sms_body", "shenrenkui");

returnIt.setType("vnd.android-dir/mms-sms");

Uri smsUri = Uri.parse("tel:100861");

returnIt = new Intent(Intent.ACTION_VIEW, smsUri);

returnIt.putExtra("sms_body", "shenrenkui");

returnIt.setType("vnd.android-dir/mms-sms");

11,直接发邮件

Java代码

Uri smsToUri = Uri.parse("smsto://100861");

returnIt = new Intent(Intent.ACTION_SENDTO, smsToUri);

returnIt.putExtra("sms_body", "shenrenkui");

Uri smsToUri = Uri.parse("smsto://100861");

returnIt = new Intent(Intent.ACTION_SENDTO, smsToUri);

returnIt.putExtra("sms_body", "shenrenkui");

12,发彩信

Java代码

Uri mmsUri =

Uri.parse("content://media/external/images/media/23");

returnIt = new Intent(Intent.ACTION_SEND);

returnIt.putExtra("sms_body", "shenrenkui");

returnIt.putExtra(Intent.EXTRA_STREAM, mmsUri);

returnIt.setType("image/png");

Uri mmsUri =

Uri.parse("content://media/external/images/media/23");

returnIt = new Intent(Intent.ACTION_SEND);

returnIt.putExtra("sms_body", "shenrenkui");

returnIt.putExtra(Intent.EXTRA_STREAM, mmsUri);

returnIt.setType("image/png");

用获取到的Intent直接调用startActivity(returnIt)就ok了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值