從一個音樂播放器來了解android的Service元件和BroadcastReceiver
阿新 • • 發佈:2019-02-15
從一個音樂播放器來理解android的Service元件和BroadcastReceiver
- 前言:很久以前寫過一個音樂播放器,採用Service元件實現後臺播放,BroadcastReceiver實現訊息傳遞。播放器原始碼在此:簡陋音樂播放器。
- MusicBox.java
package org.crazyit.broadcast;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
public class MusicBox extends Activity implements OnClickListener {
// 獲取介面中顯示歌曲標題、作者文字框
TextView title, author;
// 播放/暫停、停止按鈕
ImageButton play, stop;
// 宣告音量管理器
public AudioManager mAudioManager = null;
// 定義進度條
public static SeekBar audioSeekBar = null;
// 定義音量大小
public SeekBar audioVolume = null;
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);
audioVolume = (SeekBar) findViewById(R.id.seekBar2);
audioSeekBar = (SeekBar) findViewById(R.id.seekBar1);
// 為兩個按鈕的單擊事件新增監聽器
play.setOnClickListener(this);
stop.setOnClickListener(this);
// 播放進度監聽
audioSeekBar.setOnSeekBarChangeListener(new SeekBarChangeEvent());
// 退出後再次進去程式時,進度條保持持續更新
if (MusicService.mPlayer != null) {
// 設定進度條的最大值
MusicBox.audioSeekBar.setMax(MusicService.mPlayer.getDuration());
audioSeekBar.setProgress(MusicService.mPlayer.getCurrentPosition());
}
// 得到當前音量物件
mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
// 把當前音量值賦給進度條
audioVolume.setProgress(mAudioManager
.getStreamVolume(AudioManager.STREAM_MUSIC));
// 監聽音量
audioVolume.setOnSeekBarChangeListener(new AudioVolumeChangeEvent());
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);
}
// 音量監聽
class AudioVolumeChangeEvent implements SeekBar.OnSeekBarChangeListener {
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, progress,
0);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
}
// 播放進度監聽,別忘了Service裡面還有個進度條重新整理
class SeekBarChangeEvent implements SeekBar.OnSeekBarChangeListener {
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// 假設改變源於使用者拖動
if (fromUser) {
MusicService.mPlayer.seekTo(progress);
// 當進度條的值改變時,音樂播放器從新的位置開始播放
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
MusicService.mPlayer.pause();
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
MusicService.mPlayer.start();
}
}
// 自定義的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);
}
}
- MusicService.java
package org.crazyit.broadcast;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.SeekBar;
import android.widget.TextView;
public class MusicBox extends Activity implements OnClickListener {
// 獲取介面中顯示歌曲標題、作者文字框
TextView title, author;
// 播放/暫停、停止按鈕
ImageButton play, stop;
// 宣告音量管理器
public AudioManager mAudioManager = null;
// 定義進度條
public static SeekBar audioSeekBar = null;
// 定義音量大小
public SeekBar audioVolume = null;
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);
audioVolume = (SeekBar) findViewById(R.id.seekBar2);
audioSeekBar = (SeekBar) findViewById(R.id.seekBar1);
// 為兩個按鈕的單擊事件新增監聽器
play.setOnClickListener(this);
stop.setOnClickListener(this);
// 播放進度監聽
audioSeekBar.setOnSeekBarChangeListener(new SeekBarChangeEvent());
// 退出後再次進去程式時,進度條保持持續更新
if (MusicService.mPlayer != null) {
// 設定進度條的最大值
MusicBox.audioSeekBar.setMax(MusicService.mPlayer.getDuration());
audioSeekBar.setProgress(MusicService.mPlayer.getCurrentPosition());
}
// 得到當前音量物件
mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
// 把當前音量值賦給進度條
audioVolume.setProgress(mAudioManager
.getStreamVolume(AudioManager.STREAM_MUSIC));
// 監聽音量
audioVolume.setOnSeekBarChangeListener(new AudioVolumeChangeEvent());
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);
}
// 音量監聽
class AudioVolumeChangeEvent implements SeekBar.OnSeekBarChangeListener {
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, progress,
0);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
}
// 播放進度監聽,別忘了Service裡面還有個進度條重新整理
class SeekBarChangeEvent implements SeekBar.OnSeekBarChangeListener {
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// 假設改變源於使用者拖動
if (fromUser) {
MusicService.mPlayer.seekTo(progress);
// 當進度條的值改變時,音樂播放器從新的位置開始播放
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
MusicService.mPlayer.pause();
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
MusicService.mPlayer.start();
}
}
// 自定義的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);
}
}