Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 扣丁學堂(六)——音樂播放獨立頁面的實現

扣丁學堂(六)——音樂播放獨立頁面的實現

編輯:關於Android編程

一丶音樂播放頁實現功能

1.音樂格信息顯示,大圖顯示

2.播放功能,上一曲,下一曲,暫停

3.音樂進度顯示

4.切換播放模式

二丶顯示效果

\

三丶原理及代碼實現

1.自定義接口回調的方法實現UI狀態切換(進度位置,播放那一首歌)

2.seekbar實現歌曲進度同步及監聽

3.service統一實現Activity,Fragment的播放功能及UI圖片統一

4.BaseActivity基類統一實現服務綁定,音樂播放狀態,直接調用MusicPlayService

代碼實現

activity_play_ui.xml
 

<!--?xml version="1.0" encoding="utf-8"?-->
<relativelayout android:background="@drawable/skin2" android:layout_height="match_parent" android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android">

    <relativelayout android:id="@+id/relativeLayout" android:layout_height="wrap_content" android:layout_width="match_parent">

        <imageview android:id="@+id/iv_pull_down" android:layout_centervertical="true" android:layout_height="20dp" android:layout_marginleft="10dp" android:layout_width="wrap_content" android:src="@drawable/backtrack">

        <linearlayout android:gravity="center" android:id="@+id/ll_play_ui_top" android:layout_height="wrap_content" android:layout_margintop="5dp" android:layout_toleftof="@+id/iv_share" android:layout_torightof="@+id/iv_pull_down" android:layout_width="match_parent" android:orientation="vertical">

            <textview android:id="@+id/tv_play_ui_song" android:layout_height="wrap_content" android:layout_width="wrap_content" android:text="聽媽媽的話" android:textcolor="@color/white" android:textsize="18sp">

            <textview android:id="@+id/tv_play_ui_artist" android:layout_height="wrap_content" android:layout_width="wrap_content" android:paddingtop="5dp" android:text="周傑倫" android:textcolor="#c1c1c1">

        </textview></textview></linearlayout>

        <imageview android:id="@+id/iv_share" android:layout_alignparentright="true" android:layout_centervertical="true" android:layout_height="25dp" android:layout_marginright="10dp" android:layout_width="wrap_content" android:src="@drawable/share">
    </imageview></imageview></relativelayout>

    <linearlayout android:id="@+id/linearLayout" android:layout_alignparentbottom="true" android:layout_height="wrap_content" android:layout_width="match_parent" android:orientation="vertical">

        <relativelayout android:layout_height="wrap_content" android:layout_width="match_parent">

            <textview android:id="@+id/tv_play_ui_play_time" android:layout_centervertical="true" android:layout_height="wrap_content" android:layout_marginleft="10dp" android:layout_width="wrap_content" android:text="00:00" android:textcolor="@color/white">

            <seekbar android:id="@+id/sb_play_ui_seekbar" android:layout_height="wrap_content" android:layout_toleftof="@+id/tv_play_ui_end_time" android:layout_torightof="@+id/tv_play_ui_play_time" android:layout_width="match_parent" android:thumb="@drawable/seekbar_cycle">

            <textview android:id="@+id/tv_play_ui_end_time" android:layout_alignparentright="true" android:layout_centervertical="true" android:layout_height="wrap_content" android:layout_marginright="10dp" android:layout_width="wrap_content" android:text="00:00" android:textcolor="@color/white">
        </textview></seekbar></textview></relativelayout>

        <linearlayout android:gravity="center_vertical" android:layout_height="wrap_content" android:layout_marginleft="30dp" android:layout_marginright="30dp" android:layout_margintop="20dp" android:layout_width="match_parent" android:orientation="horizontal">

            <imageview android:id="@+id/iv_play_ui_play_mode" android:layout_height="30dp" android:layout_weight="1" android:layout_width="wrap_content" android:src="@drawable/list_cycle">

            <imageview android:id="@+id/iv_play_ui_previous" android:layout_height="wrap_content" android:layout_weight="1" android:layout_width="wrap_content" android:src="@drawable/previous">

            <imageview android:id="@+id/iv_play_ui_play" android:layout_height="wrap_content" android:layout_weight="1" android:layout_width="wrap_content" android:src="@drawable/play">

            <imageview android:id="@+id/iv_play_ui_next" android:layout_height="wrap_content" android:layout_weight="1" android:layout_width="wrap_content" android:src="@drawable/next">

            <imageview android:id="@+id/iv_play_ui_menu" android:layout_height="35dp" android:layout_weight="1" android:layout_width="wrap_content" android:src="@drawable/menu">
        </imageview></imageview></imageview></imageview></imageview></linearlayout>

        <linearlayout android:layout_height="wrap_content" android:layout_marginbottom="10dp" android:layout_marginleft="70dp" android:layout_marginright="70dp" android:layout_margintop="20dp" android:layout_width="match_parent">

            <imageview android:id="@+id/iv_play_ui_like" android:layout_height="25dp" android:layout_weight="1" android:layout_width="wrap_content" android:src="@drawable/like">

            <imageview android:id="@+id/iv_play_ui_download" android:layout_height="25dp" android:layout_weight="1" android:layout_width="wrap_content" android:src="@drawable/download">

            <imageview android:id="@+id/iv_play_ui_add" android:layout_height="28dp" android:layout_weight="1" android:layout_width="wrap_content" android:src="@drawable/add">

        </imageview></imageview></imageview></linearlayout>

    </linearlayout>

    <imageview android:background="#00FFFFFF" android:id="@+id/iv_ablum2" android:layout_below="@+id/relativeLayout" android:layout_height="250dp" android:layout_margintop="25dp" android:layout_width="match_parent">


