Android组件通信之Intent完全解析
Posted 痕迹天涯119
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android组件通信之Intent完全解析相关的知识,希望对你有一定的参考价值。
Intent作为android中的信使,被广泛应用于组件间的信息传递,我也曾经写过关于intent的学习笔记,但限于水平,广度和深度实在过于欠缺,这里重新总结整理以备后用。
Intent简介
Intent是一种运行时绑定机制,它能在程序运行过程中连接两个不同的组件。通过Intent,你的程序可以向Android表达某种请求或者意愿,Android会根据意愿的内容选择适当的组件来完成请求。
Intent的构成
action
action是一个字符串,系统预定义了一些action,用来指明要实施的动作是什么,比如说ACTION_VIEW, ACTION_EDIT等,当然我们也可以自定义自己的action
常用action示例:
a. 发送短信
Uri uri = Uri.parse("smsto:15800000000");
Intent i=newIntent(Intent.ACTION_SENDTO, uri);
i.putExtra("sms_body", "The SMS text");
startActivity(i);
b. 打电话
Uri dial = Uri.parse("tel:15800000000");
Intent i=newIntent(Intent.ACTION_DIAL, dial);
startActivity(i);
c. 发送邮件
Uri email = Uri.parse("mailto:abc@126.com;def@126.com");
Intent i=newIntent(Intent.ACTION_SENDTO, email);
startActivity(i);
d. 拍照
Intent i =newIntent(MediaStore.ACTION_IMAGE_CAPTURE);
String folderPath= Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "AndroidDemo" +File.separator;
String filePath= folderPath + System.currentTimeMillis() + ".jpg";newFile(folderPath).mkdirs();
File camerFile=newFile(filePath);
i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(camerFile));
startActivityForResult(i,1);
e. 浏览网页
Uri web = Uri.parse("http://www.google.com");
Intent i=newIntent(Intent.ACTION_VIEW, web);
startActivity(i);
f. 查看联系人
Intent i =newIntent();
i.setAction(Intent.ACTION_GET_CONTENT);
i.setType("vnd.android.cursor.item/phone");
startActivityForResult(i,1);
系统预设了很多action,详情点击:官方Action大全和一些常用Action总结
data
要实施操作的数据,常为一个路径或Uri等
data由两部分组成:mimeType和URI ,这里举一个与浏览器交互的例子
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
mineType指的是媒体类型:例如imgage/jpeg,auto/mpeg4和viedo/*等,可以表示图片、文本、视频等不同的媒体格式
uri组成如下
<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern >]
Scheme:URI的模式,如http、file、content等,若没有指定Scheme则URI其他属性无效
Host:URI主机名,如www.baidu.com,未指定同上
Port:URI端口号,依存于Scheme和Host
Path:完整路径信息
PathPattern:可包含通配符的完整路径,
PathPrefix:路径前缀信息
注意:若Intent Filter的data声明部分未指定uri,则缺省uri为content或file,Intent中的uri的scheme部分需为content或file才能匹配;若要为Intent指定完整的data,必须用setDataAndType方法,究其原因在,setData和setType方法的源码中我们发现:
public Intent setData(Uri data)
mData = data;
mType = null;
return this;
public Intent setType(String type)
mData = null;
mType = type;
return this;
category
category是一个字符串,系统预定义了一些category,同时也可以在应用中定义自己的category。
intent有如下常用方法处理category
addCategory()
: 为一个intent对象增加一个category,
removeCategory
: 删除一个category,
getCategories()
: 获取intent所有的category.
component
目标组件,当Intent中指定目标组件时,将直接显式启动。
如下:
Intent intent = new Intent();
intent.setComponent(new ComponentName(MainActivity.this,SecondActivity.class));
startActivity(intent);
其简写形式为
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
so,很多时候直接在new Intent的时候填入component组件即可。
extras
附加信息,一般为键对值或Bundle对象,
intent.putExtra()该方法被重载多次,第一个参数为String类型(键),第二个参数几乎可以为任意的基本类型、数组以及Bundle(值);
getIntent().getXXXExtra(“键值”)用于取出对应键对应的值,
经测试,intent.putExtra()完全是可以存取多个的
intent.putExtras()可直接传入Bundle对象,无需键值;
getIntent().getExtras()用于取出Bundle对象
Intent使用分类
Intent主要有显式Intent和隐式Intent,显示Intent主要根据设定有目标的进行调用,而隐式Intent则根据IntentFilter中设定的匹配规则筛选调用。
显式Intent
指明要启动的组件即可,此时不会进行过滤
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
隐式Intent
依据匹配规则匹配,匹配成功后选择可启动组件进行启动
IntentFilter的匹配规则
Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有Intent及其中定义的IntentFilter,最终找到匹配的Intent。
在这个解析过程中,Android是通过IntentFilter的action、data、category这三个属性来进行匹配判断的。一个匹配列表中可以有多个action、data、category,一个Intent只有匹配列表中的任意一组action、data、category属性才能成功启动Activity。此外,一个Activity中可以有多个Intent-filter,而Intent只需要匹配一个IntentFilter的一组属性即可成功启动Activity。
action匹配规则
Intent中的action至少能和过滤规则中的任意一个action匹配才能启动,此外,action区分大小写。
category匹配规则
category与action不同,Intent存在一个默认的category,即category,android.intent.category.DEAFAULT
,(仍需要在intentFilter中指明)若Intent没有设置,则必定匹配成功,若Intent设置了category,那么只要有一个category匹配其他的都必须匹配才能启动,否则匹配失败。
下面是常见的category
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
其中action表明该Activity是最先启动的,而category则指明该Activity会显示在主程序列表中,二者共同出现缺一不可。
android.intent.action.MAIN 与android.intent.category.LAUNCHER的区别
区别一:
android.intent.action.MAIN决定一个应用程序最先启动那个组件
android.intent.category.LAUNCHER决定应用程序是否显示在程序列表里(说白了就是是否在桌面上显示一个图标)
这两个属性组合情况:
第一种情况:有MAIN,无LAUNCHER,程序列表中无图标
原因:android.intent.category.LAUNCHER决定应用程序是否显示在程序列表里
第二种情况:无MAIN,有LAUNCHER,程序列表中无图标
原因:android.intent.action.MAIN决定应用程序最先启动的Activity,如果没有Main,则不知启动哪个Activity,故也不会有图标出现
所以这两个属性一般成对出现。
如果一个应用中有两个组件intent-filter都添加了android.intent.action.MAIN和
android.intent.category.LAUNCHER这两个属性, 则这个应用将会显示两个图标, 写在前面的组件先运行。
区别二:
android.intent.category.LAUNCHER:android.intent.category.LAUNCHER决定应用程序是否显示在程序列表里,就是android开机后的主程序列表。
android.intent.category.HOME:按住“HOME”键,该程序显示在HOME列表里。
data的匹配规则
如果Intent没有提供type,系统将从data中得到数据类型。和action一样,只要Intent的data只要与Intent Filter中的任一个data声明完全相同,data方面就完全匹配成功。
前面已经说的很详细了,这里再来看一下Intent Filter中指定data的语法:
<data android:scheme="String.“
android:host="String"
android:port="String"
android:path="String"
android:pathPattern="String"
android:pathPrefix="String"
android:mimeType="String"/>
这里各个属性无需全部指定
查询是否有Activity可以匹配我们指定Intent的组件
采用PackageManager的resolveActivity或者Intent的resolveActivity方法会获得最适合Intent的一个Activity
调用PackageManager的queryIntentActivities会返回所有成功匹配Intent的Activity
intent.resolveActivity(getPackageManager());
getPackageManager().resolveActivity(intent,PackageManager.MATCH_DEFAULT_ONLY); getPackageManager().queryIntentActivities(intent,PackageManager.MATCH_DEFAULT_ONLY);
BroadcastReceiver和Service获取成功匹配的组建信息与Activity的方法是类似的
其中,第二个参数flags我们一般使PackageManager.MATCH_DEFAULT_ONLY
,为什么要指定该值呢?
其实我们在category的匹配规则中提到过,若Intent匹配过滤规则中的一个category,那么其他的category也都需要匹配,而Intent默认带有一个android.intent.category.DEFAULT
的category,所以intentFilter中的category若存在属性但没有android.intent.category.DEFAULT
属性将会匹配失败,所以我们设置仅匹配带有android.intent.category.DEFAULT
属性category的组件。
intent-filter匹配优先级
action->data->category
参考文章:
http://blog.csdn.net/t12x3456/article/details/7688154
http://blog.csdn.net/mynameishuangshuai/article/details/51673273
以上是关于Android组件通信之Intent完全解析的主要内容,如果未能解决你的问题,请参考以下文章