admin管理员组

文章数量:1656246

广播机制(BroadcastReceiver)

 

11.1. BroadcastReceiver简介

在实际应用中,我们常需要等,等待系统抑或其他应用发出一道指令,为自己的应用擦亮明灯指明方向。而这种等待,在很多的平台上,都会需要付出不小的代价。比如,在Symbian中,你要等待一个来电消息,显示归属地之类的,必须让自己的应用忍辱负重偷偷摸摸的开机启动,消隐图标隐藏任务项,潜伏在后台,监控着相关事件,等待转瞬即逝的出手机会。这是一件很发指的事情,不但白白耗费了系统资源,还留了个流氓软件的骂名,这真是卖力不讨好的正面典型。

在Android中,充分考虑了广泛的这类需求,于是就有了Broadcast Receiver这样的一个组件。每个Broadcast Receiver都可以接收一种或若干种Intent作为触发事件(有不知道Intent的么,后面会知道了...),当发生这样事件的时候,系统会负责唤醒或传递消息到该Broadcast Receiver,任其处置。在此之前和这以后,Broadcast Receiver是否在运行都变得不重要了,及其绿色环保。

这个实现机制,显然是基于一种注册方式的,Broadcast Receiver将其特征描述并注册在系统中,根据注册时机,可以分为两类,被我冠名为冷热插拔。所谓冷插拔,就是Broadcast Receiver的相关信息写在配置文件中(求配置文件详情?稍安,后续奉上...),系统会负责在相关事件发生的时候及时通知到该Broadcast Receiver,这种模式适合于这样的场景。某事件方式 -> 通知Broadcast -> 启动相关处理应用。比如,监听来电、邮件、短信之类的,都隶属于这种模式。而热插拔,顾名思义,插拔这样的事情,都是由应用自己来处理的,通常是在OnResume事件中通过registerReceiver进行注册,在OnPause等事件中反注册,通过这种方式使其能够在运行期间保持对相关事件的关注。比如,一款优秀的词典软件(比如,有道词典...),可能会有在运行期间关注网络状况变化的需求,使其可以在有廉价网络的时候优先使用网络查询词汇,在其他情况下,首先通过本地词库来查词,从而兼顾腰包和体验,一举两得一石二鸟一箭双雕(注,真实在有道词典中有这样的能力,但不是通过Broadcast Receiver实现的,仅以为例...)。而这样的监听,只需要在其工作状态下保持就好,不运行的时候,管你是天大的网路变化,与我何干。其模式可以归结为:启动应用 -> 监听事件 -> 发生时进行处理。

除了接受消息的一方有多种模式,发送者也有很重要的选择权。通常,发送这有两类,一个就是系统本身,我们称之为系统Broadcast消息,在reference/android/content/Intent.html的Standard Broadcast Actions,可以求到相关消息的详情。除了系统,自定义的应用可以放出Broadcast消息,通过的接口可以是Context.sendBroadcast,抑或是Context.sendOrderedBroadcast。前者发出的称为Normal broadcast,所有关注该消息的Receiver,都有机会获得并进行处理;后者放出的称作Ordered broadcasts,顾名思义,接受者需要按资排辈,排在后面的只能吃前面吃剩下的,前面的心情不好私吞了,后面的只能喝西北风了。

当Broadcast Receiver接收到相关的消息,它们通常做一些简单的处理,然后转化称为一条Notification,一次振铃,

一次震动,抑或是启动一个Activity进行进一步的交互和处理。所以,虽然Broadcast整个逻辑不复杂,却是足够有用和

好用,它统一了Android的事件广播模型,让很多平台都相形见绌了。更多Broadcast Receiver相关内容,参见:

/reference/android/content/BroadcastReceiver.html。

11.2. BroadcastReceiver、Service、Activity共同应用实例

范例一:通过Activity启动广播

BroadcastReceiver:

package com.makyan.demo;

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.Intent;

import android.widget.Toast;

public class MyBroadcast extends BroadcastReceiver {

            public MyBroadcast(){

                       System.out.println("每次启动广播都会实例化一个广播对象");

            }

            public void onReceive(Context arg0, Intent arg1) {

                       Toast.makeText(arg0, "广播已经启动", Toast.LENGTH_LONG).show();

            }

}

 

Activity:

package com.makyan.demo;

import android.app.Activity;

import android.content.Intent;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

public class BroadcastActivity extends Activity {

            private Button but;

            protected void onCreate(Bundle savedInstanceState) {

                       super.onCreate(savedInstanceState);

                       setContentView(R.layout.activity_broadcast);

                       but = (Button) super.findViewById(R.id.start);

                       but.setOnClickListener(new OnClickListenerImpl());

            }

            class OnClickListenerImpl implements OnClickListener{

                       public void onClick(View arg0) {

                                   Intent it = new Intent(Intent.ACTION_EDIT); //AndroidMainfest.xml中找到对应的action,映射到对应的name

                                   BroadcastActivity.this.sendBroadcast(it);

                       }

            }

}

 

 

在AndroidMainfest.xml中注册广播:

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

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

    package="com.makyan.demo"

    android:versionCode="1"

    android:versionName="1.0" >

    <uses-sdk

        android:minSdkVersion="17"

        android:targetSdkVersion="17" />

    <application

        android:allowBackup="true"

        android:icon="@drawable/ic_launcher"

        android:label="@string/app_name"

        android:theme="@style/AppTheme" >

        <activity

            android:name="com.makyan.demo.BroadcastActivity"

            android:label="@string/app_name" >

            <intent-filter>

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

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

            </intent-filter>

        </activity>

        <receiver

            android:name="com.makyan.demo.MyBroadcast"

            android:enabled="true">

            <intent-filter>

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

            </intent-filter>

        </receiver>

    </application>

</manifest>

现在的广播跟Service一样,都是根据Activity来启动,但是要记住,广播可以通过系统的状态来启动。

也可以不在AndroidMainfest.xml中配置,直接在Activity中手动的为广播注册,如下Activity:

package com.makyan.demo;

import android.app.Activity;

import android.content.Intent;

import android.content.IntentFilter;

import android.os.Bundle;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

public class BroadcastActivity extends Activity {

            private Button but;

            protected void onCreate(Bundle savedInstanceState) {

                       super.onCreate(savedInstanceState);

                       setContentView(R.layout.activity_broadcast);

                       but = (Button) super.findViewById(R.id.start);

                       but.setOnClickListener(new OnClickListenerImpl());

            }

            class OnClickListenerImpl implements OnClickListener{

                       public void onClick(View arg0) {

                                   /**

本文标签: 二十八机制基础教程详细