BroadcastReceiver:
activity和service之间的数据通信,开线程发送广播通知组件更新UI
sample1:广播实例,启动线程发送广播并在广播处理器里更新UI
//在TApplication启动线程CallLogDataThread:
CallLogDataThread mCallLogDataThread = new CallLogDataThread(0);
mCallLogDataThread.start();
//CallLogDataThread线程中发送广播:
TApplication.CallLogListData = CallLogDataUtils
.getCallLogListData(filterType);
// 发送广播(驻留)
TApplication.MY_SELF.sendStickyBroadcast(new Intent(
TApplication.CALL_LOG_DATA_UP_ACTION));
// 调用方法更新有无头像,用于更新通话记录对应联系人姓名和头像
CallLogDataUtils
.setCallLogListContactsInfo(TApplication.CallLogListData);
// 发送广播(驻留)
TApplication.MY_SELF.sendStickyBroadcast(new Intent(
TApplication.CALL_LOG_DATA_UP_ACTION));
//在CallLogFragment中创建广播接收器,注册并更新数据
//注册广播
UpCallLogListReceiver mUpCallLogListReceiver;
// 注册广播
mUpCallLogListReceiver = new UpCallLogListReceiver();
getActivity().registerReceiver(mUpCallLogListReceiver,
new IntentFilter(TApplication.CALL_LOG_DATA_UP_ACTION));
//创建广播接收器
class UpCallLogListReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
// 更新UI
mCallLogListAdapter.changeData(TApplication.CallLogListData);
mCallLogListAdapter.notifyDataSetChanged();
}
}
sample2:广播实例,发送广播传递数据
//在MusicPlayerActivity发送广播:
//需要传输的数据,这里指用户拖动的进度值sbProgress.setOnSeekBarChangeListener代码
Intent intent = new Intent(GlobalUtils.ACTION_SEEK_TO);
intent.putExtra(GlobalUtils.EXTRA_PROGRESS, progress);
sendBroadcast(intent);
//button点击事件
Intent intent = new Intent();
switch (v.getId()) {
case R.id.btnPrevious:// 上一首
intent.setAction(GlobalUtils.ACTION_PREVIOUS);
break;
case R.id.btnPlay:// 播放或暂停
String text = btnPlay.getText().toString();
if ("播 放".equals(text)) {
intent.setAction(GlobalUtils.ACTION_PLAY);
} else if ("暂 停".equals(text)) {
Log.i("info", text);
intent.setAction(GlobalUtils.ACTION_PAUSE);
}
break;
case R.id.btnNext:// 下一首
intent.setAction(GlobalUtils.ACTION_NEXT);
break;
}
sendBroadcast(intent);
//系统菜单事件
Intent intent = new Intent();
switch (item.getItemId()) {//播放模式是由用户选择的,所以在这里发广播.
case R.id.sub_menu_loop:// 循环播放
intent.setAction(GlobalUtils.ACTION_PLAYMODE_CHANGED);
intent.putExtra(GlobalUtils.EXTRA_PLAY_MODE,
GlobalUtils.PLAY_MODE_LOOP);
break;
case R.id.sub_menu_random:// 随机播放
intent.setAction(GlobalUtils.ACTION_PLAYMODE_CHANGED);
intent.putExtra(GlobalUtils.EXTRA_PLAY_MODE,
GlobalUtils.PLAY_MODE_RANDOM);
break;
case R.id.menu_opts_flush:// 刷新
intent.setAction(Intent.ACTION_MEDIA_MOUNTED);
intent.setData(Uri.parse("file://"
+ Environment.getExternalStorageDirectory()));
break;
case R.id.menu_opts_exit:// 退出
intent = new Intent(this, MusicPlayService.class);
stopService(intent);
intent = new Intent(GlobalUtils.ACTION_STOP);
finish();
break;
}
sendBroadcast(intent);
//onResume()方法中
// 发送更新状态变更广播,音乐还在播放,界面退出后而返回,音乐名和时长没更新.设置为true,就执行界面更新.
Intent intent = new Intent(GlobalUtils.ACTION_UPDATE_STATE_CHANGED);
intent.putExtra(GlobalUtils.EXTRA_UPDATE_STATE, true);
sendBroadcast(intent);
// 发送获取请求播放状态的广播,界面退出后,能保存先前的按钮的状态,播放或暂停,回环广播
intent = new Intent(GlobalUtils.ACTION_GET_PLAY_STATE);
sendBroadcast(intent);
//onPause()方法中
// 发送更新状态变更广播,音乐还在播放,界面退出后而返回,更新播放按钮的状态,当暂停时(false).这里是不需要更新界面.
Intent intent = new Intent(GlobalUtils.ACTION_UPDATE_STATE_CHANGED);
intent.putExtra(GlobalUtils.EXTRA_UPDATE_STATE, false);
sendBroadcast(intent);
//在MusicPlayService中注册广播并处理MusicPlayerActivity发送的广播:
// 初始化广播接收器注册动态广播
receiver = new InnerReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(GlobalUtils.ACTION_PLAY);
filter.addAction(GlobalUtils.ACTION_PREVIOUS);
filter.addAction(GlobalUtils.ACTION_PAUSE);
filter.addAction(GlobalUtils.ACTION_NEXT);
filter.addAction(GlobalUtils.ACTION_PLAYMODE_CHANGED);//播放模式.
filter.addAction(GlobalUtils.ACTION_SEEK_TO);//用户拖动的滚动条位置.
filter.addAction(GlobalUtils.ACTION_UPDATE_STATE_CHANGED);// 更新状态变更(音乐名和时长的更新.)
filter.addAction(GlobalUtils.ACTION_GET_PLAY_STATE);//播放或暂停变更显示.
registerReceiver(receiver, filter);
// 广播接收处理器--处理对应的广播
private class InnerReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (GlobalUtils.ACTION_PLAY.equals(action)) {
play();
} else if (GlobalUtils.ACTION_PAUSE.equals(action)) {
pause();
} else if (GlobalUtils.ACTION_PREVIOUS.equals(action)) {
previous();
} else if (GlobalUtils.ACTION_NEXT.equals(action)) {
next();
} else if (GlobalUtils.ACTION_SEEK_TO.equals(action)) {
if (isPause || player.isPlaying()) {
int position = intent.getIntExtra(
GlobalUtils.EXTRA_PROGRESS, -1);
if (position != -1) {
seekTo(position * player.getDuration() / 100);// 定位到用户拖动滚动条的位置后播放.
}
}
} else if (GlobalUtils.ACTION_PLAYMODE_CHANGED.equals(action)) {
playMode = intent.getIntExtra(GlobalUtils.EXTRA_PLAY_MODE,
GlobalUtils.PLAY_MODE_LOOP);// 默认循环播放.
} else if (GlobalUtils.ACTION_UPDATE_STATE_CHANGED.equals(action)) {
needUpdate = intent.getBooleanExtra(
GlobalUtils.EXTRA_UPDATE_STATE, true);//音乐名,时长,播放暂停按钮的状态更新.设置为true,就是需要更新.
synchronized (thread) {
thread.notify();
}
} else if (GlobalUtils.ACTION_GET_PLAY_STATE.equals(action)) {//这是回环广播.
// 发送播放状态广播,音乐还在播放,界面退出后而返回,播放按钮没更新.
// 发送到MusicPlayerActivity中的onCreate()方法中的动态注册广播处并在InnerReceiver里处理
Intent intent1 = new Intent(GlobalUtils.ACTION_PLAY_STATE);
intent1.putExtra(GlobalUtils.EXTRA_PLAY_STATE, player
.isPlaying());
sendBroadcast(intent1);
}
}
}
sample3:广播实例
//在MusicPlayService中发送广播:
//play()方法中
//播放音乐是在这里发生的,所以将播放的音乐信息发广播传递到界面进行显示.发送音乐变更广播给Activity和MusicAppProvider,当音乐库发生变化时,更新到MusicPlayerActivity
Intent intent = new Intent(GlobalUtils.ACTION_CURRENT_MUSIC_CHANGED);
intent.putExtra(GlobalUtils.EXTRA_CURRENT_MUSIC, app.getMusics().get(currentIndex));
sendBroadcast(intent);
// 发送播放状态广播,和 pause()里的广播配合使用,用于按钮字的不同显示.(播放/暂停)
Intent intent1 = new Intent(GlobalUtils.ACTION_PLAY_STATE);
intent1.putExtra(GlobalUtils.EXTRA_PLAY_STATE, player.isPlaying());
sendBroadcast(intent1);
//pause()方法中
//发送播放状态广播,和play()里的广播配合使用,用于按钮字的不同显示.(播放/暂停)
Intent intent1 = new Intent(GlobalUtils.ACTION_PLAY_STATE);
intent1.putExtra(GlobalUtils.EXTRA_PLAY_STATE, player.isPlaying());
sendBroadcast(intent1);
//seekTo()方法中
// 手动拨动拖动条发送播放状态广播
Intent intent1 = new Intent(GlobalUtils.ACTION_PLAY_STATE);
intent1.putExtra(GlobalUtils.EXTRA_PLAY_STATE, player.isPlaying());
sendBroadcast(intent1);
//onCreate()方法中
// 创建工作线程,每秒更新播放进度,进而让界面的滚动条动起来.
isLoop = true;
needUpdate = true;
thread = new Thread() {
public void run() {
// TODO Auto-generated method stub
while (isLoop) {
if (needUpdate && player.isPlaying()) {
// 发送更新进度条广播.让滚动条动起来.在这里发广播是因为播放引起的滚动条移动就是在这里发生的.
Intent intent = new Intent(GlobalUtils.ACTION_UPDATE_PROGRESS);
intent.putExtra(GlobalUtils.EXTRA_PROGRESS, player.getCurrentPosition());
intent.putExtra(GlobalUtils.EXTRA_DURATION, player.getDuration());
intent.putExtra(GlobalUtils.EXTRA_MUSIC_NAME, app.getMusics().get(app.getCurrentIndex()).getName());
sendBroadcast(intent);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
};
thread.start();
//在MusicPlayerActivity中注册广播并处理MusicPlayService发送的广播:
// 创建广播接收器对象和 filter对象,系统广播,为了刷新----动态注册广播
receiver = new InnerReceiver();
filter = new IntentFilter();
filter.addAction(Intent.ACTION_MEDIA_SCANNER_FINISHED);
filter.addAction(Intent.ACTION_MEDIA_SCANNER_STARTED);
filter.addDataScheme("file");
// 音乐播放相关广播,这里没有协议,自定义广播------动态注册广播
receiver1 = new InnerReceiver();
filter1 = new IntentFilter();
filter1.addAction(GlobalUtils.ACTION_CURRENT_MUSIC_CHANGED);
filter1.addAction(GlobalUtils.ACTION_UPDATE_PROGRESS);
filter1.addAction(GlobalUtils.ACTION_PLAY_STATE);
// 广播接收处理器,处理MusicPlayService发送的广播
private class InnerReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_MEDIA_SCANNER_STARTED.equals(action)) {// 开始扫描sdcard
dialog.show();
} else if (Intent.ACTION_MEDIA_SCANNER_FINISHED.equals(action)) {// sdcard扫描结束
dialog.dismiss();
// 获取最近的播放列表信息
ArrayList<Music> musics = new MusicBiz(MusicPlayerActivity.this)
.getLocalMusics();
app.setMusics(musics);// 更新共享的播放列表数据,更新数据.
adapter.changeDataSet(musics);// 更新界面
} else if (GlobalUtils.ACTION_CURRENT_MUSIC_CHANGED.equals(action)) {
// 获取当前播放的音乐信息
Music music = (Music) intent
.getSerializableExtra(GlobalUtils.EXTRA_CURRENT_MUSIC);
tvName.setText(music.getName());// 更新音乐显示信息
} else if (GlobalUtils.ACTION_UPDATE_PROGRESS.equals(action)) {
// 获取 当前进度 总时长 和音乐名
int duration = intent.getIntExtra(GlobalUtils.EXTRA_DURATION,
-1);// 总时长
int progress = intent.getIntExtra(GlobalUtils.EXTRA_PROGRESS,
-1);// 当前进度
String name = intent
.getStringExtra(GlobalUtils.EXTRA_MUSIC_NAME);// 音乐名
// 设置文本框中的内容
tvName.setText(name);
// 设置文本框中的内容
tvProgress.setText(GlobalUtils.formatTime(progress));
tvDuration.setText(GlobalUtils.formatTime(duration));
sbProgress.setProgress(progress * 100 / duration);// 设置进度条
} else if (GlobalUtils.ACTION_PLAY_STATE.endsWith(action)) {
// 用于按钮之间文本切换
boolean playState = intent.getBooleanExtra(
GlobalUtils.EXTRA_PLAY_STATE, false);//播放状态默认暂停的
if (playState) {
btnPlay.setText("暂 停");
} else {
btnPlay.setText("播 放");
}
}
}
}
//在AndroidManifest.xml静态注册和MusicAppWidgetProvider中处理MusicPlayService发送的广播(ACTION_CURRENT_MUSIC_CHANGED):
public class MusicAppWidgetProvider extends AppWidgetProvider {
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
String action = intent.getAction();
RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.provider_music);
ComponentName provider = new ComponentName(context,MusicAppWidgetProvider.class);
AppWidgetManager manager = AppWidgetManager.getInstance(context);
if (GlobalUtils.ACTION_CURRENT_MUSIC_CHANGED.equals(action)) {
// 当前音乐.
Music music = (Music) intent.getSerializableExtra(GlobalUtils.EXTRA_CURRENT_MUSIC);
views.setTextViewText(R.id.tvMusicName_Provider, music.getName());
views.setTextViewText(R.id.tvSinger_Provider, music.getSinger());
manager.updateAppWidget(provider, views);
} else if (GlobalUtils.ACTION_STOP.equals(action)) {
views.setTextViewText(R.id.tvMusicName_Provider, "音乐名");
views.setTextViewText(R.id.tvSinger_Provider, "歌手");
manager.updateAppWidget(provider, views);
}
}
}