Androi之Intent分析
Androi之Intent分析
飞上北极星 发表于7个月前
Androi之Intent分析
  • 发表于 7个月前
  • 阅读 2
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 技术升级10大核心产品年终让利>>>   

AndroidIntent分析

什么是Intent

在一个Android应用中,主要是由四种组件组成(Activities, Services, Broadcast receivers,Content providers),而这四种组件是独立的,它们之间可以互相调用,协调工作,最终组成一个真正的Android应用。在这些组件之间的通讯,主要是由Intent协助完成的。如果我们把Activity比作积木的话,那么Intent就是胶水,把不同的积木粘起来,构成我们搭建的房子(应用)。
Intent
负责对应用中一次操作的动作动作涉及数据进行描述,Android则根据此Intent的描述,负责找到对应的组件,将Intent传递给调用的组件,并完成组件的调用。因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的解耦控制。

Intent是一种运行时绑定(run-time binding)机制,它能在程序运行过程中连接两个不同的组件。通过Intent,你的程序可以向Android表达某种请求或者意愿,Android会根据意愿的内容选择适当的组件来完成请求。比如,有一个Activity希望打开网页浏览器查看某一网页的内容,那么这个Activity只需要发出WEB_SEARCH_ACTION给Android,Android就会根据Intent的请求内容,查询各组件注册时声明的IntentFilter,找到网页浏览器的Activity来浏览网页。

Android的三个基本组件——Activity,Service和Broadcast Receiver——都是通过Intent机制激活的(这里的第四组件contentprovider有所区别)。

不同类型的组件有不同的传递Intent方式:

1.1要激活一个新的Activity,或者让一个现有的Activity做新的操作,可以通过调用Context.startActivity()或者Activity.startActivityForResult()方法。

1.2 要启动一个新的Service,或者向一个已有的Service传递新的指令,调用Context.startService()方法或者调用Context.bindService()方法将调用此方法的上下文对象与Service绑定。

1.3 Context.sendBroadcast()、Context.sendOrderBroadcast()、Context.sendStickBroadcast()这三个方法可以发送Broadcast Intent。发送之后,所有已注册的并且拥有与之相匹配IntentFilter的BroadcastReceiver就会被激活。

Intent一旦发出,Android都会准确找到相匹配的一个或多个Activity,Service或者BroadcastReceiver作响应。所以,不同类型的Intent消息不会出现重叠即Broadcast的Intent消息只会发送给BroadcastReceiver,而决不会发送给Activity或者Service。由startActivity()传递的消息也只会发给Activity,由startService()传递的Intent只会发送给Service。这样就在启动发送intent的时候区分开来了intent将要发送到的地点。

Intent的构成

要在不同的activity之间传递数据,就要在intent中包含相应的内容,一般来说数据中最基本的应该包括:
Action用来指明要实施的动作是什么,比如说ACTION_VIEW, ACTION_EDIT等。具体的可以查阅android SDK-> reference中的Android.content.intent类,里面的constants中定义了所有的action。

一些常用的Action:
ACTION_CALL activity 启动一个电话
.
ACTION_EDIT activity 显示用户编辑的数据
.
ACTION_MAIN activity 作为Task中第一个Activity启动

ACTION_SYNC activity 同步手机与数据服务器上的数据.
ACTION_BATTERY_LOW broadcast receiver 电池电量过低警告
.
ACTION_HEADSET_PLUG broadcast receiver 插拔耳机警告

ACTION_SCREEN_ON broadcast receiver 屏幕变亮警告.
ACTION_TIMEZONE_CHANGED broadcast receiver 改变时区警告.

Data: 要事实的具体的数据,一般由一个Uri变量来表示

Data数据的具体格式表现在contentprovider上面的就相对较多,那么下面我们详细讲解一下contentprovider中的Data属性设置:

Android应用开发中经常会接触到Uri、ContentProvider,现在可以具体理解 data 、android:host、android:scheme代表的含义

Android平台上共享数据时我们会用到ContentProvider。要标识一个Content Provider,就必须用到URI。什么是URI呢? 它就类似于我们要通过网址来标识某个特定网站,实际上网址URL本身 就是一种URI。URI全称Uniform Resource Identifier, 它包括了URL和URN。URI不仅可以标识特定ContentProvider,还可以标识ContentProvider中特定的数据库表,就好像URL不仅可以标识特定网站,也可以标识这个网站某个特定网页一 样。实际上在Android平台上URI的用途更广泛一些,它还用于Intent中data的标识。

就Android平台而言,URI主要分三个部分:scheme, authority and path。其中authority又分为host和port。格式如下:
scheme://host:port/path
举个实际的例子:

content://com.example.project:200/folder/subfolder/etc
\---------/ \---------------------------/ \---/ \--------------------------/
scheme        host          port     path
         \--------------------------------/
                 authority
现在大家应该知道data flag中那些属性的含义了吧,看下data flag

