音樂播放器

在Android中播放音頻文件一般都是使用MediaPlayer類來實(shí)現(xiàn)的

MediaPlayer使用步驟簡介:

  • 創(chuàng)建MediaPlayer對象

    MediaPlayer mediaPlayer = new MediaPlayer();
    
  • MediaPlayer對象重置為剛剛創(chuàng)建的狀態(tài)

    mediaPlayer.reset();
    
  • 設(shè)置要播放的音頻文件的位置(可以是本地文件也可以是網(wǎng)絡(luò)文件)

    mediaPlayer.setDataSource(Environment.getExternalStorageDirectory().getAbsolutePath() + "/richu.mp3");
    
  • 在開始播放之前完成準(zhǔn)備工作

    • 若播放的是本地文件

      mediaPlayer.prepare();
      
    • 若播放的是網(wǎng)絡(luò)文件

      /*異步準(zhǔn)備弦疮,本地文件也可以使用此方法來進(jìn)行播放前的準(zhǔn)備*/
      mediaPlayer.prepareAsync();
      /*播放網(wǎng)絡(luò)音頻,不一定會(huì)調(diào)用完準(zhǔn)備方法后直接準(zhǔn)備完成蜘醋,故添加一個(gè)準(zhǔn)備監(jiān)聽*/
      mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
          /*此方法在準(zhǔn)備完成之后調(diào)用*/
          @Override
          public void onPrepared(MediaPlayer mp) {
              
          }
      });
      
  • 開始播放音頻文件

    mediaPlayer.start();
    
  • 其他API

    • 判斷當(dāng)前MediaPlayer是否正在播放音頻

      mediaPlayer.isPlaying();
      
    • 暫停播放音頻

      mediaPlayer.pause();
      
    • 停止播放音頻

      mediaPlayer.stop();
      

    調(diào)用這個(gè)方法后的MediaPlayer對象無法再播放音頻

    • 釋放掉與MediaPlayer對象相關(guān)的資源

      mediaPlayer.release();
      
    • 獲取載入的音頻文件的時(shí)長

      mediaPlayer.getDuration();
      
    • 獲取已播放的音頻時(shí)長

      mediaPlayer.getCurrentPosition();
      
    • 從指定的位置開始播放音頻文件

      mediaPlayer.seekTo();
      

制作簡易音樂播放器

播放音樂需要在服務(wù)中進(jìn)行胁塞,當(dāng)音樂播放器界面不顯示的時(shí)候,音樂依舊可以播放

1压语、在服務(wù)中闲先,有開始播放、暫停播放无蜂、滑動(dòng)進(jìn)度條在指定位置播放音樂等方法的定義
2吓著、在服務(wù)中,定義一個(gè)計(jì)時(shí)器芝雪,根據(jù)音樂播放的進(jìn)度参萄,在進(jìn)度條SeekBar中顯示出來
3、在活動(dòng)中酣倾,添加進(jìn)度條SeekBar監(jiān)聽器

  • MusicService

    public class MusicService extends Service {
    //操作音頻文件的API
    private static MediaPlayer mediaPlayer;
    //計(jì)時(shí)器API
    private Timer timer;
    
    @Override
    public IBinder onBind(Intent intent) {
        //活動(dòng)和服務(wù)綁定時(shí)舵揭,返回MusicControl對象(繼承自IBinder對象)
        return new MusicControl();
    }
    
    @Override
    public void onCreate() {
        super.onCreate();
        //創(chuàng)建MediaPlayer對象
        mediaPlayer = new MediaPlayer();
    }
    
    @Override
    public void onDestroy() {
        super.onDestroy();
        //暫停播放
        mediaPlayer.stop();
        //釋放資源
        mediaPlayer.release();
        if (timer != null) {
            //將計(jì)時(shí)器取消
            timer.cancel();
            timer = null;
        }
    }
    
    /*開始播放音樂的方法*/
    public void play(){
        //重置MediaPlayer對象
        mediaPlayer.reset();
            try {
                /*加載多媒體文件*/
                //本地加載
                mediaPlayer.setDataSource(Environment.getExternalStorageDirectory().getAbsolutePath() + "/richu.mp3");
                //網(wǎng)絡(luò)視頻加載
    

// mediaPlayer.setDataSource("http://192.168.1.101:8080/richu.mp3");
//異步準(zhǔn)備
mediaPlayer.prepareAsync();

            mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
                //準(zhǔn)備完畢時(shí),此方法調(diào)用
                @Override
                public void onPrepared(MediaPlayer mp) {
                    //開始播放
                    mediaPlayer.start();
                    //計(jì)時(shí)器開始計(jì)時(shí)
                    addTimer();
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
}

/*繼續(xù)播放音樂的方法*/
public void continuePlay(){
    mediaPlayer.start();
}

/*暫停播放音樂*/
public void pause(){
    mediaPlayer.pause();
}

/*添加一個(gè)計(jì)時(shí)器對象*/
public void addTimer(){
    if (timer == null) {
        timer = new Timer();
        //計(jì)時(shí)器設(shè)置躁锡,相當(dāng)于開啟了一個(gè)子線程
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                //獲取歌曲總時(shí)長
                int duration = mediaPlayer.getDuration();
                //獲取歌曲當(dāng)前播放進(jìn)度
                int currentPosition = mediaPlayer.getCurrentPosition();
                /*發(fā)送消息對象午绳,在主線程中更新UI*/
                Message message = MainActivity.handler.obtainMessage();
                Bundle bundle = new Bundle();
                bundle.putInt("duration", duration);
                bundle.putInt("currentPosition", currentPosition);
                message.setData(bundle);
                MainActivity.handler.sendMessage(message);
            }
        }, 5, 500);//開始計(jì)時(shí)任務(wù)后的5毫秒,第一次執(zhí)行run方法映之;以后每500毫秒執(zhí)行一次
    }
}

