Android最簡單音樂播放器的小例子總結


這只是一個小例子,實現三首mp3格式音樂的循環播放,並且有播放、暫停、停止的功能。

大體思想:

  1. 需要一個Activity用來與用戶交互當前播放情況,用戶通過點擊按鈕操作播放、暫停和停止。

  2. 還需要有一個后台Service處理音樂的播放(還好Android有MediaPlayer對象可以對音樂進行播放、暫停等操作)。

  3. Activity和Service之間需要進行交互,

    (1)用戶點擊按鈕執行音樂的播放、暫停或者停止,每一個按鈕對應一種狀態,通過Broadcast廣播傳給Service。

    (2)Service接收Activity發來的廣播,對操作進行判斷從而執行MediaPlayer的音樂操作。之后將音樂的信息同樣以廣播的形式發送回Activity。

    (3)Activity接收Service的廣播在頁面上更新歌曲的信息。

下面是細節的問題:

1.首先Activity布局非常簡單,一個文本框用來顯示歌曲名,兩個按鈕,“播放”和“停止”。

2.然后是Activity:

(1)onCreate()方法:

    這是Activity第一次創建的時候調用的,因此默認代碼就是將布局文件進行加載。除了這些內容,我們要獲取獲取布局文件上的組件,尤其是Button,我們需要定義監聽器處理用戶點擊的事件(一會就會說到)。其實最主要的兩件事是創建BroadcastReceiver對象、Intent過濾器和Receiver的注冊(Broadcast不同於監聽器,Broadcast是一個系統級的監聽器,擁有自己的進程,因此只要存在與之匹配的Intent被廣播出來,BroadcastReceiver總會被觸發),然后開啟后台的Service。

ar = new ActivityReceiver();

IntentFilter filter = new IntentFilter();

filter.addAction(UPDATE_ACTION); //update更改界面播放信息

getApplicationContext().registerReceiver(ar,filter);

Intent in = new Intent(MainActivity.this,MP3Service.class);

startService(in); //開啟Service

 

(2)定義BroadcastReceiver的子類並重寫onReceive方法,這是Service發送歌曲信息的廣播,然后Activity獲取並更新頁面的Receiver:onReceive方法在應用發送相應廣播后自動執行,執行之后BroadcastReceiver實例就會被銷毀。

public class ActivityReceiver extends BroadcastReceiver{

  

        @Override

        public void onReceive(Context context, Intent intent) {

            System.out.println("activity receive");

            int update = intent.getIntExtra("update", -1);

            int current = intent.getIntExtra("current", -1);

            if(current>=0){

                title.setText(titleStrs[current]);

            }

            switch(update){

            case 0x11:

                play.setText(R.string.play);

                break;

            case 0x12:

                play.setText(R.string.pause);

                break;

            case 0x13:

                play.setText(R.string.play);

                break;

            }

        }

          

    }

 

(3)onClick:首先Activity有兩個按鈕,定義一個control狀態代表哪個按鈕被執行,播放和暫停是一類的,停止是第二類的,將哪個按鈕被執行的control狀態封裝到Intent中,然后發送廣播給Service。

public void onClick(View source) {

    Intent in = new Intent(CTL_ACTION); //Service中廣播處理的是CTL_ACTION的Intent

    switch(source.getId()){

    case R.id.play:

        in.putExtra("control", 1);

        break;

    case R.id.stop:

        in.putExtra("control", 2);

        break;

    }

    sendBroadcast(in);//發送廣播到service

    System.out.println("activity send");

}

 

(4)onDestroy:最后,因為Service是Activity開啟的,而且同樣在onCreate中注冊了BroadcastReceiver,因此當Activity被銷毀時,也需要將Service和BroadcastReceiver釋放:

protected void onDestroy() {

    stopService(in);

    getApplicationContext().unregisterReceiver(ar);

    super.onDestroy();

}

3.接着是Service:

(1)onCreate:創建MediaPlayer對象,為MediaPlayer設置CompletingListener監聽器(當前數據被播放完之后執行,用來播放下一首),創建AssetManager對象用於讀取sdcard的音樂文件,並創建接收Activity廣播的BroadcastReceiver:

asset = getAssets();

mr = new MyReceiver();

IntentFilter filter = new IntentFilter(MainActivity.CTL_ACTION); //控制播放

getApplicationContext().registerReceiver(mr,filter);

mp = new MediaPlayer();

 

(2)MediaPlayer的監聽器:根據current當前歌曲的標號進行歌曲的切換,並發送下一首歌曲的信息通過廣播發送給Activity:

mp.setOnCompletionListener(new OnCompletionListener(){

  

            @Override

            public void onCompletion(MediaPlayer mp) {

                current = current+1; //從0開始的,0,1,2三首

                if(current>=3){

                    current = 0;

                }

                //通知界面更新歌曲信息

                Intent sendIntent = new Intent(MainActivity.UPDATE_ACTION);

                sendIntent.putExtra("current", current);

                sendBroadcast(sendIntent);

                prepareAndPlay(songs[current]);

            }

              

        });

 

(3)最重要的接收Activity中用戶點擊按鈕的狀態發來的廣播進行音樂播放處理的Receiver:

public class MyReceiver extends BroadcastReceiver{

  

        @Override

        public void onReceive(Context context, Intent intent) {

            System.out.println("serivce receive");

            int control = intent.getIntExtra("control",-1);

            switch(control){

            case 1: //播放或暫停

                if(status==0x11){

                    prepareAndPlay(songs[current]);

                    status = 0x12;

                }

                else if(status==0x12){

                    mp.pause();

                    status = 0x13;

                }

                else if(status==0x13){

                    mp.start();

                    status = 0x12;

                }

                break;

            case 2: //停止音樂

                if(status==0x12||status==0x13){

                    mp.stop();

                    status = 0x11;

                }

            }

            Intent sendIntent = new Intent(MainActivity.UPDATE_ACTION);

            sendIntent.putExtra("current",current);

            sendIntent.putExtra("update", status);

            sendBroadcast(sendIntent);

            System.out.println("service send");

        }

          

    }

 

(4)最后在onDestroy中釋放Receiver:

public void onDestroy() {

        System.out.println("ondestroy");

        getApplicationContext().unregisterReceiver(mr);

        super.onDestroy();

    }

(5)有一個細節,就是在播放完一個歌曲之后,再播放下一個的時候,MediaPlayer對象一定要執行reset方法,不然會發生MediaPlayer狀態的異常。以下是prepareAndPlay方法:

 

public void prepareAndPlay(String music){

        try{

            File f = new File(Environment.getExternalStorageDirectory()+"/"+music);

            if(f.exists()){

                System.out.println("--cunzai--");

            }

            //AssetFileDescriptor afd = asset.openFd(Environment.getExternalStorageDirectory()+"/"+music);

            try {

                mp.reset(); //在執行新的一次play的時候需要reset

                mp.setDataSource(Environment.getExternalStorageDirectory()+"/"+music);

                mp.prepare();

                mp.start();

            } catch (IllegalArgumentException e) {

                e.printStackTrace();

            } catch (SecurityException e) {

                e.printStackTrace();

            } catch (IllegalStateException e) {

                e.printStackTrace();

            } catch (IOException e) {

                // TODO Auto-generated catch block

                e.printStackTrace();

            }

        }catch(Exception e){

              

        }

    }

4.最后別忘記在Manifest文件中配置Service,由於Receiver是在代碼中生成的,因此無需進行配置。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM