Android開發實戰之簡單音樂播放器

來源:互聯網
上載者:User

標籤:

 最近開始學習音頻相關。所以,很想自己做一個音樂播放器,於是,花了一天學習,將播放器的準系統實現了出來。我覺得學習知識點還是蠻多的,所以寫篇部落格總結一下關於一個音樂播放器實現的邏輯。希望這篇博文對你的學習和生活有所協助。:

**實現邏輯**

  在市面上的音樂播放app,即時你關了。那麼一樣會在背景播放,所以播放的邏輯應該寫在Service中。並且能夠實現Service和Activity之間進行通訊。那麼Service是四大組件之一,所以在使用的時候一定不要忘了在設定檔中聲明一下。

     <service android:name="com.yakir.services.MusicService">        </service>

 

我們需要重寫Service中的三個方法,onCreate(),onStartCommand(),onDestroy()。

onCreate():Service第一次啟動的時候調用這個方法,可以做一些變數的初始化。

onStartCommand():Service每一次啟動的時候調用這個方法,可以在此方法寫一些商務邏輯。

onDestroy():Service銷毀的時候調用,用於釋放資源。

  接下來,如果需要播放一個音樂檔案,可以使用安卓內建的播放器MediaPlayer,將播放邏輯封裝起來:

    //開始    public void start(String path) {        try {            mediaPlayer.reset();            mediaPlayer.setDataSource(path);            mediaPlayer.prepare();            mediaPlayer.start();            MediaUtils.currentState= Constants.PLAY_START;        } catch (IOException e) {            e.printStackTrace();        }    }    //暫停    public void pause (){        if (mediaPlayer!=null&&mediaPlayer.isPlaying()) {            mediaPlayer.pause();            MediaUtils.currentState=Constants.PLAY_PAUSE;        }    }    //繼續播放    public void continuePlay() {        if (mediaPlayer!=null&&!mediaPlayer.isPlaying()) {            mediaPlayer.start();            MediaUtils.currentState= Constants.PLAY_START;        }    }    //停止播放    public void stop() {        if (mediaPlayer!=null) {            mediaPlayer.stop();            MediaUtils.currentState=Constants.PLAY_STOP;        }    }

我們知道,UI是寫在Activity中的,那麼就涉及到Activity與Service之間進行通訊,他們之間通訊的方式有5種,這裡我是用了Intent,調用startService()進行通訊,

同時讓Intent攜帶一組索引值對資料,與Service端進行匹配。

Activity:

   private void startMusicService(String option,String path) {        Intent intentService = new Intent(MainActivity.this, MusicService.class);        intentService.putExtra("option", option);        intentService.putExtra("messenger",new Messenger(handler));        intentService.putExtra("path", path);        startService(intentService);    }    private void startMusicService(String option) {        Intent intentService = new Intent(MainActivity.this, MusicService.class);        intentService.putExtra("option", option);        intentService.putExtra("messenger",new Messenger(handler));        startService(intentService);    }    private void startMusicService(String option,int progress) {        Intent intentService = new Intent(MainActivity.this, MusicService.class);        intentService.putExtra("option", option);        intentService.putExtra("progress",progress);        intentService.putExtra("messenger",new Messenger(handler));        startService(intentService);    }

 Service:

    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        Log.e("thread",Thread.currentThread().getName() );        String option=intent.getStringExtra("option");        if (messenger==null) {            messenger = (Messenger) intent.getExtras().get("messenger");        }        if ("開始".equals(option)) {            start(intent.getStringExtra("path"));        } else if ("暫停".equals(option)) {            pause();        } else if ("繼續".equals(option)) {            continuePlay();        } else if ("停止".equals(option)) {            stop();        } else if ("跳轉".equals(option)) {            seekPlay(intent.getIntExtra("progress",-1));        }        return super.onStartCommand(intent, flags, startId);    }

這樣,就實現了兩者之間的通訊,接下來,當我點擊下一首的時候,那麼下一個item的文字高亮,並且播放下一首歌。

先從系統中拿到所有的音頻資料:

   public static void getSongList (Context context) {        musicBeanList.clear();        Uri uri= MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;        Cursor cursor=context.getContentResolver().query(uri,                new String[]{                        MediaStore.Audio.Media.TITLE,                        MediaStore.Audio.Media.ARTIST,                        MediaStore.Audio.Media.DATA},null,null,null);        while (cursor.moveToNext()) {            musicBeanList.add(new MusicBean(                    cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE)),                    cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST)),                    cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA))));        }    }

