BroadCast(广播),概念:一种在系统内进行通信的机制.通过这种机制,它能够将系统中的某个进程的信息或者意图传递到其他的对这些信息或者意图感兴趣的进程.
广播发送者:想要主动传递自己的信息或者意图给系统或者特定的接收者,以便其作出响应.
广播接收者:想要接收系统或者特定进程的某些信息或意图,以便作出相应的响应.
Android广播机制包含三个基本要素:
广播(Broadcast)----- 用于发送广播。
广播接收器(BroadcastReceiver)----- 用于接收广播。
意图内容(Intent)----- 用于保存广播相关信息的媒介。
广播的过程:首先在需要发送信息的地方,把要发送的信息和用于过滤的信息(如Action、Category)装入一个Intent对象,然后通过调用Context.sendBroadcast()、Context.sendOrderBroadcast()方法,把Intent对象以广播的方式发出去。当Intent发送以后,所有已经注册的BroadcastReceiver会检查注册时的Intentfilter是否与发送的Intent相匹配,若匹配就会调用BroadcastReceiver的void onReceive(Context curContext, Intent broadcastMsg)方法,onReceiver()方法执行完成后,BroadcastReceiver的实例就会销毁。
sendBroadCast():发送普通广播可以在同一时刻被所有接收者收到
优点:消息传递效率高
缺点:各个接收者之间无法通信,无法终止消息传播
sendOrderedBroadCast:发送有序广播
接收者将按预先声明的优先级依次接收广播消息
优先级设置:<intent-filter> android:priority (-1000∽1000)数越大级别越高 也可调用IntentFilter对象的setPriority()设置
上一个接收者可往广播中压入数据传递给下一个接收者
任意一个接收者都可终止广播的传播,下一个就不能接收
注意:
如果找不到合适的BroadcastReceiver组件,应用不会有任何问题。
onReceiver()方法不能在10秒执行完成,会认为该进程无响应。弹出ANR(application no response)的对话框。
源代码实例如下:
发送普通广播:
Aactivity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button)findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
Intent intent = new Intent();
intent.setAction("com.coslay.action.CUSTOM_BROADCAST");
intent.putExtra("msg","简单的消息");
sendBroadcast(intent);
}
});
}
程序启动BroadcastReceiver只需要两步:
创建需要启动的BroadcastReceiver的Intent
调用Context的sendBroadcast()或sendOrderedBroadcast()方法来启动指定的BroadcastReceiver
BroadcastReceiver:
public class CustomReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context arg0, Intent arg1) {
Toast.makeText(arg0, "接收到的Intent的Action为:"+arg1.getAction()+"\n消息内容是:"+arg1.getStringExtra("msg"), Toast.LENGTH_LONG).show();
}
}
只要重写BroadcastReceiver的onReceive(Context context,Intent intent)方法即可。然后在如下注册监听器即可。
AndroidManifest.xml:
<receiver android:name=".CustomReceiver">
<intent-filter>
<action android:name="com.coslay.action.CUSTOM_BROADCAST"/>
</intent-filter>
</receiver>
指定该BroadcastReceiver能匹配的Intent有两种方式:
1.使用代码进行指定:
IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");
SomeReceiver receiver = new SomeReceiver();
registerReceiver(receiver,filter);
2.在AndroidManifest.xml文件中配置。如上所示。
发送有序广播:
Aactivity:
button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction("com.coslay.action.SORTED_BROADCAST");
intent.putExtra("msg", "简单的消息");
sendOrderedBroadcast(intent, null);
}
});
BroadcastReceiver:
public class SortedBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "接收到的Intent的Action为:"+intent.getAction()+"\n消息内容是:"+intent.getStringExtra("msg"), Toast.LENGTH_LONG).show();
//创建一个Bundle对象,并存入数据
Bundle bundle = new Bundle();
//将bundle存入结果中
bundle.putString("first", "第一个BroadcastReceiver存入的消息");
setResultExtras(bundle);
//取消Broadcast的继续传播
//abortBroadcast();
}
}
优先接收到Broadcast的接收者可以通过 setResultExtras(bundle);方法将处理结果存入Broadcast中,然后传给下一个接收者,下一个接收者通过代码:Bundle bundle = getResultExtras(true)可以获取上一个接收者存入的数据。
AndroidManifest.xml:
<receiver android:name=".SortedBroadcastReceiver">
<intent-filter android:priority="0">
<action android:name="com.coslay.action.SORTED_BROADCAST"/>
</intent-filter>
</receiver>
接收系统广播(接收开机广播启动服务):
BroadcastReceiver如下:
public class LaunchReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
Intent tIntent = new Intent(context
, LaunchService.class);
// 启动指定Service
context.startService(tIntent);
}
}
Service如下:
public class LaunchService extends Service
{
@Override
public IBinder onBind(Intent intent)
{
return null;
}
@Override
public void onCreate()
{
// 定义1秒执行一行输出
new Timer().schedule(new TimerTask()
{
@Override
public void run()
{
System.out.println("-----"
+ new Date() + "-----");
}
}, 0, 1000);
}
}
AndroidManifest.xml:
<service android:name=".LaunchService">
</service>
<!-- 定义一个BroadcastReceiver,监听系统开机广播 -->
<receiver android:name=".LaunchReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<!-- 授予应用程序访问系统开机事件的权限 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
BroadcastReceiver可以实现Service与Activity之间的通信:
Activity如下:
public class MusicBox extends Activity implements OnClickListener
{
// 获取界面中显示歌曲标题、作者文本框
TextView title, author;
// 播放/暂停、停止按钮
ImageButton play, stop;
ActivityReceiver activityReceiver;
public static final String CTL_ACTION =
"org.crazyit.action.CTL_ACTION";
public static final String UPDATE_ACTION =
"org.crazyit.action.UPDATE_ACTION";
// 定义音乐的播放状态,0x11代表没有播放;0x12代表正在播放;0x13代表暂停
int status = 0x11;
String[] titleStrs = new String[] { "心愿", "约定", "美丽新世界" };
String[] authorStrs = new String[] { "未知艺术家", "周蕙", "伍佰" };
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取程序界面界面中的两个按钮
play = (ImageButton) this.findViewById(R.id.play);
stop = (ImageButton) this.findViewById(R.id.stop);
title = (TextView) findViewById(R.id.title);
author = (TextView) findViewById(R.id.author);
// 为两个按钮的单击事件添加监听器
play.setOnClickListener(this);
stop.setOnClickListener(this);
activityReceiver = new ActivityReceiver();
// 创建IntentFilter
IntentFilter filter = new IntentFilter();
// 指定BroadcastReceiver监听的Action
filter.addAction(UPDATE_ACTION);
// 注册BroadcastReceiver
registerReceiver(activityReceiver, filter);
Intent intent = new Intent(this, MusicService.class);
// 启动后台Service
startService(intent);
}
// 自定义的BroadcastReceiver,负责监听从Service传回来的广播
public class ActivityReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
// 获取Intent中的update消息,update代表播放状态
int update = intent.getIntExtra("update", -1);
// 获取Intent中的current消息,current代表当前正在播放的歌曲
int current = intent.getIntExtra("current", -1);
if (current >= 0)
{
title.setText(titleStrs[current]);
author.setText(authorStrs[current]);
}
switch (update)
{
case 0x11:
play.setImageResource(R.drawable.play);
status = 0x11;
break;
// 控制系统进入播放状态
case 0x12:
// 播放状态下设置使用暂停图标
play.setImageResource(R.drawable.pause);
// 设置当前状态
status = 0x12;
break;
// 控制系统进入暂停状态
case 0x13:
// 暂停状态下设置使用播放图标
play.setImageResource(R.drawable.play);
// 设置当前状态
status = 0x13;
break;
}
}
}
@Override
public void onClick(View source)
{
// 创建Intent
Intent intent = new Intent("org.crazyit.action.CTL_ACTION");
switch (source.getId())
{
// 按下播放/暂停按钮
case R.id.play:
intent.putExtra("control", 1);
break;
// 按下停止按钮
case R.id.stop:
intent.putExtra("control", 2);
break;
}
// 发送广播,将被Service组件中的BroadcastReceiver接收到
sendBroadcast(intent);
}
}
、
Service的实例代码如下:
public class MusicService extends Service
{
MyReceiver serviceReceiver;
AssetManager am;
String[] musics = new String[] { "wish.mp3", "promise.mp3",
"beautiful.mp3" };
MediaPlayer mPlayer;
// 当前的状态,0x11 代表没有播放 ;0x12代表 正在播放;0x13代表暂停
int status = 0x11;
// 记录当前正在播放的音乐
int current = 0;
@Override
public IBinder onBind(Intent intent)
{
return null;
}
@Override
public void onCreate()
{
am = getAssets();
// 创建BroadcastReceiver
serviceReceiver = new MyReceiver();
// 创建IntentFilter
IntentFilter filter = new IntentFilter();
filter.addAction(MusicBox.CTL_ACTION);
registerReceiver(serviceReceiver, filter);
// 创建MediaPlayer
mPlayer = new MediaPlayer();
// 为MediaPlayer播放完成事件绑定监听器
mPlayer.setOnCompletionListener(new OnCompletionListener() //①
{
@Override
public void onCompletion(MediaPlayer mp)
{
current++;
if (current >= 3)
{
current = 0;
}
// 发送广播通知Activity更改文本框
Intent sendIntent = new Intent(MusicBox.UPDATE_ACTION);
sendIntent.putExtra("current", current);
// 发送广播 ,将被Activity组件中的BroadcastReceiver接收到
sendBroadcast(sendIntent);
// 准备、并播放音乐
prepareAndPlay(musics[current]);
}
});
super.onCreate();
}
public class MyReceiver extends BroadcastReceiver
{
@Override
public void onReceive(final Context context, Intent intent)
{
int control = intent.getIntExtra("control", -1);
switch (control)
{
// 播放或暂停
case 1:
// 原来处于没有播放状态
if (status == 0x11)
{
// 准备、并播放音乐
prepareAndPlay(musics[current]);
status = 0x12;
}
// 原来处于播放状态
else if (status == 0x12)
{
// 暂停
mPlayer.pause();
// 改变为暂停状态
status = 0x13;
}
// 原来处于暂停状态
else if (status == 0x13)
{
// 播放
mPlayer.start();
// 改变状态
status = 0x12;
}
break;
// 停止声音
case 2:
// 如果原来正在播放或暂停
if (status == 0x12 || status == 0x13)
{
// 停止播放
mPlayer.stop();
status = 0x11;
}
}
// 发送广播通知Activity更改图标、文本框
Intent sendIntent = new Intent(MusicBox.UPDATE_ACTION);
sendIntent.putExtra("update", status);
sendIntent.putExtra("current", current);
// 发送广播 ,将被Activity组件中的BroadcastReceiver接收到
sendBroadcast(sendIntent);
}
}
private void prepareAndPlay(String music)
{
try
{
// 打开指定音乐文件
AssetFileDescriptor afd = am.openFd(music);
mPlayer.reset();
// 使用MediaPlayer加载指定的声音文件。
mPlayer.setDataSource(afd.getFileDescriptor(),
afd.getStartOffset(), afd.getLength());
// 准备声音
mPlayer.prepare();
// 播放
mPlayer.start();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}