1、Intent和IntentFilter详解

Intent(意图)Android中是一个十分重要的组件,它是连接不同应用的桥梁和纽带,也是让组件级复用(Activity和 Service)成为可能的一个重要原因。Intent的使用分为二个方面一个是发出Intent,另一个则是接收Intent用官方的说法就是Intent Resolving。本主将对IntentIntentFilter进行一些介绍。

Android 应用程序中有三大核心组件: Activity, Service, Broadcast Receiver 都是通过被称之为意图的消息运行。Intent messaging is a facility for late run-time binding between components in the same or different applications. 意图本身一个 Intent 对象,它保存了对要执行操作的抽象描述对于broadcasts来说,则表示对已经发生并且正要报告的操作。对这下三种组件,发送intents分别有不同的机制。

1) 传递一个Intent对象到 Context.startActivity(intent) 或者 Activity.startActivity ForResult(int) 去运行一个Activity(可以在通过此方式启动后的Activity中调用 Activity.setResult() 设置结果参数,该参数将会在启动当前activityactivity中被接收---可以通过onActivityResult(int requestCode, int resultCode, Intent data) 接收)

2) 传递一个Intent对象到 Context.startService(intent) 去启动一个service 或者 传递一个新的指令到正在运行的service中。另外,还可以通过 Context.bindService(intent) 去绑定一个Service。(在调用组件和目标Service 建立一个连接)

3) 传递一个Intent对象到 任何一个broadcast methods (如: Context.sendBroadcast() , Context.sendOrderedBroadcast(), Context.sendStickyBroadcast() ) 该intent将被传递给所有已经被注册的broadcast receiver中。

在以上的三种情况下,当Intent被传递出后,Android系统会找到适合的activityservice,或者是多个broadcast receiver去响应这个intent,这三种情况不会存在重叠的部分,它们相互独立,互不干扰。

    Intent的产生的作用主要有两点:1.提供一致的编程模型,2.实现松散耦合的效果。

Intent消息机制通常有二种,一个是显式IntentExplicit Intent)用于明确需要跳转的组件,另一个是隐式IntentImplicit Intent),只提出意图,没有明确跳转的组件。

     显式Intent 需要在Intent中明确指定目标组件,也就是在Intent中明确写明目标组件的名称(Component name),需要指定完整的包名和类名。因为对于本程序以外的其他应用程序,你很难知道它的组件名字,所以显式的Intent通常用于应用程序内部通信,更确切的说,显示Intent是用于应用程序内部启动组件,通常又是ActivityService。还没有见用显式Intent来给BroadcastReceiver发送广播的。

     隐式Intent 也就是不在Intent中指定目标组件,在Intent中不能含有目标的名字。系统是根据其他的信息,比如DataTypeCategory去寻找目标组件。隐式Intent通常用于与应用程序外部的组件进行通信。应用程序级别的组件复用也主要是靠隐式Intent来完成的。而IntentFilter也是只有隐式Intent才用的着,显式Intent都是直接把Intent传递给目标组件,根本不会理会组件的IntentFilter

1)显式Intent

     在构造Intent对象时就指定接收者,它一般用在知道目标组件名称的前提下,一般是在相同的应用程序内部实现的。Intent跳转Activity实现如下:

 

<span style="white-space:pre">		</span>// 显示Intent
		// 通过直接指定组件实现
		Intent intent = new Intent();
		intent.setClass(this, Activity2.class);
		// intent.setComponent(new ComponentName(this, Activity2.class));
		// intent.setClassName(this, "com.lingyun.blog.intent.Activity2");
		// intent.setClassName("com.lingyun.blog.intent",
		// "com.lingyun.blog.intent.Activity2");
		startActivity(intent);</span>

Intent可以使用以下几种方法设置Component属性,虽然设置的方法有这么多,但Intent内部标识目标组件的属性只有一个Component,所以这么设置方法的目的也只是设置目标组件的Component,事实上有这么多的方法原因在于ComponentName的构造是多重载了的。在解析Intent时,系统也是取得这个Component属性,然后去启动它。

setComponent(ComponentName component);
setClass(Context packageContext, Class<?> cls);
setClassName (Context packageContext, String className);
setClassName (String packageName, String className);

(2)隐式Intent

隐式的Intent,即Intent的发送者在构造Intent对象时,并不知道也不关心接收者是谁,有利于降低发送者和接收者之间的耦合,它一般用在没有明确指出目标组件名称的前提下,一般是用于在不同应用程序之间。

		// 隐式Intent
		// 通过Action实现
		 Intent intent = new Intent();
		 intent.setAction("com.lingyun.action.HELLO");
		 intent.addCategory("com.lingyun.category.ABC");
		 startActivity(intent);

在此之前我们需要在AndroidManifest中对相应Activity进行配置,如下:

<activity android:name=".Activity2" >
            <intent-filter>
                <action android:name="com.lingyun.action.HELLO" />

                <category android:name="com.lingyun.category.ABC" />
                <!-- 注意:需要将下面的category一同加入 -->
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

隐式Intent常用于不同应用之间,可以使用Intent调用系统拨打电话、发短信等功能,如下:

		// 隐式Action调用其他应用
		 Intent intent = new Intent();
		 intent.setAction(Intent.ACTION_VIEW);
		 //打电话
		 //intent.setData(Uri.parse("tel://110"));
		 //打开网页
		 intent.setData(Uri.parse("http://www.baidu.com"));
		 startActivity(intent);

		// 发短信
		 Intent intent = new Intent();
		 intent.setAction(Intent.ACTION_SENDTO);
		 intent.setData(Uri.parse("smsto:10086"));
		 intent.putExtra("sms_body", "hello 10086");
		 startActivity(intent);

隐式Intent解析

 对于显式IntentAndroid不需要去做解析,因为目标组件已经很明确,Android需要解析的是那些隐式Intent,通过解析,将Intent映射给可以处理此IntentActivityIntentReceiverService。        

   Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Intent,最终找到匹配的Intent。在这个解析过程中,Android是通过Intentactiontypecategory这三个属性来进行判断的,判断方法如下:

Ø 如果Intent指明定了action,则目标组件的IntentFilteraction列表中就必须包含有这个action,否则不能匹配;

Ø 如果Intent没有提供type,系统将从data中得到数据类型。和action一样,目标组件的数据类型列表中必须包含Intent的数据类型,否则不能匹配。

Ø 如果Intent中的数据不是content: 类型的URI,而且Intent也没有明确指定它的type,将根据Intent中数据的scheme (比如 http: 或者mailto:) 进行匹配。同上,Intent scheme必须出现在目标组件的scheme列表中。

Ø 如果Intent指定了一个或多个category,这些类别必须全部出现在组建的类别列表中。比如Intent中包含了两个类别:LAUNCHER_CATEGORY 和 ALTERNATIVE_CATEGORY,解析得到的目标组件必须至少包含这两个类别。

Intent属性

一个Intent对象是一个信息包。它包含了要接收此Intent的组件需要的信息(例如需要的动作和动作需要的信息)和 android 系统需要的信息(要处理此Intent的组件的类别和怎样启动它)

总的来说,Intent Object 主要包括以下信息:

Ø 动作(Action

一个字符串,代表要执行的动作。系统中给出了很多Action,包括目标组件是Activity或者广播的,用户也可以定义自己的 action strings 来激活组件。自定义的action 应该包含包名作为前缀: 例如"com.example.project.MYACTION".

Constent( 常量)

Target Component (目标组件)

Action (动作 )

ACTION_CALL

activity

初始化一个电话呼叫

ACTION_EDIT

activity

显示用户要编辑的数据

ACTION_MAIN

activity

将该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

Data属性有两部分构成: 数据URI 和 数据MIME type 。 action的定义往往决定了data该如何定义。 例如: 如果 一个Intent的 action  ACTION_EDIT 那么它对应的data 应该包含待编辑的数据的URI . 如果一个action 为:ACTION_CALL ,那么data 应该为 tel: 电话号码的URI . 类似的, 如果action  ACTION_VIEW 那么data 应该为: http: URI , 接收到的activity 将会下载并显示相应的数据。

当一个Intent 和 有能力处理此Intent的组件进行匹配时, 除了 dataURI以外,了解data的类型(MIME Type)也很重要。 例如: 一个显示图片的组件 不应该去播放声音文件。

许多情况下,data type 可以从URI中推测出。 尤其是: URI = content: URIs这时候数据通常是位于本设备上而且是由某个content provider来控制的。即便如此,我们仍然可以明确的在 Intent object上设置一个 data type。 setData() 方法只能设置URI, setType() 设置MIME type, setDataAndType() 可以对二者都进行设置, 获取URI 和 data type 可分别调用 getData() 和 getType() 方法。

Ø Category

包含了处理该Intent的组件的种类信息起着对action的补充说明作用.一个Intent对象可以有任意多个 category。和action 一样, 在Intent class 中也定义了几个 category 常量。

Constant

Meaning

CATEGORY_BROWSABLE

目标Activity可以使用浏览器显示数据

CATEGORY_GADGET

activity可以被包含在另外一个装载小工具的activity.

CATEGORY_HOME

The activity displays the home screen, the first screen the user sees when the device is turned on or when the HOME key is pressed.

CATEGORY_LAUNCHER

The activity can be the initial activity of a task and is listed in the top-level application launcher.

可以让一个activity出现在launcher

CATEGORY_PREFERENCE

The target activity is a preference panel.

activity是一个选项面板

Ø Extras

为键-值对形式的附加信息例如ACTION_TIMEZONE_CHANGEDintent有一个"time-zone"附加信息来指明新的时区ACTION_HEADSET_PLUG有一个"state"附加信息来指示耳机是被插入还是被拔出.

intent对象有一系列put...()set...()方法来设定和获取附加信息这些方法和Bundle对象很像事实上附加信息可以使用putExtras()getExtras()作为Bundle来读和写.

Ø Flags

有各种各样的标志,许多指示Android系统如何去启动一个活动(例如,活动应该属于那个任务)和启动之后如何对待它(例如,它是否属于最近的活动列表)。所有这些标志都定义在Intent类中。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值