定义:Intent是一个消息传送对象,可以用它来访问另外一个组件
可以用于以下三个场景:
- startActivity
startActivity()
startActivityForResult()
- startService
Android 5.0以上可以使用JobScheduler启动
所有版本可以使用:
startService();
bindService();
- sendBroadcast
三种调用方法
sendBroadCast()
sendOrderedBroadCast()
sendStickyBroadcast()
Intent 类型
- 显示类型
直接指定调用组件的名字,一般用于自己的APP内部 - 隐式类型
没有指定组件的名字,而是声明一般的action行为,用此方法可以允许调用另外一个APP的组件
启动Service最好使用显示Intent,否则会存在安全风险,因为无法确定service什么时候被调用,而service又是用户感知不到的组件
Android 5.0开始,如果bindService()隐式调用启动service,会抛出异常
Intent的创建
一个Intent对象包含了Android系统应该启动哪个组件的信息
一个Intent可以包含以下信息:
-
componentName
指定需要启动组件的名字
此项是可选的,用来区分显示Intent和隐式Intent。
赋值的方法有以下几种- Intent的构造方法
- setComponent()
- setClass()
- setClassName
-
action
指定Intent要完成的动作,为字符串常量
action可自定义,也可使用系统的,一般自定义的话最好加上自己APP的包名前缀
一些系统标准的Action常量
ACTION_VIEW,startActivity(),唤起系统相册
ACTION_SEND,startActivity(),把一些数据发送给另外的一些APP,如email,社交软件等
ACTION_CALL,startActivity(),唤起打电话界面
不定期补充...
除了Intent定义了Action常量,其他的类也有定义,比如Settings,可以用来跳转到系统指定的设置界面
action赋值的方法有一下几种:- Intent的构造方法
- setAction()
data
根据给定的Uri寻找匹配的目标组件,如果不给定MIME类型,会进行推导,给定MIME类型,则强制使用此类型。
不同的Action有对应的data数据指定。
其中data的值设置为setData(),MIME的设置为setType()
常用值如下所示:
tel://: 号码数据格式,后跟电话号码。
mailto://: 邮件数据格式,后跟邮件收件人地址。
smsto://: 短息数据格式,后跟短信接收号码。
content://: 内容数据格式,后跟需要读取的内容。
file://: 文件数据格式,后跟文件路径。
geo:// latitude, longitude:经纬数据格式,在地图上显示经纬度所指定的位置。
Uri指定数据指向那种数据格式,MIME指定数据具体的类型。比如Image和Audio有同样的Uri,但是MIME的类型是不同的。
setData()和setType()会互相覆盖,所以当需要同时设置Uri和MIME时,为了避免这种情况,可以调用setDataAndType()
- category
执行Action的附加信息。可以放置很多category,但是大多数intent是不需要category的
常用值如下:
CATEGORY_DEFAULT:Android系统中默认的执行方式,按照普通Activity的执行方式执行。
CATEGORY_HOME:设置该组件为Home Activity。
CATEGORY_PREFERENCE:设置该组件为Preference。
CATEGORY_LAUNCHER:设置该组件为在当前应用程序启动器中优先级最高的Activity,通常为入口ACTION_MAIN配合使用。
CATEGORY_BROWSABLE:设置该组件可以使用浏览器启动。
CATEGORY_GADGET:设置该组件可以内嵌到另外的Activity中。
通过addCategory()指定 - extras
用来存放需要传递的数据,以键值对的形式进行存储和访问
通过putExtras()方法设置 - flags
设置Activity的启动模式,例如:
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_NO_HISTORY
FLAG_ACTIVITY_SINGLE_TOP
具体的笔记放到Activity上
通过setFlags()方法设置
显示Intent的例子
Intent downloadIntent = new Intent(this, DownloadService.class);
downloadIntent.setData(Uri.parse(fileUrl));
startService(downloadIntent);
隐式Intent的例子
其中resolveActivity()用来判断Intent是否能够被解析,防止APP崩溃
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");
//Intent chooser = Intent.createChooser(sendIntent, title);//强制使用选择器
//if (sendIntent.resolveActivity(getPackageManager()) != null) {
// startActivity(chooser);
//}
// Verify that the intent will resolve to an activity
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(sendIntent);
}
接收一个隐式Intent
需要在manifest文件中配置
MIME类型 application/vnd.google.panorama360+jpg为指定的全景照片数据类型
使用PendingIntent
PendingIntent是对Intent的包装,使外部的APP能够像在内部APP那样对所包含的Intent进行使用
主要有如下的使用场景:
- Notification
- App Widget
- AlarmManager
取得实例的方法如下:
PendingIntent.getActivity(),启动Activity
PendingIntent.getService(),启动Service
PendingIntent.getBroadcast(),启动BroadcastReceiver
状态栏通知:
int icon = android.R.drawable.my_icon;
long when = System.currentTimeMillis();//通知发生的时间为系统当前时间
Notification notification = new Notification(icon, null, when);//新建一个通知,第一个参数为图标,第二个参数为短暂提示标题,第三个为通知时间
notification.defaults = Notification.DEFAULT_SOUND;//发出默认声音
notification.flags |= Notification.FLAG_AUTO_CANCEL;//点击通知后自动清除通知
Intent openintent = new Intent(this, OtherActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, openintent, 0);//当点击消息时就会向系统发送openintent意图
notification.setLatestEventInfo(this, "标题", "内容", contentIntent);//setLatestEventInfo表示设置点击该通知的事件
int notifyCode = 0;
//获取通知管理器
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(notifyCode , notification);//第一个参数为自定义的通知唯一标识
action匹配规则
如果intent-filter设置了action的过滤规则,比如下面的XML代码,
...
那么:
- intent不设置action,则直接不通过
- intent设置了多个Action,则只要有一个匹配上,则可以通过
//不通过
Intent intent = new Intent();
//通过
intent.setAction("android.intent.action.EDIT");
//通过
intent.setAction("android.intent.action.EDIT");
intent.setAction("android.intent.action.test");
Category匹配规则
如果intent-filter设置了category的过滤规则,如下面的XML代码,
...
那么:
- Intent不设置category,则都通过,不论intent-filter设置多少category
- intent设置了category,intent上的category能够匹配上intent-filter设置的category,才能够通过
比如:
//通过
Intent intent = new Intent();
//通过
intent.addCategory("android.intent.category.DEFAULT"),可以匹配上
//通过
intent.addCategory("android.intent.category.BROWSABLE")
//不通过
intent.addCategory("android.intent.category.DEFAULT")
intent.addCategory("android.intent.category.test")
Data匹配规则
intent-filter中的结构由Uri和MIME Type组成
Uri包括如下几部分:
scheme:整个Uri的模式,如http,ftp,content等
如果scheme未指定,则忽略host
如果只指定scheme,则所有和intent-filter相同的scheme都匹配host:Uri的域名,如www.google.com
如果host未指定,则忽略portport:Uri的端口
path:包含的路径信息,如:folder/subfolder/etc
如果scheme,host都未指定,则忽略path
整体组成:
MIME Type:表示image/ipeg,video/*等媒体类型
匹配规则如下:
intent中的data必须和intent-filter完全匹配才能通过。有如下几种情况:
a.intent没有设置Uri和MIME Type,同时intent-filter也没有设置
b.intent只包含Uri,但未包含MIME Type,同时能够匹配上intent-filter设置的Uri,并且intent-filter为设置MIME Type
c.intent只设置MIME Type,同时intent-filter也设置了相同的MIME Type并且未指定Uri
d.intent设置了Uri和MIME Type,intent-filter只设置了MIME Type,则intent的Uri的scheme必须为content:或是file:。即,intent-filter如果没有设置Uri,只设置了MIME Type,则Uri为content:或file:的模式。也就是说,过滤的规则希望组件能够从文件(file)或内容提供者(content provider)获取到本地数据。
规则d例子,从相册获取图片:
...
则intent的匹配规则为:
Intent intent = new Intent();
intent.setDataAndType(Uri.parse("file://test"), "image/*");
startActivity(intent);
如果intent-filter设置了多个data,则intent中的data只要和其中一个匹配就可以通过
为了防止APP崩溃,所有的intent匹配规则进行调用前都要进行判断处理:
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(intent);
}
本知识点完~