日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

用MediaPlayer做个带进度条可后台的音乐播放器

發(fā)布時(shí)間:2025/7/14 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用MediaPlayer做个带进度条可后台的音乐播放器 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

傳送到github看源碼
下載apk試用 密碼:rukn


前言

  • 想在天朝聽(tīng)音樂(lè)還是有些難度的, 一般來(lái)說(shuō), 兩三個(gè)app還是要的. 那何不嘗試自己做個(gè)手機(jī)播放器, 聽(tīng)個(gè)爽呢?!今天就帶大家先做個(gè)簡(jiǎn)單的帶進(jìn)度條可拖動(dòng)的音樂(lè)播放器.
  • 添加了后臺(tái)播放的功能, 很實(shí)用哦~

先看效果圖

很尷尬的一點(diǎn)就是大家沒(méi)法聽(tīng)到音樂(lè), 就只能看看圖片.

效果圖

布局文件

布局文件

添加Service

我們需要先把Service添加進(jìn)來(lái), 再考慮使用MediaPlayer播放, 我們分步來(lái)說(shuō).

  • 首先要有一個(gè)自定義接口, 這個(gè)接口中的方法都是要在服務(wù)中實(shí)現(xiàn)的, 然后要到Activity中使用的.
public interface IService {//1. 定義接口IService, 添加調(diào)用函數(shù), 調(diào)用MusicService中對(duì)應(yīng)的函數(shù)public void callPlayMusic(String path);public void callPauseMusic();public void callConMusic();public void callSeekToPos(int pos); }
  • 然后來(lái)看Service中的實(shí)現(xiàn), 自定義一個(gè)類, 繼承Binder, 然后實(shí)現(xiàn)我們?cè)俳涌谥卸x的方法.
/*** 類MyBinder繼承Binder實(shí)現(xiàn)接口IService*/private class MyBinder extends Binder implements IService {//2. 定義類MyBinder繼承Binder實(shí)現(xiàn)接口IService中的函數(shù)@Overridepublic void callPlayMusic(String path) {playMusic(path);}@Overridepublic void callPauseMusic() {pauseMusic();}@Overridepublic void callConMusic() {conMusic();}@Overridepublic void callSeekToPos(int pos) {seekToPos(pos);}}
  • 具體的實(shí)現(xiàn)就要涉及到MediaPlayer的使用了, 我們等下說(shuō), 先把Service綁定到Activity. 首先要返回一個(gè)自定義類的實(shí)例.
@Nullable@Overridepublic IBinder onBind(Intent intent) {//3. 返回自定義類MyBinder對(duì)象return new MyBinder();}
  • 然后我們轉(zhuǎn)到Activity來(lái)綁定服務(wù)
//4. 開(kāi)啟服務(wù)Intent intent = new Intent(this, MusicService.class);startService(intent);//7. 綁定服務(wù)MyConn myConn = new MyConn();bindService(intent, myConn, BIND_AUTO_CREATE);
  • 中間的MyConn又是一個(gè)自定義的類, 我們來(lái)看下實(shí)現(xiàn). 之中要獲取下IService對(duì)象, 以此調(diào)用定義的函數(shù).
private class MyConn implements ServiceConnection {//5. 定義類MyConn實(shí)現(xiàn)接口ServiceConnection@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {//6. 獲取IBinder對(duì)象, 以此調(diào)用暴露的函數(shù)iService = (IService) service;}@Overridepublic void onServiceDisconnected(ComponentName name) {}}

MediaPlayer的使用

然后服務(wù)就完成一個(gè)綁定了, 之后我們來(lái)說(shuō)下MediaPlayer和SeekBar的使用. 無(wú)非就是播放, 暫停, 繼續(xù)這些的實(shí)現(xiàn). 具體的說(shuō)明請(qǐng)移步官方文檔

/*** 播放音樂(lè)** @param path 播放文件的路徑*/public void playMusic(String path) {Log.i(TAG, "playMusic");try {mediaPlayer.reset();mediaPlayer.setDataSource(path);mediaPlayer.setLooping(true);mediaPlayer.prepare();mediaPlayer.start();updateSeekBar();} catch (Exception e) {e.printStackTrace();}}/*** 暫停播放音樂(lè)*/public void pauseMusic() {Log.i(TAG, "pauseMusic");if (mediaPlayer.isPlaying()) {mediaPlayer.pause();}}/*** 繼續(xù)播放音樂(lè)*/public void conMusic() {Log.i(TAG, "conMusic");mediaPlayer.start();}

讀取文件系統(tǒng)肯定是要權(quán)限的, 可以查看我之前的文章一個(gè)Util帶你獲取Android6.0以上的讀寫sdcard權(quán)限


進(jìn)度條的設(shè)置

SeekBar這里用起來(lái)其實(shí)不難, 難就難在要從Service傳數(shù)據(jù)到Activity. 這里我選用Handler, 當(dāng)然你也可以用其它辦法. 同樣我們分步來(lái)說(shuō).

  • 之前調(diào)用mediaPlayer.start();之后我調(diào)用了一個(gè)updateSeekBar();, 現(xiàn)在來(lái)看看實(shí)現(xiàn). 關(guān)鍵是要獲取到音樂(lè)的總長(zhǎng)度, 并且實(shí)時(shí)更新, 要實(shí)時(shí)更新的話, 我這里開(kāi)了一個(gè)線程, 1s刷一次, 就不多說(shuō)了.
/*** 更新SeekBar*/private void updateSeekBar() {//獲取總時(shí)長(zhǎng)final int duration = mediaPlayer.getDuration();//開(kāi)啟線程發(fā)送數(shù)據(jù)new Thread() {@Overridepublic void run() {while (keepTrue) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}int currentPosition = mediaPlayer.getCurrentPosition();//發(fā)送數(shù)據(jù)給activityMessage message = Message.obtain();Bundle bundle = new Bundle();bundle.putInt("duration", duration);bundle.putInt("currentPosition", currentPosition);message.setData(bundle);MainActivity.handler.sendMessage(message);}}}.start();}
  • 然后回到Activity要接收發(fā)送的message. 接收到之后也完成的差不多了. 然后就是一個(gè)SeekBar的監(jiān)聽(tīng)設(shè)置.
public static Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {Bundle data = msg.getData();int duration = data.getInt("duration");int currentPosition = data.getInt("currentPosition");sb_progress.setMax(duration);sb_progress.setProgress(currentPosition);}};
  • 就是在放開(kāi)拖動(dòng)SeekBar的時(shí)候重新設(shè)置位置, 要注意的是, 函數(shù)seekToPos也是在Service中實(shí)現(xiàn)的.
//8. 設(shè)置進(jìn)度條拖動(dòng)事件sb_progress.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {iService.callSeekToPos(seekBar.getProgress());}}); /*** 設(shè)置SeekBar位置** @param pos 當(dāng)前位置*/public void seekToPos(int pos) {mediaPlayer.seekTo(pos);}

這樣就完成啦! 喜歡就趕緊下載試試吧! 有意見(jiàn)或者建議也可以評(píng)論區(qū)哦.


傳送到github看源碼
下載apk試用 密碼:rukn


《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的用MediaPlayer做个带进度条可后台的音乐播放器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。