Android 初步之Android组件 Intent
啥是Intent
在一个Android程序中,主要由3种组件(Activity,BroadCast,Service)组成的,这三种组件是独立的,但是它们之间可以相互调用,协调工作。这些组件之间的通信主要是由Intent来完成的。Intent在其中起着一个媒体中介的作用,专门提供组件相互调用的相关信息,实现调用者与被调用者之间的解耦。
Intent负责对应用中一次操作的动作,动作涉及的数据以及附加数据进行描述,Android则根据此Intent的描述负责找到对应的组件,将Intent传递给调用的组件,并完成组件的调用。
Intent对象的组成
- 组件名字 Component:定位合适的目标组件
- 动作 Action:用来标示要广播的事件,动作很大程度上决定了数据和附加信息,就像一个方法名决定了参数和返回值一样,因此应尽可能明确指定动作,同时必须确保动作字符串的唯一性,一般使用java包名。
- 数据 data :数据是作用Intent上的数据的URI和数据的MIME类型,不同的数据具有不同的规范,当匹配一个Intent到一个能够处理数据的组件的时候,明确其数据类型(MIME)和URI很重要。
- 种类 Catoragry :用于作为被执行动作的附加信息
- 附加信息 Extra :传输数据的重要方法
- 标志 Flag :主要用来指示Android程序如何去启动一个活动,例如,活动应该属于哪个任务。和启动后如何对待它,例如它是否属于最近的活动列表。
组件名称
组件名称是可选的,如果设置了,Intent对象传递到指定的类的实例,如果没有设置,Android使用Intent中的其他信息来定位合适的目标组件。组件名字的设置可用如下方法。
动作 标准的Activity动作
在上述两个表中,需要将其转换为对应的字符串信息,比如将ACTION_TIME_TICK转换为android.intent.action.TIME_TICK
除了预定义的动作,我们还可以自定义动作字符串,来启动应用程序中的组件,这些新发明的字符串应该包含一个应用程序包作为前缀,如com.exemple.SHOW_COLOR
数据
种类
附加信息
标志
Intent 作用
Intent用处可归纳如下几点:
- 负责Android设备上安装的任意应用程序组件之间的交互,不管它们是哪个应用程序的一部分都是如此,这就把设备从一个包含相互独立的组件集合的平台变成一个互联的系统。
- 通过定义隐式或者显式的Intent来启动Activity或者Service。
- 用于在系统范围内广播消息,应用程序可以通过注册一个Broadcast Receiver来监听和响应这些广播的Intent,这样就可以基于内部的,系统的或者第三方应用程序的事件创建事件驱动的应用程序。
- Android通过广播Intent来公布系统事件,比如网络状态,电池电量的改变。本地Android应用简单得注册监听特定的广播Intent并作出相应的响应的组件,这样就可以通过监听相同的Intent 的BroadCast Receiver来替换本地提供的应用程序。
使用Intent 启动 Activity
显式启动Activity (条件:目标Activity必须在manifest文件中注册):
Intent intent = new Intent(MainActivity.this,Detail.class);
startActivity(intent);上述代码执行后,新的Acitivity将会被创建,启动和运行,并移动到Activity堆栈的顶部。
隐式启动Activity
隐式启动可以要求系统启动一个可执行给定动作的Activity,而不必知道需要启动哪个应用程序或者Acitivity,这种情况下运行时会自动解析Intent来选择最合适的Activity,如果有多个Acitivity都能够执行指定动作,那么系统将会向用户呈现选项,让用户来选择。
方法一:指定ACTION以及执行当前ACTION所需数据的URI
Intent intent = new Intent(Intent.ACTION_DIAL,Uri.parse(“tel:555-2368”)); |
方法二:使用自定义的Activity来响应当前的隐式Intent
Intent intent = new Intent("com.androidDemo.intent.action.ShowView"); |
在manifest中添加意图过滤器intent-filer
<activity android:name=".BasicViewActivity" android:label="Basic View Tests"> |
- 关闭Activty如果当前的Activity不是主活动,那么执行finish方法后,返回到调用它的那个Activity,否则将返回到主屏幕中。
finish()
关闭Activity还可以使用finishActivity方法实现该方法用来关闭使用startActivityForResult方法启动的Activity。
使用Intent在Activity之间交换数据
Extra作为一个Bundle对象存储在Intent中,用于向Intent附加基本类型值,可以使用putExtra可以添加附加的数据,在目标Activity中使用getExtras方法来取出数据。
下面是使用Intent在Acitivity之间传输数据的代码片段:
发送方:
Intent intent = new Intent(MainActivity.this,RegisterActivity.class); |
接收方:
Intent intent = getIntent(); |
调用另一个Activity并返回结果
通过startAcitivity启动Acitivity,在关闭的时候不会返回任何数据。因此如果需要在调用Acitivity后返回数据则需要使用startActivityForResult来实现,代码块如下:
发送方:
startActivityForResult(intent,request_code); |
接收方:
setResilt(0x717,intent); |
确定Intent能否解析
在使用Intent启动一个Acitivity之前,必须先确定用户设备上安装了能够处理当前请求的应用程序。这个可以通过调用Intent的resolveActivity方法,并向该方法传入Package Manager 进行查询。具体的代码块如下:
PackageManager pm = getPackageManager(); |
使用Intent 启动和绑定 Service
- 启动服务
intent = new Intent(this, EchoService.class);
startService(intent) - 停止服务
intent = new Intent(this, EchoService.class);
stopService(intent); - 绑定服务
intent = new Intent(this, EchoServices.class);
bindService(intent, conn, Context.BIND_AUTO_CREATE); - 解除绑定服务
unbindService(conn);
使用Intent 发送BroadCast Intent
Intent intent = new Intent(Constant.ACTION_NAME);
sendBroadcast(intent);//普通广播
sendOrderedBroadcast(intent, null);//有序广播
sendStickyBroadcast(intent);//粘性广播
意图过滤器 IntentFilter
当在android程序中使用显示意图的时候,意图对象中只用组件名字内容就可以决定那个组件应该获得这个意图,而使用隐式意图的时候android程序必须查找一个最适合的组件去处理意图,该过程是通过比较意图对象内容和意图过滤器来完成的。
如果一个组件没有任何Intent过滤器,它仅仅能接收显示的意图,而声明了意图过滤器的组件可以接收显示和隐式意图。
当一个意图对象的动作,数据(URI和数据类型),种类,这三者都符合一个意图过滤器的时候,才能考虑是否接收意图,而附加信息和标识在解析哪个组件接收意图时不起作用。
意图过滤器的动作匹配
动作测试:
<intent-filter> |
尽管意图对象仅定义一个动作,在意图过滤器中可以列出多个,列表不能为空,即过滤器中必须至少包含一个
规则:
如果Intent Filter 包含了指定的动作,那么就认为动作匹配了,如果检测到没有任何一个动作和Intent指定的动作相匹配,就认为动作匹配失败了。
意图过滤器的种类匹配
种类测试:
<intent-filter> |
在接收隐式意图的Activity必须在过滤器中包含android.catagory.DEFAULT.
Intent Filter 必须包含待解析Intent的所有Category,但是可以包含Intent不包含的其他category。一个没有指定category的Intent Filter只能和没有任何category的Intent相匹配。
意图过滤器的数据匹配
数据测试:
<intent-filter> |
每个标签可以指定URI和数据类型,URI可以分成scheme,host,port,path这几个独立的部分,格式如下
scheme://host:port/path |
例如:content://com.example.project:200/folder/subfolder/etc
其中scheme是content,host是com.example.project,port是200,path是/folder/subfolder/etc,host和port组成了URI授权,如果host没有指定则忽略port。这些属性都是可选的但是相互之间并非完全独立的,如果授权有效,则sheme必须指定,如果path有效,则sheme和授权必须指定。当意图对象中的URI与过滤器中的URI规范相比较的时候,它仅与过滤器中实际提到的URI部分相比较,例如过滤器仅指定了sheme那么所有具有该sheme的URI都能匹配该过滤器,如果过滤器指定了scheme和授权没有指定path那么,不管path如何,具有该sheme授权的URI都能匹配,如果过滤器中指定了sheme,授权和path则仅有具有相同sheme,授权和path的URI能够匹配。然而过滤器中的path中可以包含通配符来允许部分匹配。
(也就是只要Intent的数据是Intent Filter数据集合中的一项就可以通过匹配)mimeType:Intent对象和过滤器都能使用*来包含子类型,例如text/*或者audio/