交互式通信之广播消息BroadcastReceiver

来源:互联网 发布:suse linux网卡绑定 编辑:程序博客网 时间:2024/05/22 04:39

交互式通信之广播消息Broadcast

在Android系统中,广播机制是一种允许在组件之间进行通信的一种方式。当然,这些组件可以运行在同一个进程,也可以运行在不同的进程当中,如果是运行在不同的进程当中,广播机制就有点类似于服务Service组件了。实际上,广播机制就是在Binder进程间通信的基础之上实现的,这点无需置疑。如果是这样的话,那么Android为什么还要引进广播这种机制那?答案是肯定的。我们都知道,在Binder进程间通信中,Client组件在和Service组件通信的时候之前,必须要获得它的一个代理对象,也就是说Client组件实现要知道Service组件的存在。但是,在广播机制中,广播发送者实现是不知道广播的接受者的存在的,这样就可以降低广播发送者和接受者之间的耦合度,可以大大提高系统的拓展性。因此,在Android系统中,引入广播机制来实现组件间的通信是有必要的。

广播的原理:

 

如上图说是,需要说明下ActivityManagerService是做什么的。在Java的本地系统服务SystemServer当中存在了服务ActivityManagerService它主要是用来创建Android应用程序组件(activity)、服务(service)、广播接收器(broadcast receiver)等工作,并全权管理他们的生命周期,是Android平台核心服务之一。

正如上面所示,在Java本地系统中存在一个广播的注册中心ActivityManagerService,当客户端发送一条注册请求registerReceiver时,这个注册请求就会注册到这个注册中心中,并指明该广播的接收信息的类型;同样,当客户端发送一条发送请求sendBroadcast的时候,会先将请求发送到这个ActivityManagerService中心去,其会现在已经注册的消息中根据消息类型寻找匹配的消息并返回给广播的接受者,然后继续后续处理。上面即是对广播机制的简单分析,更深入的分析会以后的源码分析中介绍吧!

广播的注册:

广播接收者的注册方式分为两种,分别为静态和动态的。在静态的注册方式中,描述广播的接收者的Broadcast receiver组件信息必须放在根配置文件AndroidManifest.xml中,并注明他们所感兴趣的广播类型,这样ActivityManagerService就可以找到他们。而在动态注册方式中,我们需要手动的在代码中调用Context的成员函数方法registerReceiver来将广播Broadcast receiver注册到消息注册中心ActivityManagerService中。需要注意的是,在同样条件下,动态注册方式会优先于静态注册方式接受广播。

一般情况下,因为Activity和Service组件都实现了Context接口,那么我们就可以在他们当中方便的注册广播了,而且经常是这样做。

广播的发送:

广播的发送方式有两种,分别为有序和无序的。

我们知道,在注册广播的时候,可以指定广播的优先级别,当消息中心ActivityManagerService接收到有序广播的时候,它会先将这个有序广播发送给符合条件的、优先级高的接收处理,然后再发送给优先级低的接收者处理;当ActivityManagerService接收到无序广播的时候,它会忽略掉广播接收者的优先级,而是将其并行的发送给所有满足条件的接收者处理。

下面我们以一个例子来说明广播的使用,这里会将广播注册在Service当中,当我们点击按钮的时候,发送广播并在接收广播的时候进行对应处理。在这里使用动态的注册方式注册广播,使用无序的方式来发送广播,我的项目目录:

 

接下来,就详细的介绍下广播的使用方法。

创建广播

首先,我们新建一个用来接收消息的广播VerifyBroadcastReceiver,并使其继承自BroadcastReceiver,我们必须实现里面的onReceive方法,因为我们接收广播的所有操作都在这里,它的代码如下:

public class VerifyBroadcastReceiver extends BroadcastReceiver {

private static String TAG = "VerifyBroadcastReceiver";

@Override

public void onReceive(Context context, Intent intent) {

// 用来接收广播的监听

String action = intent.getAction();

if("action_from_ui_onclick".equals(action)) {

log("我接收了消息:"+action);

}

}

private void log(String log) {

Log.d(TAG, log);

}

}

在这里,我们可以使用intent.getAction()来获得接收广播的动作标志,比如在这里只有接收到的消息标志为action_from_ui_onclick 的广播消息才会打印LOG。

注册广播

正如我们的需求,我们是要开启个服务Service,并在这里面注册上面的广播对象,使用这个服务来实时的监听广播并接收广播。那么先看下服务Service吧!其源代码如下:

public class BroadcastService extends Service {

private static IntentFilter intentFilter = null;

private static VerifyBroadcastReceiver broadcastReceiver = null;

private static Context context = null;

// 开启服务

public static void runService(Context ctx) {

context = ctx;

Intent intent = new Intent(context,BroadcastService.class);

context.startService(intent);

}

@Override

public void onCreate() {

// 创建广播消息过滤器

intentFilter = new IntentFilter();

intentFilter.addAction("action_from_ui_onclick");

// 创建广播对象

broadcastReceiver = new VerifyBroadcastReceiver();

// 注册广播接收

registerReceiver(broadcastReceiver,intentFilter);

super.onCreate();

}

 

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

return super.onStartCommand(intent, flags, startId);

}

 

@Override

public void onDestroy() {

// 取消注册消息广播

unregisterReceiver(broadcastReceiver);

super.onDestroy();

}

@Override

public IBinder onBind(Intent intent) {

return null;

}

// 结束服务

public static void stopService() {

Intent intent = new Intent(context,BroadcastService.class);

context.stopService(intent);

}

}

在这里,我们使用了startService这种方式来启动一个服务的,具体的可参看前面的“交互式通信之Service”,那里有详细的说明。服务开启之后,我们要在这个服务中注册我们上面所创建的广播,一般情况下,我们会在服务的onCreate()方法中进行创建并注册(registerReceiver)操作,当然,在这里需要设定一下接收广播的过滤条件IntentFiler,比如上面的“action_from_ui_onclick”,只有满足这个动作标志的广播才会接收到,并打印LOG。而在服务的onDestroy()中取消广播的注册(unregisterReceiver),以便于释放资源。

注意:因为我是使用动态的广播注册方式,所以不会在AndroidManifest.xml中进行广播描述声明;而这里开启的服务需要在这个配置文件中进行声明,我的AndroidManifest.xml文件内容如下所示:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="com.demo.verifybroadcast"

    android:versionCode="1"

    android:versionName="1.0" >

 

    <uses-sdk

        android:minSdkVersion="8"

        android:targetSdkVersion="19" />

 

    <application

        android:allowBackup="true"

        android:icon="@drawable/ic_launcher"

        android:label="@string/app_name"

        android:theme="@style/AppTheme" >

        <activity

            android:name="com.demo.verifybroadcast.ui.VerifyBroadcastActivity"

            android:label="@string/app_name" >

            <intent-filter>

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

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

        

        <!-- 全程服务 -->

        <service 

            android:name=".service.BroadcastService"

            android:exported="false" >

        </service>

    </application>

 

</manifest>

 

这里声明的服务Service 为全局服务,其中android:export为false则代表该服务不允许其他组件与之进行交互或是调用,反之是允许的。接下来,就是我们发送广播的操作了,这里是简单的在前台界面中添加一个按钮,当点击的时候,就会发送一个广播消息,然后广播接收者接收到符合的消息就会在onReceive()中接收该动作并打印出来,没点击一次就会发送广播消息。效果图如下:

 

 

到这里,广播的使用及原理就介绍完成了。

 

/**

* 欢迎加入技术群:179914858

* 如果有任何问题请在评论中进行讨论学习

*/