Intent是抽象的数据结构,包含了一系列描述某个操作的数据,使得程序在运行时可以在程序中不同组件间通信或启动
不同的应用程序。可以通过startActivity(Intent)启动一个Activity, sendBroadcast(Intent) 发送广播发送给感兴
趣的BroadcastReceiver组件, startService(Intent)启动service,bindService(Intent, ServiceConnection, int)绑定服务。
Intent Filter顾名思义就是Intent的过滤器,组件通过定义Intent Filter可以决定哪些隐式Intent可以和该组件进行通讯。
关于隐式Intent的定义后面会进行介绍,Intent Filter对显式的Intent不起作用。
Action就是个String类型的字符串,在隐式Intent中用来和filter进行匹配的关键指标,如ACTION_VIEW,ACTION_EDIT等,Intent内置了很多Action常量
,我们也可以自定义私有Action方便自己进行匹配。
Data为Uri类型的数据,若mType为空通过对mData的解析可以得到数据的类型。
Component表示组件信息,包含context和目标组件的class信息,设置了即为显示Intent。
Category作为决定哪个组件处理Intent的附属信息,一个Intent可以添加或删除多个Category存储在mCategories。
Flag用于标记如何启动一个活动,是NEW_TASK还是其他等等,以及启动后怎么对待这个活动。
Extras为附加信息,会传递给目标组件,比如发送邮件,Extras可以存储邮件收件人地址、内容、主题、附件等信息。
因为Intent Filter和Intent的匹配只有三个字段起作用,所以Intent Filter只包含Actions、Datas、Categorys三个属性(实际源码中会将Data划分为多个部分),
属性的意义和Intent相同。不同的是Intent Filter可以包含多个Action、多个Data、多个Category,而Intent除Category可以有多个外,只能有一个Action
对于一个定义好的Intent,Android如何判断和哪个目标组件通讯呢。Intent分为隐式(implicit)Intent和显式(explicit)Intent。
显式Intent通常用于在程序内部组件间通信,已经明确的定义目标组件的信息,所以不需要系统决策哪个目标组件处理Intent,如下
Intent intent = new Intent(DemoList.this, GoogleMapDemo.class);
startActivity(intent);
其中DemoList和GoogleMapDemo都是用户自定义的组件,
隐式Intent不指明目标组件的class,只定义希望的Action及Data等相关信息,由系统决定使用哪个目标组件。如发送短信
Uri uri = Uri.parse("smsto:15800000000");
Intent i = new Intent(Intent.ACTION_SENDTO, uri);
i.putExtra("sms_body", "The SMS text");
startActivity(i);
Android系统通过对Intent和目标组件在AndroidManifest文件中定义的<intent-filter>(也可以在程序中定义Intent Filter)进行匹配决定和哪个目标组件通讯。
如果某组件未定义<intent-filter>则只能通过显式的Intent进行通信。Intent的三个属性用于对目标组件选取的决策,分别是Action、Data(Uri和Data Type)、Category
。匹配规则如下
a. Intent定义的Action必须包含在<intent-filter>的Action列表中,若隐式Intent未定义Action系统会报错。由此可知一个<intent-filter>至少包含一个Action。
b. 未定义Uri和Type的Intent仅可以通过不包含包含Uri和Type的filter;包含了Uri,不包含Type的Intent仅可以通过包含匹配Uri不包含Type的filter;包含了Type不
包含Uri的Intent仅可以通过包含了相同Type不包含Uri的filter;同时包含了Uri和Type的Intent仅可以通过相同Type匹配Uri(或不包含Uri但Intent Uri为content:或file:)
的filter。
c. Intent若定义了Category(可多个),则所有Category必需包含在<intent-filter>的Category列表中。若Intent未定义Category,则<intent-filter>是否定义Category
不影响。
PS:<intent-filter>必须包含<category android:name="android.intent.category.DEFAULT" />才能通过startActivity启动,所以Activity的<intent-filter>至少包含一
个category,Service和BroadcastReceiver不必。
目标组件必须包含同时满足以上规则的<intent-filter>才能进行匹配。若有多个目标组件同时可以匹配,则系统会提示用户进行选择,若没有目标组件可以匹配系统会进行提示。
a. 发送短信
Uri uri = Uri.parse("smsto:15800000000");
Intent i = new Intent(Intent.ACTION_SENDTO, uri);
i.putExtra("sms_body", "The SMS text");
startActivity(i);
b. 打电话
Uri dial = Uri.parse("tel:15800000000");
Intent i = new Intent(Intent.ACTION_DIAL, dial);//"android.intent.action.CALL"
startActivity(i);
c. 发送邮件
Uri email = Uri.parse("mailto:[email protected];[email protected]");
Intent i = new Intent(Intent.ACTION_SENDTO, email);
startActivity(i);
或
Intent i = new Intent(Intent.ACTION_SEND);
String[] tos = {"[email protected]"};
String[] ccs = {"[email protected]"};
i.putExtra(Intent.EXTRA_EMAIL, tos);
i.putExtra(Intent.EXTRA_CC, ccs);
i.putExtra(Intent.EXTRA_SUBJECT, "主题");
i.putExtra(Intent.EXTRA_TEXT, "正文");
i.setType("message/rfc822");
startActivity(i);
d. 拍照
Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String folderPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "AndroidDemo" + File.separator;
String filePath = folderPath + System.currentTimeMillis() + ".jpg";
new File(folderPath).mkdirs();
File camerFile = new File(filePath);
i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(camerFile));
startActivityForResult(i, 1);
e. 浏览网页
Uri web = Uri.parse("http://www.google.com");
Intent i = new Intent(Intent.ACTION_VIEW, web);
startActivity(i);
f. 查看联系人
Intent i = new Intent();
i.setAction(Intent.ACTION_GET_CONTENT);
i.setType("vnd.android.cursor.item/phone");
startActivityForResult(i, 1);