</imageview></relativelayout>

PlayUIActivity.java

 

 

public class PlayUIActivity extends BaseActivity implements View.OnClickListener{

    private ImageView iv_pull_down,iv_play_ui_play,iv_play_ui_next,iv_play_ui_previous,iv_play_ui_play_mode,iv_ablum2;
    private TextView tv_play_ui_song,tv_play_ui_artist,tv_play_ui_end_time,tv_play_ui_play_time;
    private ArrayList mp3Infos;
    private SeekBar sb_play_ui_seekbar;
    private static final int UPDATE_TIME = 0x1;
    private static MyHandler myHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_play_ui);
        iv_pull_down = (ImageView)findViewById(R.id.iv_pull_down);
        iv_ablum2 = (ImageView)findViewById(R.id.iv_ablum2);
        tv_play_ui_song = (TextView)findViewById(R.id.tv_play_ui_song);
        tv_play_ui_artist = (TextView)findViewById(R.id.tv_play_ui_artist);
        tv_play_ui_end_time = (TextView)findViewById(R.id.tv_play_ui_end_time);
        tv_play_ui_play_time = (TextView)findViewById(R.id.tv_play_ui_play_time);
        iv_play_ui_play = (ImageView)findViewById(R.id.iv_play_ui_play);
        iv_play_ui_next = (ImageView)findViewById(R.id.iv_play_ui_next);
        iv_play_ui_previous = (ImageView)findViewById(R.id.iv_play_ui_previous);
        iv_play_ui_play_mode = (ImageView)findViewById(R.id.iv_play_ui_play_mode);
        sb_play_ui_seekbar = (SeekBar)findViewById(R.id.sb_play_ui_seekbar);
        iv_pull_down.setOnClickListener(this);
        iv_play_ui_play.setOnClickListener(this);
        iv_play_ui_next.setOnClickListener(this);
        iv_play_ui_previous.setOnClickListener(this);
        iv_play_ui_play_mode.setOnClickListener(this);
        mp3Infos = MediaUtils.getMp3Infos(this);
        myHandler = new MyHandler(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    protected void onResume() {
        super.onResume();
        bindMusicPlayService();
    }

    @Override
    protected void onPause() {
        super.onPause();
        unbindMusicPlayService();
    }

    /**
     * 進度條控件已經內部處理過了,開始時間的改變是在子線程中改變主線程的UI,這當然是不可以的
     * 怎麼辦呢,用你最熟悉的Handler處理吧
     */
    static class MyHandler extends android.os.Handler{
        //內部類去要想使用外部類的權限,就得把外部類拿進來
        private PlayUIActivity playUIActivity;
        public MyHandler(PlayUIActivity playUIActivity){
            this.playUIActivity = playUIActivity;
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if(playUIActivity!=null){
                switch (msg.what){
                    case UPDATE_TIME:
                        playUIActivity.tv_play_ui_play_time.setText(MediaUtils.formatTime(msg.arg1));
                        break;
                }
            }
        }
    }

    //這裡是子線程,不斷的發送msg給主線程,通知其更改UI
    @Override
    public void publish(int progress) {
        Message msg = myHandler.obtainMessage(UPDATE_TIME);
        msg.arg1 = progress;
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        myHandler.sendMessage(msg);
        sb_play_ui_seekbar.setProgress(progress);
    }

    @Override
    public void change(int position) {
        Mp3Info mp3Info = mp3Infos.get(position);
        tv_play_ui_song.setText(mp3Info.getTitle());
        tv_play_ui_artist.setText(mp3Info.getArtist());
        tv_play_ui_end_time.setText(MediaUtils.formatTime(mp3Info.getDuration()));
        iv_play_ui_play.setImageResource(R.drawable.pause);
        //獲取專輯封面圖片
        Bitmap albumBitmap = MediaUtils.getArtwork(this, mp3Info.getId(), mp3Info.getAlbumId(), true, false);
        //改變播放界面專輯封面圖片
        iv_ablum2.setImageBitmap(albumBitmap);
        sb_play_ui_seekbar.setProgress(0);
        sb_play_ui_seekbar.setMax((int)mp3Info.getDuration());
        if(musicPlayService.isPlaying()){
            iv_play_ui_play.setImageResource(R.drawable.pause);
        }else {
            iv_play_ui_play.setImageResource(R.drawable.play);
        }


        switch (musicPlayService.getPlay_mode()){
            case MusicPlayService.ORDER_PLAY:
                iv_play_ui_play_mode.setImageResource(R.drawable.list_cycle);
                //iv_play_ui_play_mode.setTag(MusicPlayService.ORDER_PLAY);
                break;
            case MusicPlayService.RANDOM_PLAY:
                iv_play_ui_play_mode.setImageResource(R.drawable.random);
                //iv_play_ui_play_mode.setTag(MusicPlayService.RANDOM_PLAY);
                break;
            case MusicPlayService.SINGLE_PLAY:
                iv_play_ui_play_mode.setImageResource(R.drawable.single_cycle);
                //iv_play_ui_play_mode.setTag(MusicPlayService.SINGLE_PLAY);
                break;
            default:
                break;
        }

    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.iv_pull_down:
                finish();
                overridePendingTransition(R.anim.abc_fade_in, R.anim.abc_fade_out);
                break;
            case R.id.iv_play_ui_play:
                if(musicPlayService.isPlaying()){
                    musicPlayService.pause();
                    iv_play_ui_play.setImageResource(R.drawable.play);
                }else{
                    if(musicPlayService.isPause()){
                        musicPlayService.start();
                        iv_play_ui_play.setImageResource(R.drawable.pause);
                    }else{
                        musicPlayService.play(0);
                    }
                }
                break;
            case R.id.iv_play_ui_previous:
                musicPlayService.previous();
                break;
            case R.id.iv_play_ui_next:
                musicPlayService.next();
                break;
            case R.id.iv_play_ui_play_mode:
                switch (musicPlayService.getPlay_mode()){
                    case MusicPlayService.ORDER_PLAY:
                        iv_play_ui_play_mode.setImageResource(R.drawable.random);
                        musicPlayService.setPlay_mode(MusicPlayService.RANDOM_PLAY);
                        break;
                    case MusicPlayService.RANDOM_PLAY:
                        iv_play_ui_play_mode.setImageResource(R.drawable.single_cycle);
                        musicPlayService.setPlay_mode(MusicPlayService.SINGLE_PLAY);
                        break;
                    case MusicPlayService.SINGLE_PLAY:
                        iv_play_ui_play_mode.setImageResource(R.drawable.list_cycle);
                        musicPlayService.setPlay_mode(MusicPlayService.ORDER_PLAY);
                }
                break;
            default:
                break;

        }
    }
}
BaseActivity.java

 

 