/*指定位置播放音樂*/
public void seekTo(int progress){
    mediaPlayer.seekTo(progress);
}

/*服務(wù)和綁定此服務(wù)的活動(dòng)通信的中間對象*/
class MusicControl extends Binder implements MusicInterface{

    @Override
    public void play() {
        MusicService.this.play();
    }

    @Override
    public void continuePlay() {
        MusicService.this.continuePlay();
    }

    @Override
    public void pause() {
        MusicService.this.pause();
    }

    @Override
    public void seekTo(int progress) {
        MusicService.this.seekTo(progress);
    }
    
}

}
```

  • MusicInterface服務(wù)和綁定此服務(wù)的活動(dòng)通信的中間對象抽象出來的接口:

    public interface MusicInterface {
    
        void play();
        
        void continuePlay();
        
        void pause();
        
        void seekTo(int progress);
    
    }
    
  • MainActivity活動(dòng)界面:

    public class MainActivity extends Activity {
    
        private MyConnection connection;
        private MusicInterface control;
        private Intent intent;
        //進(jìn)度條對象
        private static SeekBar bar;
        
        static final int TIME = 0;
    
        static Handler handler = new Handler(){
            public void handleMessage(android.os.Message msg) {
                Bundle bundle = msg.getData();
                int duration = (Integer) bundle.get("duration");
                int currentPosition  = (Integer) bundle.get("currentPosition");
                bar.setMax(duration);
                //主線程中更新UI拦焚,更新進(jìn)度條進(jìn)度
                bar.setProgress(currentPosition);
            }
        };
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            
            bar = (SeekBar) findViewById(R.id.sb);
            
            bar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
                
                @Override
                public void onStopTrackingTouch(SeekBar seekBar) {
                    //根據(jù)拖動(dòng)的進(jìn)度改變音樂的播放進(jìn)度
                    int currentPosition = seekBar.getProgress();
                    control.seekTo(currentPosition);
                    Log.d("MainActivity", "手指抬起");
                }
                
                @Override
                public void onStartTrackingTouch(SeekBar seekBar) {
                    Log.d("MainActivity", "手指按下");
                    
                }
                
                @Override
                public void onProgressChanged(SeekBar seekBar, int progress,
                        boolean fromUser) {
                    Log.d("MainActivity", "手指滑動(dòng)");
                    
                }
            });
            
            connection = new MyConnection();
            
            intent = new Intent(this, MusicService.class);
            //開啟服務(wù)以及綁定服務(wù)
            startService(intent);
            bindService(intent, connection, BIND_AUTO_CREATE);
            
        }
    
    class MyConnection implements ServiceConnection{
    
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //拿到服務(wù)和活動(dòng)通信的中間對象
            control = (MusicControl) service;
        }
    
        @Override
        public void onServiceDisconnected(ComponentName name) {
            
        }
        
    }
    
        /*
         *通過中間人對象調(diào)用服務(wù)中的方法來操作音樂的狀態(tài)
         */
        public void play(View v){
            control.play();
        }
        
        public void continuePlay(View v){
            control.continuePlay();
        }
        
        public void pause(View v){
            control.pause();
        }
        
        public void exit(View v){
            unbindService(connection);
            stopService(intent);
        }
        
    }
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蜡坊,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子赎败,更是在濱河造成了極大的恐慌秕衙,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件僵刮,死亡現(xiàn)場離奇詭異据忘,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)搞糕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門勇吊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人窍仰,你說我怎么就攤上這事萧福。” “怎么了辈赋?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵鲫忍,是天一觀的道長。 經(jīng)常有香客問我钥屈,道長悟民,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任篷就,我火速辦了婚禮射亏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘竭业。我一直安慰自己智润,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布未辆。 她就那樣靜靜地躺著窟绷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪咐柜。 梳的紋絲不亂的頭發(fā)上兼蜈,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天,我揣著相機(jī)與錄音拙友,去河邊找鬼为狸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛遗契,可吹牛的內(nèi)容都是我干的辐棒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼漾根!你這毒婦竟也來了泰涂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤立叛,失蹤者是張志新(化名)和其女友劉穎负敏,沒想到半個(gè)月后贡茅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體秘蛇,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年顶考,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赁还。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,688評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡驹沿,死狀恐怖艘策,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情渊季,我是刑警寧澤朋蔫,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站却汉,受9級特大地震影響驯妄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜合砂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一青扔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧翩伪,春花似錦微猖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至轻姿,卻和暖如春当悔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背踢代。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工盲憎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人胳挎。 一個(gè)月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓饼疙,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子窑眯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內(nèi)容