Intent(意图)主要是解决Android应用的各项组件之间的通讯。
Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,
将Intent传递给调用的组件,并完成组件的调用。
因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的解耦。
例如,在一个联系人维护的应用中,当我们在一个联系人列表屏幕(假设对应的Activity为listActivity)上,
点击某个联系人后,希望能够跳出此联系人的详细信息屏幕(假设对应的Activity为detailActivity)
为了实现这个目的,listActivity需要构造一个Intent,这个Intent用于告诉系统,我们要做"查看"动作,
此动作对应的查看对象是"某联系人",然后调用startActivity(Intentintent),将构造的Intent传入,
系统会根据此Intent中的描述,到ManiFest中找到满足此Intent要求的Activity,系统会调用找到的Activity,
即为detailActivity,最终传入Intent,detailActivity则会根据此Intent中的描述,执行相应的操作。
一、抽象描述要描述什么
在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_ACTIONcontent://contacts/1--显示标识符为"1"的联系人的详细信息
EDIT_ACTIONcontent://contacts/1--编辑标识符为"1"的联系人的详细信息
VIEW_ACTIONcontent://contacts/--显示所有联系人的列表
PICK_ACTIONcontent://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)来指定)。
通过指定具体的组件类,通知应用启动对应的组件。
间接Intent:没有指定component属性的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,解析得到的目标组件必须至少包含这两个类别。
折叠编辑本段三、Intent的显示调用和隐式调用
显式Intent直接用组件的名称定义目标组件,这种方式很直接。但是由于开发人员往往并不清楚别的应用程序的组件名称,
因此,显示Intent更多用于在应用程序内部传递消息。比如在某应用程序内,一个Activity启动一个Service。
隐式Intent恰恰相反,它不会用组件名称定义需要激活的目标组件,它更广泛地用于在不同应用程序之间传递消息。
在显示Intent消息中,决定目标组件的唯一要素就是组件名称,因此,如果你的Intent中已经明确定义了目标组件的名称,
那么你就完全不用再定义其他Intent内容。
而对于隐式Intent则不同,由于没有明确的目标组件名称,所以必须由Android系统帮助应用程序寻找与Intent请求意图
最匹配的组件。
(Intent定义:Intent是一种在不同组件之间传递的请求消息,是应用程序发出的请求和意图。作为一个完整的消息传递机制,
Intent不仅需要发送端,还需要接收端。
显式Intent定义:对于明确指出了目标组件名称的Intent,我们称之为显式Intent。
隐式Intent定义:对于没有明确指出目标组件名称的Intent,则称之为隐式Intent。
说明:Android系统使用IntentFilter来寻找与隐式Intent相关的对象。
显式Intent直接用组件的名称定义目标组件,这种方式很直接。但是由于开发人员往往并不清楚别的应用程序的组件名称,
因此,显示Intent更多用于在应用程序内部传递消息。比如在某应用程序内,一个Activity启动一个Service。
隐式Intent恰恰相反,它不会用组件名称定义需要激活的目标组件,它更广泛地用于在不同应用程序之间传递消息。
在显式Intent消息中,决定目标组件的唯一要素就是组件名称,因此,如果你的Intent中已经明确定义了目标组件的名称,
那么你就完全不用再定义其他Intent内容。
而对于隐式Intent则不同,由于没有明确的目标组件名称,所以必须由Android系统帮助应用程序寻找与Intent请求意图最
匹配的组件。
Android系统寻找与Intent请求意图最匹配的组件具体的选择方法是:Android将Intent的请求内容和一个叫做IntentFilter
的过滤器比较,IntentFilter中包含系统中所有可能的待选组件。
如果IntentFilter中某一组件匹配隐式Intent请求的内容,那么Android就选择该组件作为该隐式Intent的目标组件。
Android如何知道应用程序能够处理某种类型的Intent请求呢?这需要应用程序在Android-Manifest.xml中声明自己所含组件
的过滤器(即可以匹配哪些Intent请求)。
一个没有声明Intent-Filter的组件只能响应指明自己名字的显示Intent请求,而无法响应隐式Intent请求。
而一个声明了IntentFilter的组件既可以响应显示Intent请求,也可以响应隐式Intent请求。在通过和IntentFilter比较来
解析隐式Intent请求时,Android将以下三个因素作为选择的参考标准:
Action
Data
Category
而Extra和Flag在解析收到Intent时是并不起作用的。
文档1:
[代码]调用拨号程序
1//给移动客服10086拨打电话
2Uriuri=Uri.parse("tel:10086");
3Intentintent=newIntent(Intent.ACTION_DIAL,uri);
4startActivity(intent);
[代码]发送短信或彩信
01//给10086发送内容为“Hello”的短信
02Uriuri=Uri.parse("smsto:10086");
03Intentintent=newIntent(Intent.ACTION_SENDTO,uri);
04intent.putExtra("sms_body","Hello");
05startActivity(intent);
06//发送彩信(相当于发送带附件的短信)
07Intentintent=newIntent(Intent.ACTION_SEND);
08intent.putExtra("sms_body","Hello");
09Uriuri=Uri.parse("content://media/external/images/media/23");
10intent.putExtra(Intent.EXTRA_STREAM,uri);
11intent.setType("image/png");
12startActivity(intent);[代码]通过浏览器打开网页
1//打开Google主页
2Uriuri=Uri.parse("http://www.google.com");
3Intentintent=newIntent(Intent.ACTION_VIEW,uri);
4startActivity(intent);[代码]发送电子邮件
01//给someone@domain.com发邮件
02Uriuri=Uri.parse("mailto:someone@domain.com");
03Intentintent=newIntent(Intent.ACTION_SENDTO,uri);
04startActivity(intent);
05//给someone@domain.com发邮件发送内容为“Hello”的邮件
06Intentintent=newIntent(Intent.ACTION_SEND);
07intent.putExtra(Intent.EXTRA_EMAIL,"someone@domain.com");
08intent.putExtra(Intent.EXTRA_SUBJECT,"Subject");
09intent.putExtra(Intent.EXTRA_TEXT,"Hello");
10intent.setType("text/plain");
11startActivity(intent);
12//给多人发邮件
13Intentintent=newIntent(Intent.ACTION_SEND);
14String[]tos={"1@abc.com","2@abc.com"};//收件人
15String[]ccs={"3@abc.com","4@abc.com"};//抄送
16String[]bccs={"5@abc.com","6@abc.com"};//密送
17intent.putExtra(Intent.EXTRA_EMAIL,tos);
18intent.putExtra(Intent.EXTRA_CC,ccs);
19intent.putExtra(Intent.EXTRA_BCC,bccs);
20intent.putExtra(Intent.EXTRA_SUBJECT,"Subject");
21intent.putExtra(Intent.EXTRA_TEXT,"Hello");
22intent.setType("message/rfc822");
23startActivity(intent);[代码]显示地图与路径规划
1//打开Google地图中国北京位置(北纬39.9,东经116.3)
2Uriuri=Uri.parse("geo:39.9,116.3");
3Intentintent=newIntent(Intent.ACTION_VIEW,uri);
4startActivity(intent);
5//路径规划:从北京某地(北纬39.9,东经116.3)到上海某地(北纬31.2,东经121.4)
6Uriuri=Uri.parse("http://maps.google.com/maps?f=d&saddr=39.9116.3&daddr=31.2121.4");
7Intentintent=newIntent(Intent.ACTION_VIEW,uri);
8startActivity(intent);[代码]播放多媒体
1Intentintent=newIntent(Intent.ACTION_VIEW);
2Uriuri=Uri.parse("file:///sdcard/foo.mp3");
3intent.setDataAndType(uri,"audio/mp3");
4startActivity(intent);
5Uriuri=
6Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI,"1");
7Intentintent=newIntent(Intent.ACTION_VIEW,uri);
8startActivity(intent);[代码]拍照
1//打开拍照程序
2Intentintent=newIntent(MediaStore.ACTION_IMAGE_CAPTURE);
3startActivityForResult(intent,0);
4//取出照片数据
5Bundleextras=intent.getExtras();
6Bitmapbitmap=(Bitmap)extras.get("data");[代码]获取并剪切图片
01//获取并剪切图片
02Intentintent=newIntent(Intent.ACTION_GET_CONTENT);
03intent.setType("image/");
04intent.putExtra("crop","true");//开启剪切
05intent.putExtra("aspectX",1);//剪切的宽高比为1:2
06intent.putExtra("aspectY",2);
07intent.putExtra("outputX",20);//保存图片的宽和高
08intent.putExtra("outputY",40);
09intent.putExtra("output",Uri.fromFile(newFile("/mnt/sdcard/temp")));//保存路径
10intent.putExtra("outputFormat","JPEG");//返回格式
11startActivityForResult(intent,0);
12//剪切特定图片
13Intentintent=newIntent("com.android.camera.action.CROP");
14intent.setClassName("com.android.camera","com.android.camera.CropImage");
15intent.setData(Uri.fromFile(newFile("/mnt/sdcard/temp")));
16intent.putExtra("outputX",1);//剪切的宽高比为1:2
17intent.putExtra("outputY",2);
18intent.putExtra("aspectX",20);//保存图片的宽和高
19intent.putExtra("aspectY",40);
20intent.putExtra("scale",true);
21intent.putExtra("noFaceDetection",true);
22intent.putExtra("output",Uri.parse("file:///mnt/sdcard/temp"));
23startActivityForResult(intent,0);
[代码]打开GoogleMarket
1//打开GoogleMarket直接进入该程序的详细页面
2Uriuri=Uri.parse("market://details?id="+"com.demo.app");
3Intentintent=newIntent(Intent.ACTION_VIEW,uri);
4startActivity(intent);
[代码]安装和卸载程序
1Uriuri=Uri.fromParts("package","com.demo.app",null);
2Intentintent=newIntent(Intent.ACTION_DELETE,uri);
3startActivity(intent);
[代码]进入设置界面viewsourceprint?
1//进入无线网络设置界面(其它可以举一反三)
2Intentintent=newIntent(android.provider.Settings.ACTION_WIRELESS_SETTINGS);
3startActivityForResult(intent,0);
文档2:
1.从google搜索内容
Intentintent=newIntent();
intent.setAction(Intent.ACTION_WEB_SEARCH);
intent.putExtra(SearchManager.QUERY,"searchString")
startActivity(intent);
2.浏览网页
Uriuri=Uri.parse("http://www.google.com");
Intentit=newIntent(Intent.ACTION_VIEW,uri);
startActivity(it);
3.显示地图
Uriuri=Uri.parse("geo:38.899533,-77.036476");
Intentit=newIntent(Intent.Action_VIEW,uri);
startActivity(it);
4.路径规划
Uriuri=Uri.parse("http://maps.google.com/maps?f=dsaddr=startLat%20startLng&daddr=endLat%20endLng&hl=en");
Intentit=newIntent(Intent.ACTION_VIEW,URI);
startActivity(it);
5.拨打电话
Uriuri=Uri.parse("tel:xxxxxx");
Intentit=newIntent(Intent.ACTION_DIAL,uri);
startActivity(it);
6.调用发短信的程序
Intentit=newIntent(Intent.ACTION_VIEW);
it.putExtra("sms_body","TheSMStext");
it.setType("vnd.android-dir/mms-sms");
startActivity(it);
7.发送短信
Uriuri=Uri.parse("smsto:0800000123");
Intentit=newIntent(Intent.ACTION_SENDTO,uri);
it.putExtra("sms_body","TheSMStext");
startActivity(it);
Stringbody="thisissmsdemo";
Intentmmsintent=newIntent(Intent.ACTION_SENDTO,Uri.fromParts("smsto",number,null));
mmsintent.putExtra(Messaging.KEY_ACTION_SENDTO_MESSAGE_BODY,body);
mmsintent.putExtra(Messaging.KEY_ACTION_SENDTO_COMPOSE_MODE,true);
mmsintent.putExtra(Messaging.KEY_ACTION_SENDTO_EXIT_ON_SENT,true);
startActivity(mmsintent);
8.发送彩信
Uriuri=Uri.parse("content://media/external/images/media/23");
Intentit=newIntent(Intent.ACTION_SEND);
it.putExtra("sms_body","sometext");
it.putExtra(Intent.EXTRA_STREAM,uri);
it.setType("image/png");
startActivity(it);
StringBuildersb=newStringBuilder();
sb.append("file://");
sb.append(fd.getAbsoluteFile());
Intentintent=newIntent(Intent.ACTION_SENDTO,Uri.fromParts("mmsto",number,null));
//Belowextradatasarealloptional.
intent.putExtra(Messaging.KEY_ACTION_SENDTO_MESSAGE_SUBJECT,subject);
intent.putExtra(Messaging.KEY_ACTION_SENDTO_MESSAGE_BODY,body);
intent.putExtra(Messaging.KEY_ACTION_SENDTO_CONTENT_URI,sb.toString());
intent.putExtra(Messaging.KEY_ACTION_SENDTO_COMPOSE_MODE,composeMode);
intent.putExtra(Messaging.KEY_ACTION_SENDTO_EXIT_ON_SENT,exitOnSent);
startActivity(intent);
9.发送Email
Uriuri=Uri.parse("mailto:xxx@abc.com");
Intentit=newIntent(Intent.ACTION_SENDTO,uri);
startActivity(it);
Intentit=newIntent(Intent.ACTION_SEND);
it.putExtra(Intent.EXTRA_EMAIL,"me@abc.com");
刚才找appid未果,结果发现用packagename也可以
Uriuri=Uri.parse("market://details?id=");
这个简单多了17寻找应用
Uriuri=Uri.parse("market://search?q=pname:pkg_name");
Intentit=newIntent(Intent.ACTION_VIEW,uri);
startActivity(it);
//wherepkg_nameisthefullpackagepathforanapplication
18打开联系人列表
<1>
Intenti=newIntent();
i.setAction(Intent.ACTION_GET_CONTENT);
i.setType("vnd.android.cursor.item/phone");
startActivityForResult(i,REQUEST_TEXT);
<2>
Uriuri=Uri.parse("content://contacts/people");
Intentit=newIntent(Intent.ACTION_PICK,uri);
startActivityForResult(it,REQUEST_TEXT); |
|