<data 
android:host="string" 
android:mimeType="string" 
android:path="string" 
android:pathPattern="string" 
android:pathPrefix="string" 
android:port="string" 
android:scheme="string" />

但是我们在程序中一般是不直接用URI来标识ContentProvider的,是的,正如我们通常见到的用定义的常量来标识。例如Contacts中用Contacts.People.CONTENT_URI来标识Contacts ContentProvider中People这个表。那么要标识某个具体的人怎么办呢? 这就用到了ContentUris.withAppendedId() 和 Uri.withAppendedPath()。例如我们要表示content://contacts/people/20,那么我们就可以用如下语句:Uri uri = ContentUris.withAppendedId(People.CONTENT_URI, 20); 或者
Uri uri = Uri.withAppendedPath(People.CONTENT_URI, "20");

 Category:一个字符串,包含了关于处理该intent的组件的种类的信息。一个intent对象可以有任意个category。intent类定义了许多category常数.

addCategory()方法为一个intent对象增加一个category,
removeCategory删除一个
category,
getCategories()获取intent所有的category.

Type:显式指定Intent的数据类型(MIME)(多用于互联网邮件扩展,Multipurpose Internet MailExtensions)。比如,一个组件是可以显示图片数据的而不能播放声音文件。很多情况下,data类型可在URI中找到,比如content:开头的URI,表明数据由设备上的content provider提供。但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导。

MIME类型有2种形式
1.1 单个记录的格式: vnd.android.cursor.item/vnd.yourcompanyname.contenttype,如:content://com.example.transportationprovider/trains/122(一条列车信息的uri)的MIME类型是vnd.android.cursor.item/vnd.example.rail

1.2 多个记录的格式:vnd.android.cursor.dir/vnd.yourcompanyname.contenttype,如:content://com.example.transportationprovider/trains(所有列车信息)的MIME类型是vnd.android.cursor.dir/vnd.example.rail

component:指定Intent的目标组件的类名称。通常 Android会根据Intent 中包含的其它属性的信息,比如action、data/type、category进行查找,最终找到一个与之匹配的目标组件。但是,如果 component这个属性有指定的话,将直接使用它指定的组件,而不再执行上述查找过程。指定了这个属性以后,Intent的其它所有属性都是可选的。例如:

Intent it = new Intent(Activity.Main.this,Activity2.class); startActivity(it);

startActivity(it);

extras:附加信息,例如ACTION_TIMEZONE_CHANGED的intent有一个"time-zone"附加信息来指明新的时区,而ACTION_HEADSET_PLUG有一个“state”附加信息来指示耳机是被插入还是被拔出。intent对象有一系列put...()和set...()方法来设定和获取附加信息。 这些方法和Bundle对象很像。事实上附加信息可以使用putExtras()和getExtras()作为Bundle来读和写。例如:

//用Bundle传递数据

Intent it = new Intent(Activity.Main.this, Activity2.class);

Bundle bundle=new Bundle();

bundle.putString("name", "This is fromMainActivity!");

it.putExtras(bundle);

startActivity(it);

 //获得数据

Bundle bundle=getIntent().getExtras();

String name=bundle.getString("name");

intent的解析:

在应用中,我们可以以两种形式来使用Intent:
1.1 显式Intent:指定了component属性的Intent(调用setComponent(ComponentName)或者setClass(Context, Class)来指定)。通过指定具体的组件类,通知应用启动对应的组件。

2.2 隐式Intent:没有指定comonent属性的Intent。这些Intent需要包含足够的信息,这样系统才能根据这些信息,在在所有的可用组件中,确定满足此Intent的组件。
对于直接Intent,Android不需要去做解析,因为目标组件已经很明确,Android需要解析的是那些间接Intent,通过解析将 Intent映射给可以处理此Intent的Activity、Service或Broadcast Receiver。

Intent解析机制

Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有<intent-filter>及其中定义的Intent,通过PackageManager(注:PackageManager能够得到当前设备上所安装的application package的信息)来查找能处理这个Intent的component。在这个解析过程中,Android是通过Intentactiontypecategory这三个属性来进行判断的,判断方法如下:
1.1 如果Intent指明定了action,则目标组件的IntentFilter的action列表中就必须包含有这个action,否则不能匹配;
1.2 如果Intent没有提供type,系统将从data中得到数据类型。和action一样,目标组件的数据类型列表中必须包含Intent的数据类型,否则不能匹配。
1.3 如果Intent中的数据不是content:类型的URI,而且Intent也没有明确指定type,将根据Intent中数据的scheme(比如 http:或者mailto:)进行匹配。同上,Intent 的scheme必须出现在目标组件的scheme列表中。
1.4 如果Intent指定了一个或多个category,这些类别必须全部出现在组建的类别列表中。比如Intent中包含了两个类别:LAUNCHER_CATEGORY和ALTERNATIVE_CATEGORY,解析得到的目标组件必须至少包含这两个类别。

 

共有 人打赏支持
粉丝 0
博文 140
码字总数 0
×
飞上北极星
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: