Android开发之BroadcastReceiver详解

BroadcastReceiver,顾名思义就是“广播接收者”的意思,它是Android四大基本组件之一,这种组件本质上是一种全局的监听器,用于监听系统全局的广播消息。它可以接收来自系统和应用的的广播。

由于BroadcastReceiver是一种全局的监听器,因此它可以非常方便地实现系统不同组件之间的通信。比如Activity与通过startService()方法启动的Service之间通信,就可以借助于BroadcastReceiver来实现。

BroadcastReceiver简介:



BroadcastReceiver用于接收程序(包括系统程序和一般应用)通过sendBroadcast()方法发出的Broadcast intents。

程序启动BroadcastReceiver的步骤(发出广播):



1)        创建需要启动BroadcastReceiver的Intent。

2)        调用Context的sendBroadcast()或sendOrderedBroadcast()方法来启动指定的BroadcastReceiver。其中sendBroadcast发送的是普通广播,sendOrderedBroadcast发送的是有序广播。

当应用发出一个Broadcast Intent之后所匹配该Intent的组件都可能被启动。

创建BroadcastReceiver的步骤:



第一步:创建BroadcastReceiver的子类:

由于BroadcastReceiver本质上是一种监听器,所以创建BroadcastReceiver的方法也非常简单,只需要创建一个BroadcastReceiver的子类然后重写onReceive
(Context context,
Intentintent)方法即可。

具体代码如下:

public class MyBroadcastReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
                   // TODO Auto-generated method stub
                   String msg=intent.getExtras().get("msg").toString();
                   Toast.makeText(context,"intent.getAction()"+intent.getAction().toString(),
                                     Toast.LENGTH_LONG).show();
                   System.out.println("msg:"+msg);
         }
}

第二步:注册BroadcastReceiver

一旦实现了BroadcastReceiver,接下就应该指定该BroadcastReceiver能匹配的Intent即注册BroadcastReceiver。注册BroadcastReceiver的方式有两种:

第一种是静态注册:这种方法是在配置AndroidManifest.xml配置文件中注册,通过这种方式注册的广播为常驻型广播,也就是说如果应用程序关闭了,有相应事件触发,程序还是会被系统自动调用运行。例如:

<!-- 在配置文件中注册BroadcastReceiver能够匹配的Intent -->
<receiver android:name="com.example.test.MyBroadcastReceiver">
    <intent-filter>
        <action android:name="android.intent.action.MyBroadcastReceiver"></action>
        <category android:name="android.intent.category.DEFAULT"></category>
    </intent-filter>
</receiver> 

第二种是动态注册:这种方法是通过代码在.Java文件中进行注册。通过这种方式注册的广播为非常驻型广播,即它会跟随Activity的生命周期,所以在Activity结束前我们需要调用unregisterReceiver(receiver)方法移除它。例如:

//通过代码的方式动态注册MyBroadcastReceiver
MyBroadcastReceiver receiver=new MyBroadcastReceiver();
IntentFilter filter=new IntentFilter();
filter.addAction("android.intent.action.MyBroadcastReceiver");
//注册receiver
registerReceiver(receiver, filter);

注意:如果我们在Activity中注册了BroadcastReceiver,当这个Activity销毁的时候要主动撤销注册否则会出现异常。方法如下:

         @Override
         protected void onDestroy() {
                   // TODO Auto-generated method stub
                   super.onDestroy();
                   //当Activity销毁的时候取消注册BroadcastReceiver
                   unregisterReceiver(receiver);
         }

BroadcastReceiver的生命周期:



BroadcastReceiver的生命周期,从对象调用它开始,到onReceiver方法执行完成之后结束。另外,每次广播被接收后会重新创建BroadcastReceiver对象,并在onReceiver方法中执行完就销毁,如果BroadcastReceiver的onReceiver方法中不能在10秒内执行完成,Android会出现ANR异常。所以不要在BroadcastReceiver的onReceiver方法中执行耗时的操作。

如果需要在BroadcastReceiver中执行耗时的操作,可以通过Intent启动Service来完成。但不能绑定Service。

特别是,您可能无法从一个BroadcastReceiver中显示一个对话框,或绑定到服务。对于前者,则应该使用NotificationManager的API。对于后者,你可以使用Context.startService()来启动一个Service。

广播的类型:



Broadcast的类型有两种:普通广播和有序广播。

Normal broadcasts(普通广播):Normal broadcasts是完全异步的可以同一时间被所有的接收者接收到。消息的传递效率比较高。但缺点是接收者不能讲接收的消息的处理信息传递给下一个接收者也不能停止消息的传播。