通過內容提供者,拿到系統的所有音頻資料,以及音訊相關資訊。DATA就是音頻路徑,拿到音頻路徑後就可以根據現實位置進行播放切換了。(這裡很簡單,不細說)

處理文字高亮:

我們需要知道當前的item位置和下一個item位置,當點擊下一首歌曲,下個位置高亮,其他位置不亮。所以,需要我們定義一個常量記錄當前位置,並且,當點擊下一首,常量增加,上一首,常量減少。

   case R.id.ib_bottom_last:                  setColor(Color.BLUE);                  MediaUtils.currentPosition--;                  setColor(Color.RED);                  startMusicService("開始",MediaUtils.musicBeanList.get(MediaUtils.currentPosition).path);                  imgBottomPlay.setImageResource(R.drawable.appwidget_pause);              break;          case R.id.ib_bottom_next:                  setColor(Color.BLUE);                  MediaUtils.currentPosition++;                  setColor(Color.RED);                  startMusicService("開始",MediaUtils.musicBeanList.get(MediaUtils.currentPosition).path);                  imgBottomPlay.setImageResource(R.drawable.appwidget_pause);              break;

需要在改變顏色時做一下邏輯處理:

當到最後一個item時點擊下一個高亮變為第一個,當位於第一個時,點擊上一首,高亮位於最後一個位置。

  private void setColor(int color) {        if (MediaUtils.currentPosition==MediaUtils.musicBeanList.size()) {            MediaUtils.currentPosition=0;        }        if (MediaUtils.currentPosition==-1) {            MediaUtils.currentPosition=MediaUtils.musicBeanList.size()-1;        }        TextView textView= (TextView) songList.findViewWithTag(MediaUtils.currentPosition);        if (textView!=null) {            textView.setTextColor(color);        }    }

接下來,需要實現一個更隨音樂播放進度的進度條,這就需要實現Service向Activity的通訊,可以通過訊息機制,讓Service發送訊息給Activity,將播放資訊傳遞給Activity.

拿著這個Intent傳一個信使(Messager).

intentService.putExtra("messenger",new Messenger(handler));

從而Service:

                                Message message=Message.obtain();                                message.arg1=currentPostion;                                message.arg2=duration;                                message.what=Constants.MUSIC_PREPARE;                                messenger.send(message);

Activity再處理:

    private Handler handler=new Handler(){        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case Constants.MUSIC_PREPARE:                    int curduration=msg.arg1;                    int totalduration=msg.arg2;                    tv_curduration.setText(MediaUtils.duration2Str(curduration));                    tv_totalduration.setText(MediaUtils.duration2Str(totalduration));                    sk_duration.setMax(totalduration);                    sk_duration.setProgress(curduration);                    break;            }        }    };

在SeekBar中設定監聽,當拖動停止時把當前進度傳給Service,讓音樂就當前位置播放:

   sk_duration.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {            @Override            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {            }            @Override            public void onStartTrackingTouch(SeekBar seekBar) {            }            @Override            public void onStopTrackingTouch(SeekBar seekBar) {                 sk_duration.setProgress(seekBar.getProgress());                startMusicService("跳轉",seekBar.getProgress());            }        });

同時,我們需要注意到一個情況,當啟動電話時,音樂應該是停止狀態,可以通過AudioManager獲得音頻焦點,當焦點失去時,音樂也應該停止:

     AudioManager audioManager= (AudioManager) getSystemService(Context.AUDIO_SERVICE);        audioManager.requestAudioFocus(new AudioManager.OnAudioFocusChangeListener() {            @Override            public void onAudioFocusChange(int focusChange) {                switch (focusChange) {                    case AudioManager.AUDIOFOCUS_GAIN:                        mediaPlayer.start();                        mediaPlayer.setVolume(1.f,2.0f);                        break;                    case AudioManager.AUDIOFOCUS_LOSS:                        if (mediaPlayer.isPlaying())                            mediaPlayer.stop();                            mediaPlayer.release();                            mediaPlayer=null;                        break;                    case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT:                        if (mediaPlayer.isPlaying());                        mediaPlayer.pause();                        break;                }            }        },AudioManager.STREAM_MUSIC,AudioManager.AUDIOFOCUS_GAIN);

好了,這樣一個簡單的音樂播放器就完成了,雖然說代碼不是很困難,但是還是有很多知識點,比如Activity中Service中的通訊,以及ListView相關,還有程式的邏輯性,所以我把幾個重要的點總結了一下。希望這篇博文對你的生活和學習有所協助,如果有什麼疑問可以在下方留言,如果你想要源碼,可以私聊我~

Android開發實戰之簡單音樂播放器

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.