/**
 * 自定義基礎activity,用來讓其他activity繼承,作為工具activity,用於綁定服務
 */
public abstract class BaseActivity extends FragmentActivity {

    protected MusicPlayService musicPlayService;
    private boolean isBound = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            MusicPlayService.PlayBinder playBinder = (MusicPlayService.PlayBinder)iBinder;
            musicPlayService = playBinder.getMusicPlayService();
            musicPlayService.setMusicUpdateListener(musicUpdateListener);
            //綁定成功後調用監聽onChange方法
            musicUpdateListener.onChange(musicPlayService.getCurrentPosition());
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            musicPlayService = null;
            isBound = false;
        }
    };

    private MusicPlayService.MusicUpdateListener musicUpdateListener = new MusicPlayService.MusicUpdateListener(){
        @Override
        public void onPublish(int progress) {
            publish(progress);
        }

        @Override
        public void onChange(int position) {
            change(position);
        }
    };

    public abstract void publish(int progress);
    public abstract void change(int position);

    //綁定服務
    public void bindMusicPlayService(){
        if(!isBound){
            Intent intent = new Intent(this,MusicPlayService.class);
            bindService(intent,conn,BIND_AUTO_CREATE);
            isBound = true;
        }

    }

    //解除綁定服務
    public void unbindMusicPlayService(){
        if(isBound){
            unbindService(conn);
            isBound = false;
        }

    }
}
MusicPlayService.java

 

 