Ordered broadcasts(有序广播):Ordered broadcasts的接收者按照一定的优先级进行消息的接收。如:A,B,C的优先级依次降低,那么消息先传递给A,在传递给B,最后传递给C。优先级别声明在<intent-filter>中,取值为[-1000,1000]数值越大优先级别越高。优先级也可通过filter.setPriority(10)方式设置。
另外Ordered broadcasts的接收者可以通过abortBroadcast()的方式取消广播的传播,也可以通过setResultData和setResultExtras方法将处理的结果存入到Broadcast中,传递给下一个接收者。然后,下一个接收者通过getResultData()和getResultExtras(true)接收高优先级的接收者存入的数据。

应用实例:



发送并接收普通和有序广播:

运行效果图:

实例代码:

MainActivity.java:发送广播:

package com.jph.broadcastreceiverdemo;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.app.Activity;
import android.content.Intent;
/**
 * Describe:</br>
 * <br/>本实例有两个优先级别不同的广播接收器
 * <br/>通过发送普通广播,和有序广播来学习
 * <br/>BroadcastReceiver的原理
 * <br/>@author jph
 * <br/>@Date:2014.08.05
 * */
public class MainActivity extends Activity {
	MyBroadcastReceiver receiver;
	Button btnSend,btnSend2;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		btnSend=(Button)findViewById(R.id.btnSend);
		btnSend2=(Button)findViewById(R.id.btnSend2);
		receiver=new MyBroadcastReceiver();
		OnClickListener listener=new OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				switch (v.getId()) {
				case R.id.btnSend:
					Intent intent=new Intent();
					intent.setAction("android.intent.action.MyBroadcastReceiver");
					intent.putExtra("msg", "我在发送广播!这只是一个普通的广播," +
							"你们无法通过abortBroadcast()的方式停止广播的传播," +
							"也无法往Broadcast中存入数据因为它是异步的");
					sendBroadcast(intent);
					break;
				case R.id.btnSend2:
					Intent intent2=new Intent();
					intent2.setAction("android.intent.action.MyBroadcastReceiver");
					intent2.putExtra("msg", "我在发送个有序的广播," +
							"你们可以通过abortBroadcast()的方式停止广播的传播," +
							"也可以往Broadcast中存入数据");
					sendOrderedBroadcast(intent2, null);
					break;
				default:
					break;
				}
			}
		};
		btnSend.setOnClickListener(listener);
		btnSend2.setOnClickListener(listener);
	}
}

MyBroadcastReceiver.java:接收广播

package com.jph.broadcastreceiverdemo;

import java.text.SimpleDateFormat;
import java.util.Date;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
/**
 * Describe:</br>
 * <br/>@author jph
 * <br/>@Date:2014.08.05
 * */
public class MyBroadcastReceiver extends BroadcastReceiver {
	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		String msg=intent.getExtras().get("msg").toString();
		setResultData("MyBroadcastReceiver接收到广播");
		Toast.makeText(context,"时间:"+new SimpleDateFormat("yyyy-MM-dd hh.mm.ss").format(new Date())
				+"\nMyBroadcastReceiver收到Action名为:"+intent.getAction().toString()
				+"的广播 \nComponent:"+intent.getComponent()
				+"\nmsg:"+msg,
				Toast.LENGTH_LONG).show();
	}
}

SecondBroadcastReceiver.java接收广播

package com.jph.broadcastreceiverdemo;

import java.text.SimpleDateFormat;
import java.util.Date;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
/**
 * Describe:</br>
 * <br/>@author jph
 * <br/>@Date:2014.08.05
 * */
public class SecondBroadcastReceiver extends BroadcastReceiver {
	@Override
	public void onReceive(Context context, Intent intent) {
		// TODO Auto-generated method stub
		String msg=intent.getExtras().get("msg").toString();
		String result=getResultData();
		Toast.makeText(context,"时间:"+new SimpleDateFormat("yyyy-MM-dd hh.mm.ss").format(new Date())
				+"\nSecondBroadcastReceiver收到Action名为:"+intent.getAction().toString()
				+"的广播 \nComponent:"+intent.getComponent()
				+"\nmsg:"+msg+"\n上一个接受者传来的reult:"+result,
				Toast.LENGTH_LONG).show();
	}
}

配置文件AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.jph.broadcastreceiverdemo"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.jph.broadcastreceiverdemo.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
		<!-- 在配置文件中注册MyBroadcastReceiver能够匹配的Intent -->
		<receiver android:name="com.jph.broadcastreceiverdemo.MyBroadcastReceiver">
		    <intent-filter android:priority="200">
		        <action android:name="android.intent.action.MyBroadcastReceiver"></action>
		        <category android:name="android.intent.category.DEFAULT"></category>
		    </intent-filter>
		</receiver>
		<!-- 在配置文件中注册SecondBroadcastReceiver能够匹配的Intent -->
		<receiver android:name="com.jph.broadcastreceiverdemo.SecondBroadcastReceiver">
		    <intent-filter android:priority="100">
		        <action android:name="android.intent.action.MyBroadcastReceiver"></action>
		        <category android:name="android.intent.category.DEFAULT"></category>
		    </intent-filter>
		</receiver>
    </application>

</manifest>

Android开发之BroadcastReceiver详解

时间: 2024-10-05 05:07:10

Android开发之BroadcastReceiver详解的相关文章

Android开发之SpannableString详解

在实际的应用开发过程中经常会遇到,在文本的不同部分显示一些不同的字体风格的信息如:文本的字体.大小.颜色.样式.以及超级链接等.一般情况下,TextView中的文本都是一个样式,对于类似的情况,可以借助SpannableString或SpannableStringBuilder对象来实现以上设置. SpannableString与SpannableStringBuilder都可以将某段文本设置成一个Span,在Android中,Span表示一段文本的效果,例如,链接形式.图像.带背景的文本等.只

Android开发之InstanceState详解

Android开发之InstanceState详解 本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceState(),并且在介绍这两个方法之后,再分别来实现使用InstanceState保存和恢复数据功能.Android实现屏幕旋转异步下载效果这样两个示例. 首先来介绍onSaveInstanceState() 和 onRestoreInstanceState() .关于这两个方法,一些朋友可能在Andr

Android开发之WebView详解

概述: 一个显示网页的视图.这个类是你可以滚动自己的Web浏览器或在你的Activity中简单地显示一些在线内容的基础.它使用了WebKit渲染引擎来显示网页,包括向前和向后导航的方法(通过历史记录),放大和缩小,执行文本搜索等. 需要注意的是:为了让你的应用能够使用WebView访问互联网和加载网页,你必须添加Internet的权限在Android Manifest文件中: <uses-permission android:name="android.permission.INTERNE

Android开发之InstanceState详解(转)---利用其保存Activity状态

Android开发之InstanceState详解 本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceState(),并且在介绍这两个方法之后,再分别来实现使用InstanceState保存和恢复数据功能.Android实现屏幕旋转异步下载效果这样两个示例. 首先来介绍onSaveInstanceState() 和 onRestoreInstanceState() .关于这两个方法,一些朋友可能在Andr

Android开发之Fragment详解

Android开发之Fragment学习 1.简介: Fragment是Android 3.0引入的新API. Fragment代表了 Activity的子模块,因此可以把Fragment理解成Activity片段.Fragment用于自己的生命周期,也可以接受它自己的输入事件. Fragment必须被"嵌入" Activity中使用,因此虽然Fragment也拥有自己的生命周期,但Fragment的生命周期会受它所在的Activity的生命周期的控制.例如,当Activity暂停时,

android开发之service详解

service作为android的四大组件之一,其重要性可想而知,在开发中,我们经常把一些不需要与用户进行交互的工作放在service中来完成,service运行在后台,这样有些人可能会产生错觉,以为service是运行在新线程中,其实不然,service也运行在主线程中,因此不能在service中进行耗时操作,否则会报ANR异常,但是我们可以在service中新开线程来进行耗时操作,比如下载等等. 先来说说service的两种绑定方式,一种是通过Context.startService()来启

Android开发之AlarmManager详解

AlarmManager实质是一个全局的定时器,是Android中常用的一种系统级别的提示服务,在指定时间或周期性启动其它组件(包括Activity,Service,BroadcastReceiver). 概述: 该类提供一种访问系统闹钟服务的方式,允许你去设置在将来的某个时间点去执行你的应用程序.当你的闹钟响起(时间到)时,在它上面注册的一个意图(Intent)将会被系统以广播发出,然后自动启动目标程序,如果它没有正在运行.注册的闹钟会被保留即使设备处于休眠中(如果闹钟在给定时间响起可以选择是

[转]ANDROID开发之SQLite详解

SQLite简介 Google为Andriod的较大的数据处理提供了SQLite,他在数据存储.管理.维护等各方面都相当出色,功能也非常的强大.SQLite具备下列特点: 1.轻量级 使用 SQLite 只需要带一个动态库,就可以享受它的全部功能,而且那个动态库的尺寸想当小. 2.独立性 SQLite 数据库的核心引擎不需要依赖第三方软件,也不需要所谓的“安装”. 3.隔离性 SQLite 数据库中所有的信息(比如表.视图.触发器等)都包含在一个文件夹内,方便管理和维护. 4.跨平台 SQLit

Android开发之MdiaPlayer详解

MediaPlayer类可用于控制音频/视频文件或流的播放,我曾在<Android开发之基于Service的音乐播放器>一文中介绍过它的使用.下面让我们看一下MediaPlayer类的详细介绍. 一.类结构: java.lang.Object    ? android.media.MediaPlayer 二.构造方法和公有方法 构造方法: Public Constructors   MediaPlayer() 默认构造方法. 公有方法: Public Methods static MediaP