1、Android Doc中对BroadcastReceiver的概述
①广播接收器是一个专注于接收广播通知信息,并做出对应处理的组件。很多广播是源自于系统代码的──比如,通知时区改变、电池电量低、拍摄了一张照片或者用户改变了语言选项。应用程序也可以进行广播──比如说,通知其它应用程序一些数据下载完成并处于可用状态。
②应用程序可以拥有任意数量的广播接收器以对所有它感兴趣的通知信息予以响应。所有的接收器均继承自BroadcastReceiver基类。
③广播接收器没有用户界面。然而,它们可以启动一个activity来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力──闪动背灯、震动、播放声音等等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。
Android中的广播事件有两种,一种就是系统广播事件,比如:ACTION_BOOT_COMPLETED(系统启动完成后触发),ACTION_TIME_CHANGED(系统时间改变时触发),ACTION_BATTERY_LOW(电量低时触发)等等。另外一种是我们自定义的广播事件。
2、广播的机制
Android广播机制包含三个基本要素:
广播(Broadcast)----- 用于发送广播。
广播接收器(BroadcastReceiver)----- 用于接收广播。
意图内容(Intent)----- 用于保存广播相关信息的媒介。
Broadcast是一种广泛应用的在应用程序之间传输信息的机制。而BroadcastReceiver是对发出来的Broadcast进行过滤接受并响应的组件。
首先在需要发送信息的地方,把要发送的信息和用于过滤的信息(如Action、Category)装入一个Intent对象,然后通过调用Context.sendBroadcast()、Context.sendOrderBroadcast()或Context.sendstickyBroadcast()方法,把Intent对象以广播的方式发出去。
当Intent发送以后,所有已经注册的BroadcastReceiver会检查注册时的Intentfilter是否与发送的Intent相匹配,若匹配就会调用BroadcastReceiver的void onReceive(Context curContext, Intent broadcastMsg)方法。
数据的发送方只负责发送数据,数据如何接收,如何被处理都由接收方处理。在Android中,广播的是操作系统中所产生的各种各样的事件。如收到一条短信,一个来电等,Android操作系统一旦内部产生了这些事件就会向所有的广播接收器对象广播这些事件,至于这些广播接收器对象是否关心这些事件,及如何处理这些事件都有广播接收器决定。

