2
     * Makes sure the media player exists and has been reset. This will create the media player 
     * if needed, or reset the existing media player if one already exists. 
     */ 
    void createMediaPlayerIfNeeded() { 
        if (mPlayer == null) {
            mPlayer = new MediaPlayer();
 
            // Make sure the media player will acquire a wake-lock while playing. If we don't do 
            // that, the CPU might go to sleep while the song is playing, causing playback to stop. 
            // 
            // Remember that to use this, we have to declare the android.permission.WAKE_LOCK 
            // permission in AndroidManifest.xml. 
            mPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
 
            // we want the media player to notify us when it's ready preparing, and when it's done 
            // playing: 
            mPlayer.setOnPreparedListener(this);
            mPlayer.setOnCompletionListener(this);
            mPlayer.setOnErrorListener(this);
        } 
        else 
            mPlayer.reset();
    } 
 
    @Override 
    public void onCreate() { 
        Log.i(TAG, "debug: Creating service");
         
        playList.service = this;
 
        mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
 
        // create the Audio Focus Helper, if the Audio Focus feature is available (SDK 8 or above) 
        if (android.os.Build.VERSION.SDK_INT >= 8)
            mAudioFocusHelper = new AudioFocusHelper(getApplicationContext(), this);
        else 
            mAudioFocus = AudioFocus.Focused; // no focus feature, so we always "have" audio focus
    } 
 
    /** 
     * Called when we receive an Intent. When we receive an intent sent to us via startService(), 
     * this is the method that gets called. So here we react appropriately depending on the 
     * Intent's action, which specifies what is being requested of us. 
     */ 
    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) {
        // String action = intent.getAction(); 
 
        return START_NOT_STICKY; // Means we started the service, but don't want it to
                                 // restart in case it's killed. 
    } 
     
    public void processPlayPauseRequest() { 
    	switch (mState) {
    		case Stopped:
	            // If we're stopped, just go ahead to the next song and start playing 
    			tryToGetAudioFocus(); 
	            playNextSong(); 
	            break; 
	             
    		case Paused:
	            // If we're paused, just continue playback and restore the 'foreground service' state. 
    			tryToGetAudioFocus(); 
    			mState = State.Playing;
	            setUpAsForeground(null); 
	            configAndStartMediaPlayer(); 
	            break; 
	             
    		case Playing:
    		case Preparing:
    			// Pause media player and cancel the 'foreground service' state. 
                mState = State.Paused;
                mPlayer.pause();
                relaxResources(false); // while paused, we always retain the MediaPlayer 
                giveUpAudioFocus(); 
                break; 
    	} 
    } 
     
    public void processPlayNowRequest() { 
    	tryToGetAudioFocus(); 
    	playNextSong(); 
    } 
     
    public void setPosition(int pos) {
    	if (mPlayer != null) {
    		mPlayer.seekTo(pos);
    	} 
    } 
 
//    void processRewindRequest() { 
//        if (mState == State.Playing || mState == State.Paused) 
//            mPlayer.seekTo(0); 
//    } 
// 
//    void processStopRequest() { 
//        if (mState == State.Playing || mState == State.Paused) { 
//            mState = State.Stopped; 
// 
//            // let go of all resources... 
//            relaxResources(true); 
//            giveUpAudioFocus(); 
//             
//            // TODO call this when finished 
//            // service is no longer necessary. Will be started again if needed. 
//            stopSelf(); 
//        } 
//    } 
 
    /** 
     * Releases resources used by the service for playback. This includes the "foreground service" 
     * status and notification, the wake locks and possibly the MediaPlayer. 
     * 
     * @param releaseMediaPlayer Indicates whether the Media Player should also be released or not 
     */ 
    void relaxResources(boolean releaseMediaPlayer) {
        // stop being a foreground service 
        stopForeground(true);
 
        // stop and release the Media Player, if it's available 
        if (releaseMediaPlayer && mPlayer != null) {
            mPlayer.reset();
            mPlayer.release();
            mPlayer = null;
        } 
    } 
 
    void giveUpAudioFocus() { 
        if (mAudioFocus == AudioFocus.Focused && mAudioFocusHelper != null
                                && mAudioFocusHelper.abandonFocus())
            mAudioFocus = AudioFocus.NoFocusNoDuck;
    } 
 
    /** 
     * Reconfigures MediaPlayer according to audio focus settings and starts/restarts it. This 
     * method starts/restarts the MediaPlayer respecting the current audio focus state. So if 
     * we have focus, it will play normally; if we don't have focus, it will either leave the 
     * MediaPlayer paused or set it to a low volume, depending on what is allowed by the 
     * current focus settings. This method assumes mPlayer != null, so if you are calling it, 
     * you have to do so from a context where you are sure this is the case. 
     */ 
    void configAndStartMediaPlayer() { 
        if (mAudioFocus == AudioFocus.NoFocusNoDuck) {
            // If we don't have audio focus and can't duck, we have to pause, even if mState 
            // is State.Playing. But we stay in the Playing state so that we know we have to resume 
            // playback once we get the focus back. 
            if (mPlayer.isPlaying()) mPlayer.pause();
            return; 
        } 
        else if (mAudioFocus == AudioFocus.NoFocusCanDuck)
            mPlayer.setVolume(DUCK_VOLUME, DUCK_VOLUME);  // we'll be relatively quiet
        else 
            mPlayer.setVolume(1.0f, 1.0f); // we can be loud
 
        if (!mPlayer.isPlaying()) mPlayer.start();
    } 
 
    /** 
     * Shortcut to making and displaying a toast. Seemed cleaner than repeating 
     * this code everywhere, at least for this sample. 
     */ 
    void say(String message) {
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
    } 
 
    void tryToGetAudioFocus() { 
        if (mAudioFocus != AudioFocus.Focused && mAudioFocusHelper != null
                        && mAudioFocusHelper.requestFocus())
            mAudioFocus = AudioFocus.Focused;
    } 
 
    /** 
     * Starts playing the next song. If manualUrl is null, the next song will be randomly selected 
     * from our Media Retriever (that is, it will be a random song in the user's device). If 
     * manualUrl is non-null, then it specifies the URL or path to the song that will be played 
     * next. 
     */ 
    void playNextSong(/*String manualUrl*/) { 
        mState = State.Stopped;
        relaxResources(false); // release everything except MediaPlayer 
 
        AudioFile file = playList.nextFile();
        if (file == null) {
        	return; 
        } 
 
        try { 
            // set the source of the media player a a content URI 
            createMediaPlayerIfNeeded(); 
            mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mPlayer.setDataSource(getApplicationContext(), file.getUri());
 
 
            mState = State.Preparing;
            // MUST call this! 
            setUpAsForeground(file.getTitle() + " (loading)");
 
            // starts preparing the media player in the background. When it's done, it will call 
            // our OnPreparedListener (that is, the onPrepared() method on this class, since we set 
            // the listener to 'this'). 
            // 
            // Until the media player is prepared, we *cannot* call start() on it! 
            mPlayer.prepareAsync();
        } 
        catch (IOException ex) {
            Log.e("MusicService", "IOException playing next song: " + ex.getMessage());
            ex.printStackTrace();
        }