Back to project page akuplayer.
The source code is released under:
Copyright (c) 2014, Dmitry Kuznetsov aka kudzmi All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditi...
If you think the Android project akuplayer listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
/* Copyright (c) 2014, Dmitry Kuznetsov aka kudzmi All rights reserved.//from w w w. j av a 2 s. co m Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.kudzmi.akuplayer.player; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.media.MediaPlayer; import android.net.wifi.WifiManager; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.PowerManager; import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import android.widget.Toast; import com.kudzmi.akuplayer.Audio; import com.kudzmi.akuplayer.PrefStorage; import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.Set; /** * MediaPlayer * @author Dmitry Kuznetsov aka kudzmi * @version 1.0 */ public class AKuPlayerService extends Service implements MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener, MediaPlayer.OnBufferingUpdateListener, MediaPlayer.OnSeekCompleteListener { private final String DBG_LABLE = " = AKuPlayer ="; private MediaPlayer mPlayer; private AudioManager am; private WifiManager.WifiLock wifiLock; private Long currentTrackId = -1L; private int currentTrackPos = 0, mBufferPos = 0; private List<Audio> mTrackList; private List<Audio> mTrackListShuffled; private boolean isPaused = false; private boolean mIsRepeat = false, mIsShuffle = false; private PrefStorage prefs; private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); switch(action){ case BroadcastCommander.UI2SRV_EVENT_PL: TrackList tl = (TrackList) intent.getSerializableExtra(BroadcastCommander.MESSAGE_EXTRA); processPlayList(tl); break; case BroadcastCommander.UI2SRV_EVENT_CMD: PlayerCommand pcmd = (PlayerCommand) intent.getSerializableExtra(BroadcastCommander.MESSAGE_EXTRA); processCommand(pcmd); break; case BroadcastCommander.UI2SRV_EVENT_CMD_SEEK: PlayerSeekCommand pscmd = (PlayerSeekCommand) intent.getSerializableExtra(BroadcastCommander.MESSAGE_EXTRA); processSeekCommand(pscmd); break; } } }; public AKuPlayerService() { } @Override public IBinder onBind(Intent intent) { throw new UnsupportedOperationException("Not yet implemented"); } private Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { sendCurrentPlayerStatus(); } }; @Override public void onCreate() { super.onCreate(); mTrackList = new ArrayList<>(); prefs = PrefStorage.getInstance(this); am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); Log.d(DBG_LABLE, "CREATED!"); initMediaPlayer(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BroadcastCommander.UI2SRV_EVENT_CMD); intentFilter.addAction(BroadcastCommander.UI2SRV_EVENT_CMD_SEEK); intentFilter.addAction(BroadcastCommander.UI2SRV_EVENT_PL); LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, intentFilter); } @Override public void onDestroy() { super.onDestroy(); if(mReceiver != null) LocalBroadcastManager.getInstance(this).unregisterReceiver(mReceiver); if(mPlayer != null) { mPlayer.release(); mPlayer = null; } releaseAudioFocus(); releaseWiFiLock(); Log.d(DBG_LABLE, "DESTROYED!"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } private void startUpdateThread(){ Thread thread = new Thread() { @Override public void run() { Log.d(DBG_LABLE, "update thread STARTED"); while(mPlayer != null && mPlayer.isPlaying()){ mHandler.sendMessage(Message.obtain()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } Log.d(DBG_LABLE, "update thread STOPED"); } }; thread.start(); } private boolean requestAudioFocus(){ // Request audio focus for playback int result = am.requestAudioFocus(afChangeListener, // Use the music stream. AudioManager.STREAM_MUSIC, // Request permanent focus. AudioManager.AUDIOFOCUS_GAIN); if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { //am.registerMediaButtonEventReceiver(RemoteControlReceiver); // Start playback. return true; } return false; } private void releaseAudioFocus(){ am.abandonAudioFocus(afChangeListener); } private void initMediaPlayer(){ mPlayer = new MediaPlayer(); mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mPlayer.setOnPreparedListener(this); mPlayer.setOnCompletionListener(this); mPlayer.setOnBufferingUpdateListener(this); mPlayer.setOnSeekCompleteListener(this); mPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK); } private void acquireWiFiLock(){ if(wifiLock == null) wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE)) .createWifiLock(WifiManager.WIFI_MODE_FULL, "AKuPlayerWiFiLock"); wifiLock.acquire(); } private void releaseWiFiLock(){ if(wifiLock != null && wifiLock.isHeld()) wifiLock.release(); } private void sendCurrentPlayerStatus(){ String trackTitle = ""; if(mIsShuffle){ trackTitle = mTrackListShuffled.get(currentTrackPos).name; }else{ trackTitle = mTrackList.get(currentTrackPos).name; } int duration = 0; int currentPos = 0; if(mPlayer != null && mPlayer.isPlaying()){ duration = mPlayer.getDuration()/1000; currentPos = mPlayer.getCurrentPosition()/1000; } PlayerStatus ps = new PlayerStatus( duration, currentPos, mBufferPos, trackTitle); ps.setCurrentTrackId(currentTrackId); if(mPlayer != null & mPlayer.isPlaying()) ps.setPlaying(true); else ps.setPlaying(false); BroadcastCommander.sendStatus(this, ps); } private void processPlayList(TrackList tl){ mTrackList = tl.getTracks(); //currentTrackId = tl.getStartTrackId(); isPaused = false; mPlayer.reset(); } private void processSeekCommand(PlayerSeekCommand cmd){ if(cmd.isSeeking()){ int pos = (int) (((float)cmd.getSeekpos() / 100)*mPlayer.getDuration()); mPlayer.seekTo(pos); } } private void processCommand(PlayerCommand cmd){ mIsRepeat = cmd.isRepeat(); mIsShuffle = cmd.isShuffle(); if(mIsShuffle) makeRandomList(); if(cmd.isToPause()){ doPause(); } if(cmd.isToPlay()){ if(isPaused){ doPlay(null); }else{ currentTrackId = cmd.getStartTrackId(); doPlay(getTrack(currentTrackId)); } } if(cmd.isToPrev()){ doPrev(); } if(cmd.isToNext()){ doNext(); } } /** * Get track URI by ID * @param id track's ID * @return track URL or file path */ private String getTrack(long id){ Iterator<Audio> it; if(!mIsShuffle)it = mTrackList.iterator(); else it = mTrackListShuffled.iterator(); int i = 0; while (it.hasNext()){ Audio a = it.next(); if(a.audio_id == id){ currentTrackPos = i; return a.file; } i++; } return null; } /** * Get track URI by it's position * @param pos track's position in the track list * @return track URL or file path */ private String getTrack(int pos){ if(mIsShuffle){ currentTrackId = mTrackListShuffled.get(pos).audio_id; return mTrackListShuffled.get(pos).file; }else{ currentTrackId = mTrackList.get(pos).audio_id; return mTrackList.get(pos).file; } } private void doPlay(String url){ Log.d(DBG_LABLE, "doPlay: "+url); Log.d(DBG_LABLE, "doPlay ID: "+currentTrackId); acquireWiFiLock(); if(isPaused){ mPlayer.start(); startUpdateThread(); }else try { mPlayer.setDataSource(url); mPlayer.prepareAsync(); } catch (IOException e) { e.printStackTrace(); Toast.makeText(this, "Problems with track: "+url, Toast.LENGTH_SHORT).show(); } isPaused = false; } private void doPause(){ isPaused = true; mPlayer.pause(); releaseWiFiLock(); } /** * Completelu stop the player * If track list ends, or the app lost audio focus */ private void doStop(){ isPaused = false; mPlayer.stop(); mPlayer.reset(); releaseAudioFocus(); sendCurrentPlayerStatus(); releaseWiFiLock(); } private void doPrev(){ if(mIsRepeat){ if(currentTrackPos == 0) currentTrackPos = mTrackList.size(); } if(currentTrackPos > 0){ isPaused = false; mPlayer.stop(); mPlayer.reset(); doPlay(getTrack(--currentTrackPos)); } } private void doNext(){ if(mIsRepeat){ if(currentTrackPos == mTrackList.size()-1) currentTrackPos = -1; } if(currentTrackPos < mTrackList.size()-1){ isPaused = false; mPlayer.stop(); mPlayer.reset(); doPlay(getTrack(++currentTrackPos)); }else{ // if there is nothing to play doStop(); } } /* Listeners */ @Override public void onCompletion(MediaPlayer mediaPlayer) { doNext(); } @Override public void onPrepared(MediaPlayer mediaPlayer) { requestAudioFocus(); mediaPlayer.start(); startUpdateThread(); } @Override public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) { mBufferPos = i; } /* tools */ AudioManager.OnAudioFocusChangeListener afChangeListener = new AudioManager.OnAudioFocusChangeListener() { public void onAudioFocusChange(int focusChange) { switch (focusChange) { case AudioManager.AUDIOFOCUS_GAIN: // resume playback if (mPlayer == null) initMediaPlayer(); if(isPaused){ mPlayer.start(); startUpdateThread(); isPaused = false; } mPlayer.setVolume(1.0f, 1.0f); break; case AudioManager.AUDIOFOCUS_LOSS: // Lost focus for an unbounded amount of time: stop playback and release media player doStop(); break; case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT: // Lost focus for a short time, but we have to stop // playback. We don't release the media player because playback // is likely to resume doPause(); break; case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: // Lost focus for a short time, but it's ok to keep playing // at an attenuated level if (mPlayer.isPlaying()) mPlayer.setVolume(0.1f, 0.1f); break; } if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT){ doPause(); } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { if(isPaused) { mPlayer.start(); startUpdateThread(); } } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { //am.unregisterMediaButtonEventReceiver(RemoteControlReceiver); doStop(); } } }; private void makeRandomList(){ Set<Integer> tmp = new HashSet<>(); Random rnd = new Random(System.currentTimeMillis()); mTrackListShuffled = new ArrayList<>(); while(mTrackListShuffled.size() < mTrackList.size()){ int pos = rnd.nextInt(mTrackList.size()); if(tmp.add(pos)){ mTrackListShuffled.add(mTrackList.get(pos)); } } } @Override public void onSeekComplete(MediaPlayer mediaPlayer) { if(mPlayer != null && mPlayer.isPlaying()) sendCurrentPlayerStatus(); } }