3、BroadcastReceiver的编写方法
继承BroadcastReceiver类,重新里面的public void onReceive(Context context, Intent intent)方法,android操作系统中发出的广播事件就由我们这个类接收和处理。一个应用中可能存在很多个Broadcast Receiver对象,如何指明哪个Receiver处理哪个广播事件呢,首先想要让Broadcast Receiver接收事件必须现在Mainfest.xml文件中注册,然后使用intent-filter来决定Broadcast Receiver接收什么类型的事件。
4、BroadcastReceiver的生命周期
当onReceive(Context context, Intent intent)返回,那么Broadcast Receiver对象就结束而不再处于活动状态,生命周期就结束了,所以,在广播接收器里面不能起线程,如果有耗时的操作可以使用service来解决。另外,由于Broadcast Receiver属于UI线程,因此在这里不能进行耗时操作。
5、注册BroadcastReceiver的方法
BroadcastReceiver用于监听被广播的事件(Intent),为了达到这个目的,BroadcastReceiver必须进行注册,注册的方法有以下两种,静态和动态注册。其实所谓的静态注册,动态注册,是指接收广播的时候,是静态注册接收还是动态注册接收,发送的时候不分静态,动态的。
(1)、在应用程序的代码中进行注册在该activity结束后,我们可以注销该广播,也就是它随着activity的消失而消失。在activity不可见以后或应用退出之后,就不会再接收广播了;
注册:registerReceiver(receiver,filter);
取消注册:unregisterReceiver(receiver);
如果一个BroadcastReceiver用于更新UI,通常会使用这个方法进行注册,在Activity启动的时候注册BroadcastReceiver,在Activity不可见以后,取消注册。
(2)、在AndroidMainfest.xml中进行注册,这种方式注册,无论应用程序开还是关,都能接受广播,始终处于活动状态,即使应用程序退出了,也会接收到广播消息。那么该广播是在activity结束之后也不会结束的,原因在于它已经写在了manifest.xml文件当中,也就是注册到了系统当中,所以无论你的activity是否存在,对于该广播没有影响。
如果是一些系统应用,比如手机没电后震动,后台计算流量这样的功能,需要一直存在的,我们可以在androidmanifest.xml中注册,而一些只有该activity存在时才有意义的广播,比如更改界面等等,就用动态注册比较合适,activity都没了。该广播还有什么用呢?只会浪费资源而已。
通过实例来更好地理解广播接收:
activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<Button android:id="@+id/static_custom_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="静态接收自定义广播"/>
<Button
android:id="@+id/static_sys_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="静态接收系统广播"/>
<Button android:id="@+id/dynamic_custom_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="动态接收自定义广播"/>
<Button
android:id="@+id/dynamic_sys_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="动态接收系统广播"/>
</LinearLayout>
mainfest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.learnbroadcast"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.learnbroadcast.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>
<receiver android:name=".MyReceiver">
<intent-filter >
<action android:name="android.intent.action.DATE_CHANGED"/>
<action android:name="test.custom.static.broadcast"/>
</intent-filter>
</receiver>
</application>
</manifest>
MyReceiver:
package com.example.learnbroadcast;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyReceiver extends BroadcastReceiver
{
public static final String TAG = "MyReceiver";
public static final String CUSTOM_STATIC = "test.custom.static.broadcast";
@Override
public void onReceive(Context arg0, Intent arg1)
{
String action = arg1.getAction();
if(action.equals(CUSTOM_STATIC))
{
Log.i(TAG, "receive custom static broadcast");
}
else if(action.equals(Intent.ACTION_DATE_CHANGED))
{
Log.i(TAG, "receive ACTION_DATE_CHANGED static broadcast");
}
else
{
Log.i(TAG, "other broadcast...");
}
}
}
MainActivity.java:
package com.example.learnbroadcast;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity
{
public static final String TAG = "MainActivity";
public static final String CUSTOM_STATIC = "test.custom.static.broadcast";
public static final String CUSTOM_DYMATIC = "test.custom.dymatic.broadcast";
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button staticCustom = (Button) findViewById(R.id.static_custom_button);
Button staticSys = (Button) findViewById(R.id.static_sys_button);
Button dymaticCustom = (Button) findViewById(R.id.dynamic_custom_button);
Button dymaticSys = (Button) findViewById(R.id.dynamic_sys_button);
staticCustom.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Log.i(TAG, "send static custom broadcast...");
Intent intent = new Intent();
intent.setAction(CUSTOM_STATIC);
sendBroadcast(intent);
}
});
staticSys.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Log.i(TAG, "send static system broadcast...");
Intent intent = new Intent(Intent.ACTION_DATE_CHANGED);
sendBroadcast(intent);
}
});
dymaticCustom.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Log.i(TAG, "send dymatic custom broadcast...");
Intent intent = new Intent(CUSTOM_DYMATIC);
sendBroadcast(intent);
}
});
dymaticSys.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
Log.i(TAG, "send dymatic system broadcast...");
Intent intent = new Intent(Intent.ACTION_CALL);
sendBroadcast(intent);
}
});
}
private BroadcastReceiver dymaticReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if(action.equals(CUSTOM_DYMATIC))
{
Log.i(TAG, "receiver CUSTOM_DYMATIC ...");
}
else if(action.equals(Intent.ACTION_CALL))
{
Log.i(TAG, "receiver System_DYMATIC ACTION_CALL ...");
}
}
};
@Override
protected void onStart()
{
Log.i(TAG, "onstart...");
super.onStart();
IntentFilter filter = new IntentFilter();
filter.addAction(CUSTOM_DYMATIC);
filter.addAction(Intent.ACTION_CALL);
registerReceiver(dymaticReceiver, filter);
}
@Override
protected void onStop()
{
Log.i(TAG, "onstop...");
super.onStop();
unregisterReceiver(dymaticReceiver);
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}