com.scooter1556.sms.lib.android.service.AudioPlayerService.java Source code

Java tutorial

Introduction

Here is the source code for com.scooter1556.sms.lib.android.service.AudioPlayerService.java

Source

/*
 * Author: Scott Ware <scoot.software@gmail.com>
 * Copyright (c) 2015 Scott Ware
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package com.scooter1556.sms.lib.android.service;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.AudioManager.OnAudioFocusChangeListener;
import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SimpleTarget;
import com.google.android.exoplayer.ExoPlayer;
import com.google.gson.Gson;
import com.loopj.android.http.JsonHttpResponseHandler;
import com.scooter1556.sms.lib.android.R;
import com.scooter1556.sms.lib.android.domain.MediaElement;
import com.scooter1556.sms.lib.android.domain.TranscodeProfile;
import com.scooter1556.sms.lib.android.player.SMSAudioPlayer;
import com.scooter1556.sms.lib.android.utils.MediaUtils;

import org.json.JSONObject;

import java.util.ArrayList;

public class AudioPlayerService extends Service implements SMSAudioPlayer.Listener {

    private static final String TAG = "AudioPlayerService";

    static final String SUPPORTED_FILES = "aac,m4a,mp3,oga,ogg";
    static final String SUPPORTED_CODECS = "aac,mp3,vorbis";
    static final String MCH_CODECS = "ac3";

    static final int MAX_SAMPLE_RATE = 48000;

    public static final float VOLUME_DUCK = 0.2f;
    public static final float VOLUME_NORMAL = 1.0f;
    public static final float VOLUME_OFF = 0.0f;

    // REST Client
    private RESTService restService = null;

    // Media Player
    private SMSAudioPlayer player;

    // Media Session
    private MediaSessionCompat mediaSession;
    private MediaSessionCallback mediaSessionCallback;
    private int mediaState;

    // Audio Manager
    private AudioManager audioManager;

    // Receivers
    BroadcastReceiver audioManagerReceiver;

    // Device Locks
    private PowerManager.WakeLock wakeLock;
    private WifiManager.WifiLock wifiLock;

    // Listeners
    private final ArrayList<AudioPlayerListener> listeners = new ArrayList<>();

    // Binder
    private final IBinder audioPlayerBind = new AudioPlayerBinder();

    // Audio List
    private ArrayList<MediaElement> mediaElementList;

    // Current Position
    private int currentListPosition;

    // Flags
    private boolean isPaused = false;

    public AudioPlayerService() {
    }

    @Override
    public void onCreate() {
        // Create the service
        super.onCreate();

        restService = RESTService.getInstance();

        currentListPosition = 0;

        mediaElementList = new ArrayList<>();

        // Setup media session
        mediaSessionCallback = new MediaSessionCallback();
        mediaSession = new MediaSessionCompat(this, "SMSPlayer");
        mediaSession.setFlags(
                MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
        mediaSession.setCallback(mediaSessionCallback);
        mediaState = PlaybackStateCompat.STATE_NONE;
        updatePlaybackState();

        audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

        PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
        wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "sms");
        wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE)).createWifiLock(WifiManager.WIFI_MODE_FULL,
                "sms");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        cleanupPlayer();
        mediaSession.release();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return audioPlayerBind;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return true;
    }

    public class AudioPlayerBinder extends Binder {
        public AudioPlayerService getService() {
            return AudioPlayerService.this;
        }
    }

    // Listener Management
    public void registerListener(AudioPlayerListener listener) {
        listeners.add(listener);
    }

    public void unregisterListener(AudioPlayerListener listener) {
        listeners.remove(listener);
    }

    private OnAudioFocusChangeListener audioFocusListener = new OnAudioFocusChangeListener() {
        public void onAudioFocusChange(int focusChange) {
            if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
                // Pause playback
                pause();
            } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
                // Lower the volume
                if (player != null) {
                    player.setVolume(VOLUME_DUCK);
                }
            } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
                // Resume playback
                if (player != null) {
                    player.setVolume(VOLUME_NORMAL);

                    if (isPaused()) {
                        start();
                    }
                }
            } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
                audioManager.abandonAudioFocus(audioFocusListener);

                // Stop playback
                stop();
            }
        }
    };

    public void play() {
        if (mediaElementList.size() <= currentListPosition) {
            return;
        }
        cleanupPlayer();
        initialiseTrack(currentListPosition);

        // Update listeners
        for (AudioPlayerListener listener : listeners) {
            listener.PlaylistPositionChanged();
        }
    }

    public void playAll(ArrayList<MediaElement> mediaElements) {
        if (mediaElements == null) {
            return;
        }
        if (mediaElements.size() == 0) {
            return;
        }

        // Set playlist and start playing first track
        mediaElementList.clear();
        mediaElementList.addAll(mediaElements);
        currentListPosition = 0;
        cleanupPlayer();
        initialiseTrack(currentListPosition);

        // Update listeners
        for (AudioPlayerListener listener : listeners) {
            listener.PlaylistChanged();
            listener.PlaylistPositionChanged();
        }
    }

    public void addAndPlay(MediaElement mediaElement) {
        mediaElementList.clear();
        mediaElementList.add(mediaElement);
        currentListPosition = 0;
        cleanupPlayer();
        initialiseTrack(currentListPosition);

        // Update listeners
        for (AudioPlayerListener listener : listeners) {
            listener.PlaylistChanged();
            listener.PlaylistPositionChanged();
        }
    }

    public void addAndPlayNext(MediaElement mediaElement) {
        if (mediaElementList.isEmpty()) {
            mediaElementList.add(mediaElement);
            currentListPosition = 0;
            cleanupPlayer();
            initialiseTrack(currentListPosition);

            // Update listeners
            for (AudioPlayerListener listener : listeners) {
                listener.PlaylistChanged();
                listener.PlaylistPositionChanged();
            }
        } else {
            mediaElementList.add(currentListPosition + 1, mediaElement);

            // Update listeners
            for (AudioPlayerListener listener : listeners) {
                listener.PlaylistChanged();
            }
        }
    }

    public void addAllAndPlayNext(ArrayList<MediaElement> mediaElements) {
        if (mediaElementList.isEmpty()) {
            this.mediaElementList.addAll(mediaElements);
            currentListPosition = 0;
            cleanupPlayer();
            initialiseTrack(currentListPosition);

            // Update listeners
            for (AudioPlayerListener listener : listeners) {
                listener.PlaylistChanged();
                listener.PlaylistPositionChanged();
            }
        } else {
            mediaElementList.addAll(currentListPosition + 1, mediaElements);

            // Update listeners
            for (AudioPlayerListener listener : listeners) {
                listener.PlaylistChanged();
            }
        }
    }

    public void addAllToQueue(ArrayList<MediaElement> mediaElements) {
        if (mediaElements == null) {
            return;
        }
        boolean queueTrack = currentListPosition == (mediaElementList.size() - 1);
        this.mediaElementList.addAll(mediaElements);

        // Update listeners
        for (AudioPlayerListener listener : listeners) {
            listener.PlaylistChanged();
        }
    }

    public void addToQueue(MediaElement mediaElement) {
        boolean queueTrack = currentListPosition == (mediaElementList.size() - 1);

        mediaElementList.add(mediaElement);

        // Update listeners
        for (AudioPlayerListener listener : listeners) {
            listener.PlaylistChanged();
        }
    }

    public void removeMediaElementFromList(long id) {
        Integer position = null;

        // Find the element id in the playlist
        for (int i = 0; i < mediaElementList.size(); i++) {
            if (mediaElementList.get(i).getID().equals(id)) {
                position = i;
                mediaElementList.remove(i);
            }
        }

        // Don't continue if the element isn't found
        if (position == null) {
            return;
        }

        // If the track being removed is before the current playing track we need to re-sync the list position.
        if (player != null && position < currentListPosition) {
            currentListPosition--;
            position--;
        }

        if (player != null && position == currentListPosition) {
            stop();
        }

        // Update listeners
        for (AudioPlayerListener listener : listeners) {
            listener.PlaylistChanged();
            listener.PlaylistPositionChanged();
        }
    }

    public void clearMediaList() {
        mediaElementList.clear();
        currentListPosition = 0;
        isPaused = false;
        cleanupPlayer();

        // Update state
        mediaState = PlaybackStateCompat.STATE_NONE;
        updatePlaybackState();

        // Update listeners
        for (AudioPlayerListener listener : listeners) {
            listener.PlaylistChanged();
            listener.PlaybackStateChanged();
            listener.PlaylistPositionChanged();
        }
    }

    public void setMediaListPosition(int position) {
        currentListPosition = position;
    }

    public void setMediaListPosition(MediaElement element) {
        if (mediaElementList.contains(element)) {
            currentListPosition = mediaElementList.indexOf(element);
        }
    }

    public int getMediaListPosition() {
        return currentListPosition;
    }

    public ArrayList<MediaElement> getMediaList() {
        return mediaElementList;
    }

    public MediaElement getMediaElement() {
        if (mediaElementList.isEmpty()) {
            return null;
        } else {
            return mediaElementList.get(currentListPosition);
        }
    }

    public void initialiseTrack(int position) {

        // Get settings
        final SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);

        // Get media element to play
        final MediaElement mediaElement = mediaElementList.get(position);

        if (mediaElement == null) {
            Toast error = Toast.makeText(getApplicationContext(), getString(R.string.error_media_playback),
                    Toast.LENGTH_SHORT);
            error.show();
            return;
        }

        // Initialise Stream
        restService.initialiseStream(getApplicationContext(), mediaElement.getID(), SUPPORTED_FILES,
                SUPPORTED_CODECS, null, null, Integer.parseInt(settings.getString("pref_audio_quality", "0")),
                MAX_SAMPLE_RATE, null, null, settings.getBoolean("pref_direct_play", false),
                new JsonHttpResponseHandler() {

                    @Override
                    public void onSuccess(int statusCode, cz.msebera.android.httpclient.Header[] headers,
                            JSONObject response) {
                        // Initialise player
                        player = new SMSAudioPlayer();

                        // Update state
                        mediaState = PlaybackStateCompat.STATE_CONNECTING;
                        updatePlaybackState();

                        // Parse profile
                        Gson parser = new Gson();
                        TranscodeProfile profile = parser.fromJson(response.toString(), TranscodeProfile.class);

                        // Setup Player
                        player.setID(mediaElement.getID());
                        player.setDuration(mediaElement.getDuration());
                        player.setTranscodeProfile(profile);
                        player.setQuality(Integer.parseInt(settings.getString("pref_audio_quality", "0")));

                        // Streaming status
                        if (profile.getType() == TranscodeProfile.StreamType.FILE) {
                            player.setStreaming(false);
                        } else {
                            player.setStreaming(true);
                        }

                        try {
                            preparePlayer();
                            isPaused = false;

                            // Update metadata
                            mediaSession.setMetadata(MediaUtils.getMediaMetadata(mediaElement, null));

                            // Attempt to get album art
                            Glide.with(getApplicationContext())
                                    .load(RESTService.getInstance().getConnection().getUrl() + "/image/"
                                            + mediaElement.getID() + "/cover/300")
                                    .asBitmap().into(new SimpleTarget<Bitmap>() {
                                        @Override
                                        public void onResourceReady(Bitmap image,
                                                GlideAnimation<? super Bitmap> glideAnimation) {
                                            // Update metadata with artwork
                                            mediaSession
                                                    .setMetadata(MediaUtils.getMediaMetadata(mediaElement, image));
                                        }
                                    });

                            // Update listeners
                            for (AudioPlayerListener listener : listeners) {
                                listener.PlaybackStateChanged();
                                listener.PlaylistPositionChanged();
                            }

                        } catch (Exception e) {
                            cleanupPlayer();
                        }
                    }

                    @Override
                    public void onFailure(int statusCode, cz.msebera.android.httpclient.Header[] headers,
                            Throwable throwable, JSONObject response) {
                        error();
                    }

                    private void error() {
                        Toast error = Toast.makeText(getApplicationContext(),
                                getString(R.string.error_media_playback), Toast.LENGTH_SHORT);
                        error.show();

                        currentListPosition = 0;

                        // Update state
                        mediaState = PlaybackStateCompat.STATE_ERROR;
                        updatePlaybackState();

                        // Update listeners
                        for (AudioPlayerListener listener : listeners) {
                            listener.PlaybackStateChanged();
                            listener.PlaylistPositionChanged();
                        }
                    }
                });
    }

    private void preparePlayer() {
        // Request audio focus for playback
        int result = audioManager.requestAudioFocus(audioFocusListener, AudioManager.STREAM_MUSIC,
                AudioManager.AUDIOFOCUS_GAIN);

        if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
            // Start playback
            String streamUrl = restService.getConnection().getUrl() + "/stream/"
                    + player.getTranscodeProfile().getID() + "?offset=" + (int) (player.getOffset() * 0.001);
            Uri contentUri = Uri.parse(streamUrl);

            player.addListener(this);
            player.initialise(this, contentUri, true);

            wakeLock.acquire();
            wifiLock.acquire();

            if (!mediaSession.isActive()) {
                mediaSession.setActive(true);
            }

            // Register receiver for audio manager events
            registerAudioManagerReceiver();
        }
    }

    private void cleanupPlayer() {
        if (player != null) {
            if (player.getTranscodeProfile() != null) {
                restService.endJob(player.getTranscodeProfile().getID());
            }

            // Abandon audio focus
            audioManager.abandonAudioFocus(audioFocusListener);

            player.release();
            player = null;

            // Unregister audio manager receiver
            unregisterReceiver(audioManagerReceiver);

            if (wakeLock.isHeld()) {
                wakeLock.release();
            }

            if (wifiLock.isHeld()) {
                wifiLock.release();
            }
        }
    }

    //
    // Helper Functions
    //
    private void updatePlaybackState() {
        // Check media session
        if (mediaSession == null) {
            return;
        }

        // Update state
        //noinspection WrongConstant
        mediaSession.setPlaybackState(new PlaybackStateCompat.Builder()
                .setState(mediaState, getCurrentPosition() * 1000, 1.0f).setActions(getAvailableActions()).build());
    }

    private long getAvailableActions() {
        long actions = PlaybackStateCompat.ACTION_PLAY_PAUSE | PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID;

        if (mediaElementList == null || mediaElementList.isEmpty()) {
            return actions;
        }

        if (mediaState == PlaybackStateCompat.STATE_PLAYING) {
            actions |= PlaybackStateCompat.ACTION_PAUSE;
        } else {
            actions |= PlaybackStateCompat.ACTION_PLAY;
        }

        if (currentListPosition > 0) {
            actions |= PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS;
        }

        if (currentListPosition < mediaElementList.size() - 1) {
            actions |= PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
        }

        return actions;
    }

    public MediaSessionCompat.Token getSessionToken() {
        if (mediaSession == null) {
            return null;
        }

        return mediaSession.getSessionToken();
    }

    //
    // Player Control
    //
    public void playPrev() {
        if (mediaElementList == null) {
            return;
        }
        if (mediaElementList.size() > (currentListPosition - 1) && (currentListPosition - 1) >= 0) {
            // Update state
            mediaState = PlaybackStateCompat.STATE_SKIPPING_TO_PREVIOUS;
            updatePlaybackState();

            currentListPosition--;
            cleanupPlayer();
            initialiseTrack(currentListPosition);
        }

        // Update listeners
        for (AudioPlayerListener listener : listeners) {
            listener.PlaybackStateChanged();
            listener.PlaylistPositionChanged();
        }
    }

    public void playNext() {
        if (mediaElementList == null) {
            return;
        }
        if (mediaElementList.size() > (currentListPosition + 1)) {
            // Update state
            mediaState = PlaybackStateCompat.STATE_SKIPPING_TO_NEXT;
            updatePlaybackState();

            currentListPosition++;
            cleanupPlayer();
            initialiseTrack(currentListPosition);
        }

        // Update listeners
        for (AudioPlayerListener listener : listeners) {
            listener.PlaybackStateChanged();
            listener.PlaylistPositionChanged();
        }
    }

    public long getCurrentPosition() {
        if (player == null) {
            return 0;
        }
        return player.getCurrentPosition();
    }

    public long getDuration() {
        if (player == null) {
            return -1;
        }
        return player.getDuration();
    }

    public boolean isPlaying() {
        if (player == null) {
            return false;
        }
        return player.isPlaying();
    }

    public boolean isPaused() {
        return isPaused;
    }

    public void pause() {
        if (player == null) {
            return;
        }
        player.pause();
        isPaused = true;

        if (wakeLock.isHeld()) {
            wakeLock.release();
        }

        if (wifiLock.isHeld()) {
            wifiLock.release();
        }

        // Update state
        mediaState = PlaybackStateCompat.STATE_PAUSED;
        updatePlaybackState();

        // Update listeners
        for (AudioPlayerListener listener : listeners) {
            listener.PlaybackStateChanged();
        }
    }

    public void stop() {
        if (player == null) {
            return;
        }
        cleanupPlayer();
        currentListPosition = 0;
        isPaused = false;

        // Update state
        mediaState = PlaybackStateCompat.STATE_STOPPED;
        updatePlaybackState();

        // Update listeners
        for (AudioPlayerListener listener : listeners) {
            listener.PlaybackStateChanged();
            listener.PlaylistPositionChanged();
        }
    }

    public void seek(int position) {
        if (player == null) {
            return;
        }

        if (player.isStreaming()) {
            // Generate new stream uri
            String streamUrl = restService.getConnection().getUrl() + "/stream/"
                    + player.getTranscodeProfile().getID() + "?offset=" + position;
            Uri contentUri = Uri.parse(streamUrl);

            // Initialise player in new position
            player.release();
            player.setOffset(position);
            player.initialise(this, contentUri, !isPaused());
        } else {
            player.seek(position);
        }
    }

    public void start() {
        if (mediaState == PlaybackStateCompat.STATE_STOPPED) {
            play();
        } else if (mediaState == PlaybackStateCompat.STATE_PAUSED) {
            player.start();

            // Update state
            mediaState = PlaybackStateCompat.STATE_PLAYING;
            updatePlaybackState();

            wakeLock.acquire();
            wifiLock.acquire();
        }

        isPaused = false;

        // Update listeners
        for (AudioPlayerListener listener : listeners) {
            listener.PlaybackStateChanged();
        }
    }

    //
    // Player Callbacks
    //
    @Override
    public void onStateChanged(SMSAudioPlayer player, boolean playWhenReady, int playbackState) {
        switch (playbackState) {
        case ExoPlayer.STATE_BUFFERING:
            // Update state
            mediaState = PlaybackStateCompat.STATE_BUFFERING;
            updatePlaybackState();
            break;

        case ExoPlayer.STATE_ENDED:
            // Clean-up resources
            cleanupPlayer();

            if (mediaElementList.size() > (currentListPosition + 1)) {
                currentListPosition++;
                initialiseTrack(currentListPosition);

                // Update state
                mediaState = PlaybackStateCompat.STATE_SKIPPING_TO_NEXT;
                updatePlaybackState();
            } else {
                // Playlist has ended
                cleanupPlayer();
                currentListPosition = 0;

                // Update state
                mediaState = PlaybackStateCompat.STATE_STOPPED;
                updatePlaybackState();
            }

            // Update listeners
            for (AudioPlayerListener listener : listeners) {
                listener.PlaybackStateChanged();
                listener.PlaylistPositionChanged();
            }

            break;

        case ExoPlayer.STATE_IDLE:
            break;

        case ExoPlayer.STATE_PREPARING:
            // Update state
            mediaState = PlaybackStateCompat.STATE_CONNECTING;
            updatePlaybackState();

            break;

        case ExoPlayer.STATE_READY:
            if (playWhenReady) {
                // Update state
                mediaState = PlaybackStateCompat.STATE_PLAYING;
                updatePlaybackState();
            }

            break;

        default:
            break;
        }
    }

    @Override
    public void onError(Exception e) {
        cleanupPlayer();
        currentListPosition = 0;

        // Update state
        mediaState = PlaybackStateCompat.STATE_ERROR;
        updatePlaybackState();

        // Update listeners
        for (AudioPlayerListener listener : listeners) {
            listener.PlaybackStateChanged();
            listener.PlaylistPositionChanged();
        }
    }

    private void registerAudioManagerReceiver() {
        IntentFilter filter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);

        audioManagerReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
                    // Pause playback
                    pause();
                }
            }
        };

        registerReceiver(audioManagerReceiver, filter);
    }

    private class MediaSessionCallback extends MediaSessionCompat.Callback {
        @Override
        public void onPlay() {
            start();
        }

        @Override
        public void onSeekTo(long position) {
            seek((int) position);
        }

        @Override
        public void onPause() {
            pause();
        }

        @Override
        public void onStop() {
            stop();
        }

        @Override
        public void onSkipToNext() {
            playNext();
        }

        @Override
        public void onSkipToPrevious() {
            playPrev();
        }

        @Override
        public boolean onMediaButtonEvent(Intent intent) {
            if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
                KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);

                if (event.getAction() == KeyEvent.ACTION_DOWN) {
                    if (KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE == event.getKeyCode()) {
                        if (isPlaying()) {
                            pause();
                        } else {
                            start();
                        }
                    } else if (KeyEvent.KEYCODE_MEDIA_PLAY == event.getKeyCode()) {
                        start();
                    } else if (KeyEvent.KEYCODE_MEDIA_PAUSE == event.getKeyCode()) {
                        pause();
                    } else if (KeyEvent.KEYCODE_MEDIA_NEXT == event.getKeyCode()) {
                        playNext();
                    } else if (KeyEvent.KEYCODE_MEDIA_PREVIOUS == event.getKeyCode()) {
                        playPrev();
                    }
                }
            }

            return true;
        }
    }

    public interface AudioPlayerListener {
        void PlaybackStateChanged();

        void PlaylistPositionChanged();

        void PlaylistChanged();
    }
}