/**
 * 實現功能:
 * 1、點擊列表上的某首歌播放
 * 2、點擊播放按鈕,從暫停轉為播放狀態
 * 3、點擊暫停按鈕,從播放狀態轉為暫停狀態
 * 4、上一首
 * 5、下一首
 * 6、播放進度顯示
 * 7、播放模式
 */
public class  MusicPlayService extends Service implements MediaPlayer.OnCompletionListener,MediaPlayer.OnErrorListener{

    private MediaPlayer mediaPlayer;
    private ArrayList mp3Infos;
    private int currentPosition;//列表當前位置
    private MusicUpdateListener musicUpdateListener;//設置屬性
    private boolean isPause = false;

    //順序播放、單曲循環、隨機播放
    public static final int ORDER_PLAY = 1;
    public static final int RANDOM_PLAY = 2;
    public static final int SINGLE_PLAY = 3;
    public int play_mode = ORDER_PLAY;


    //用於設置或者獲得播放模式
    public int getPlay_mode() {
        return play_mode;
    }

    public void setPlay_mode(int play_mode) {
        this.play_mode = play_mode;
    }


    //在fragment或者activity中輕松獲得狀態
    public boolean isPause(){
        return isPause;
    }

    //開啟線程池
    private ExecutorService es = Executors.newSingleThreadExecutor();

    Runnable updateStatusRunnable = new Runnable() {
        @Override
        public void run() {
            while (true){
                if(musicUpdateListener!=null&&mediaPlayer!=null&&mediaPlayer.isPlaying()){
                    musicUpdateListener.onPublish(getCurrentProgress());
                }
            }
        }
    };

    public MusicPlayService() {

    }

    Random random = new Random();
    //用於監聽當前歌曲播放完後,下一首該如何播放
    @Override
    public void onCompletion(MediaPlayer mediaPlayer) {
        switch (play_mode){
            case ORDER_PLAY:
                next();
                break;
            case RANDOM_PLAY:
                play(random.nextInt(mp3Infos.size()));
                break;
            case SINGLE_PLAY:
                play(currentPosition);
                break;
            default:
                break;
        }
    }

    @Override
    public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
        mediaPlayer.reset();
        return false;
    }

    class PlayBinder extends Binder{
        public MusicPlayService getMusicPlayService(){
            return MusicPlayService.this;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mediaPlayer = new MediaPlayer();
        mp3Infos = MediaUtils.getMp3Infos(this);
        mediaPlayer.setOnCompletionListener(this);
        mediaPlayer.setOnErrorListener(this);
        //在進入每一個綁定service時,就監聽進度改變事件,而狀態改變監聽則是在啟動播放的時候
        es.execute(updateStatusRunnable);
    }

    //啟動線程就得銷毀
    @Override
    public void onDestroy() {
        super.onDestroy();
        if(es!=null && es.isTerminated()){
            es.shutdown();
            es = null;
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new PlayBinder();
    }

    //點擊列表上的某首歌播放
    public void play(int position){
        if(position>=0 && position= mp3Infos.size()-1){
            currentPosition = 0;
        }else{
            currentPosition++;
        }
        play(currentPosition);
    }

    //上一首
    public void previous(){
        if(currentPosition<=0){
            currentPosition = mp3Infos.size()-1;
        }else{
            currentPosition--;
        }
        play(currentPosition);
    }

    //更新狀態的接口
    public interface MusicUpdateListener{
        public void onPublish(int progress);
        public void onChange(int position);
    }

    public void setMusicUpdateListener(MusicUpdateListener musicUpdateListener) {
        this.musicUpdateListener = musicUpdateListener;
    }

    //在音樂播放中,獲得播放的位置信息
    public int getDuration(){
        return mediaPlayer.getDuration();
    }

    //跳轉到某個地方
    public void seekTo(int msec){
        mediaPlayer.seekTo(msec);
    }

    //返回當前的位置
    public int getCurrentPosition(){

        return currentPosition;
    }

    //獲得當前位置
    public int getCurrentProgress(){
        if(mediaPlayer!=null && mediaPlayer.isPlaying()){
            return mediaPlayer.getCurrentPosition();
        }
        return 0;
    }

    //反饋狀態
    public boolean isPlaying(){
        if(mediaPlayer!=null&&mediaPlayer.isPlaying()){
            return mediaPlayer.isPlaying();
        }
        return false;
    }


}

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved