当前位置:操作系统 > 安卓/Android >>

Android实战技巧:组件间通信---Intent和IntentFilter

 

Understanding Intent and IntentFilter--理解Intent和IntentFilter

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

Intent和IntentFilter是Android和一种消息通信机制,可以让系统的组件之间进行通信。信息的载体就是Intent,它可以是一个要完成的动作请求,也可以一般性的消息广播,它可以由任意一个组件发出。消息,也就是Intent,最终也是要被组件来进行处理和消化。消息由组件发出,通常在消息的里面也会有会标记有目标组件的相关信息,另外目标组件也需要告诉系统,哪些消息是它所感兴趣的,它需要设置一些过滤器,以过滤掉无关的消息。

其实这里就好比学校里的广播,广播有时会播放通知,但有时也会播放要执行的动作,比如打扫卫生。消息中通常都会说明消息的目标对象,可能是计算机学院,可能是老师,也可能是英语系的人才需要关注。而每个人,或是学院组织,也只关心与他们有关的消息,当然这里就要他们自己去判断哪些是与他们有关的消息了。在Android当中消息就是Intent,过滤器就是IntentFilter。发出消息的组件可以在消息中设置目标组件的相关信息,目标组件也可以设置过滤器,然后系统会进行过滤,只把组件所感兴趣的消息,传递给组件。这里假设读者已经了解Intent和IntentFilter的基本使用方法,且并不会进行全面的介绍,如果不了解,可以先读读官方文档,这里重点讲讲IntentFilter在使用时的一些注意事项。

Intent消息机制通常有二种,一个是显式Intent(Explicit Intent),另一个是隐式Intent(Implicit Intent)。

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

隐式Intent--也就是不在Intent中指定目标组件,在Intent中不能含有目标的名字。系统是根据其他的信息,比如Data,Type和Category去寻找目标组件。

隐式Intent通常用于与应用程序外部的组件进行通信。应用程序级别的组件复用也主要是靠隐式Intent来完成的。而IntentFilter也是只有隐式Intent才用的着,显式Intent都是直接把Intent传递给目标组件,根本不会理会组件的IntentFilter。

显式Intent(Explicit Intent)

显示Intent使用起来比较简单,只需要在Intent中指定目标组件的名字即可,也就是通过Intent的方法设置Component属性。如前所述,显式Intent通常用于应用程序内部启动Activity或Service。事实上,并不完全局限在应用程序内部,对于外部应用的Activity和Service,也可以用显式Intent来启动,但你必须知道它们的名字。

设置组件的名字的方法有:

 

public Intent setComponent(ComponentName component); 

public Intent setClass(Context packageContext, Class<?> cls); 

public Intent setClassName (Context packageContext, String className); 

public Intent setClassName (String packageName, String className); 

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

ComponentName Intent.getComponent();

对于应用程序内部启动Activity通常是这样子设置Intent:

 

Intent i = new Intent();  

// Select one of them 

i.setComponent(new ComponentName(getApplication(), ViewStubDemoActivity.class)); 

i.setComponent(new ComponentName(getApplication(), ViewStubDemoActivity.class.getName())); 

i.setComponent(new ComponentName(getApplication().getPackageName(), ViewStubDemoActivity.class.getName())); 

i.setClass(getApplication(), ViewStubDemoActivity.class); 

i.setClassName(getApplication(), ViewStubDemoActivity.class.getName()); 

i.setClassName(getApplication().getPackageName(), ViewStubDemoActivity.class.getName()); 

startActivity(i); 

因为应用程序内部的组件类,都是可以访问到的,所以要尽可能少写字串常量,以减少拼写错误,如果一定要使用包名和类名,也要注意,类名必须是全称,也就是从包名开始,如“com.hilton.networks.WifiManagerActivity"。

但是对于外部应用程序的Activity,通常只能通过以下方法:

 

Intent i = new Intent(); 

// select one of them 

i.setComponent(new ComponentName("com.hilton.networks", "com.hilton.networks.WifiManagerActivity")); 

i.setClassName("com.hilton.networks", "com.hilton.networks.WifiManagerActivity"); 

startActivity(i); 

首先,带有Context为参数的是不能够用的,因为通常你无法拿到其他应用程序的Context,你只能拿到你所在应用程序的Context,所以用你所在的应用程序的Context去启动外部的Activity肯定会报错的。其次,不参再像上面那样通过Class.getName()去指定类名,你为你无法导入外部的类,会有编译错误的。另外,千万要注意不要拼错,否则会有RuntimeException抛出的。

对于Service组件,也是一样,Intent的写法与Activity组件一致,但是对于BroadcastReceiver组件通常都用显式Intent。

隐式Intent的消息过滤器--IntentFilter

IntentFilter是用来解析隐式Intent(Implicit Intent)的,也就是说告诉系统你的组件(Activity, Service, BroadcastReceiver)能够处理哪些隐式的Intent。在使用的时候我们通常是这样子的:

 

<manifest ...> 

    <receiver ...> 

           <intent-filter> 

              <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> 

              <action android:name="android.appwidget.action.APPWIDGET_ENABLED" /> 

              <action android:name="android.appwidget.action.APPWIDGET_DISABLED" /> 

              <action android:name="android.appwidget.action.APPWIDGET_DELETED" /> 

           </intent-filter> 

           <intent-filter> 

              <action android:name="android.intent.action.MEDIA_MOUNTED"/> 

              <action android:name="android.intent.action.MEDIA_UNMOUNTED"/> 

              <action android:name="android.intent.action.MEDIA_SHARED"/> 

              <action android:name="android.intent.action.MEDIA_REMOVED"/> 

              <action android:name="android.intent.action.MEDIA_EJECT"/> 

              <data android:scheme="file" /> 

           </intent-filter> 

           <intent-filter> 

              <action android:name="android.intent.action.PACKAGE_ADDED"/> 

              <action

补充:移动开发 , Android ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,