1. 程式人生 > >Android 後臺播放音樂Demo

Android 後臺播放音樂Demo

 

開發流程:

A,建立服務把想使用的方法暴露出來。

B,定義介面,bind呼叫時返回物件,在service 開啟播放音樂實時更新進度條的位置

C,Activity 中建立hander 更新UI

【1】佈局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical"

    tools:context=".MainActivity" >



    <Button

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:onClick="click1"

        android:text="播放" />

    

     <Button

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:onClick="click2"

        android:text="暫停" />

     

      <Button

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:onClick="click3"

        android:text="繼續播放" />



      <SeekBar

          android:id="@+id/seekBar1"

          android:layout_width="match_parent"

          android:layout_height="wrap_content" />



</LinearLayout>

【2】建立介面

interface Iservice {

//把想暴露的方法定義在接口裡

public void callplayMusic();

public void callpauseMusic();

public void callrePlayMusic();

public void callplaySeekToPosition(int position);

}

 

【3】建立Service 

    A,onCredte 方法中是用MediaPlayer

    B,為了呼叫Service 裡面方法 Bind開啟服務,提供Binder 物件 呼叫裡面方法

    C,定義方法,使用Binder的子類暴露出去。

public class MusicService extends Service {

    private Timer timer;

    private TimerTask task;

    private MediaPlayer mediaPlayer;

    //[2]把我們定義的中間人物件返回

    @Override

    public IBinder onBind(Intent intent) {

        return new MyBinder();

    }



    @Override

    public void onCreate() {

        

        //[1]播放sd卡里面的小蘋果音樂

        mediaPlayer = new MediaPlayer();

        super.onCreate();

    }

    

    // 播放音樂的方法

    public void playMusic() {

        try {

            //[2]設定播放音樂的路徑  設定資料 原:在sd卡

            mediaPlayer.setDataSource("/mnt/sdcard/xpg.mp3");

            //[3]準備播放

            mediaPlayer.prepare();

            //[4]播放音樂

            mediaPlayer.start();

            //[5]歌曲播放的同時 更新進度條

            updateSeekBar();

            

        } catch (Exception e) {

            e.printStackTrace();

        }

    }



    //更新進度條的方法

    private void updateSeekBar() {

        //[1]獲取當前歌曲的總時長

        final int duration = mediaPlayer.getDuration();

        //[2]要不停的獲取當前歌曲播放的進度  計時器 Timer

        timer = new Timer();

        task = new TimerTask() {

            @Override

            public void run() {

                int currentPosition = mediaPlayer.getCurrentPosition();

                //[3]更新進度條

                Message msg = Message.obtain();

                //[4]準備bundle

                Bundle bundle = new Bundle(); //實際就是map

                bundle.putInt("duration", duration);

                bundle.putInt("currentPosition", currentPosition);

                //[5]使用msg攜帶多條資料

                msg.setData(bundle);

                //[6]發訊息  maniActivity的handlemessage方法就會執行

                MainActivity.handler.sendMessage(msg);

                //[7]給mediaplayer設定播放完成的監聽

                mediaPlayer.setOnCompletionListener(new OnCompletionListener() {

                    

                    @Override

                    public void onCompletion(MediaPlayer mp) {

                        System.out.println("歌曲播放完成了");

                        timer.cancel();

                        task.cancel();

                    }

                });

                

                

            }

        };

        //3秒後 執行task  

        timer.schedule(task, 1000,1000);

        

        

    }



    // 暫停音樂的方法

    public void pauseMusic() {

        mediaPlayer.pause();

    }

    // 繼續播放音樂的方法

    public void rePlayMusic() {

        //繼續播放也是start方法

        mediaPlayer.start();

    }

    

    //設定歌曲播放位置的方法

    public void playSeekToPosition(int position){

        mediaPlayer.seekTo(position);

    }

    

    

    //[1]定義中間人的物件 (IBinder型別)

    private class MyBinder extends Binder implements Iservice{



        @Override

        public void callplayMusic() {

            //呼叫播放音樂的方法

            playMusic();

        }



        @Override

        public void callpauseMusic() {

            //呼叫暫停音樂的方法

            pauseMusic();

        }



        @Override

        public void callrePlayMusic() {

            //呼叫繼續播放音樂的方法

            rePlayMusic();

        }



        @Override

        public void callplaySeekToPosition(int position) {

            playSeekToPosition(position);

        }

        

    }

    

    



}



【3】MainActiivty 中呼叫:     

    A,獲取控制元件,startService 開啟服務確保能夠在後臺長期執行

    B,BindService獲取返回的介面物件,呼叫其中暴露給我們的方法,播放, 暫停。

    C,seekBar.設定位置關聯進度。

public class MainActivity extends Activity {

    private Iservice iservice;//我們定義的中間人物件

    private MyConn conn;

    private static SeekBar seekBar;

    

    public static Handler handler = new Handler(){

        //這個方法處理訊息的時候執行

        public void handleMessage(android.os.Message msg) {

            //[1]獲取發訊息攜帶的資料  資料是怎麼發的 就怎麼取   資料發的是什麼型別就取什麼型別

            Bundle data = msg.getData();

            //[2]獲取歌曲的總時長和 當前進度

            int duration = data.getInt("duration");

            int currentPosition = data.getInt("currentPosition");

            //[3]更新進度條

            seekBar.setMax(duration);

            seekBar.setProgress(currentPosition);

            

            

        };

    };

    

    

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        

        //[1]呼叫startservice 保證服務在後臺長期執行

        Intent intent = new Intent(this,MusicService.class);

        startService(intent);

        //[2]想點選按鈕的時候 呼叫服務裡面的方法  獲取我們在服務內部定義的中間人物件

        conn = new MyConn();

        bindService(intent, conn, BIND_AUTO_CREATE);

        

        //[3]找到進度條

        seekBar = (SeekBar) findViewById(R.id.seekBar1);

        //[4]給seekbar設定監聽

        seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

            //當拖動進度條停止 執行

            @Override

            public void onStopTrackingTouch(SeekBar seekBar) {

                //在這個方法裡面實現拖動到哪就播放歌曲對應的位置

                iservice.callplaySeekToPosition(seekBar.getProgress());

                

            }

            //幹開始託

            @Override

            public void onStartTrackingTouch(SeekBar seekBar) {

                

            }

            

            @Override

            public void onProgressChanged(SeekBar seekBar, int progress,

                    boolean fromUser) {

                

            }

        });

        

    }

    

    //監視服務的狀態

    private class MyConn implements ServiceConnection {

    

        //當連線服務成功後呼叫

        @Override

        public void onServiceConnected(ComponentName name, IBinder service) {

            //獲取我們定義的中間人物件

            iservice = (Iservice) service;

            

            

        }

        @Override

        public void onServiceDisconnected(ComponentName name) {



        }



    }

    

    @Override

    protected void onDestroy() {

        //當Activity銷燬的時候 解綁服務

        unbindService(conn);

        super.onDestroy();

    }



    // 點選按鈕實現音樂的播放

    public void click1(View v) {



        iservice.callplayMusic();

    }



    // 點選按鈕實現音樂的暫停

    public void click2(View v) {

        iservice.callpauseMusic();



    }



    // 點選按鈕實現音樂的繼續播放

    public void click3(View v) {

        iservice.callrePlayMusic();

    }



}