1. 程式人生 > >從一個音樂播放器來了解android的Service元件和BroadcastReceiver

從一個音樂播放器來了解android的Service元件和BroadcastReceiver

從一個音樂播放器來理解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);
    }
}