/*
* Copyright 2016 Substance Mobile
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.animbus.music.media;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.media.session.MediaButtonReceiver;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.support.v7.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
import com.animbus.music.R;
import com.animbus.music.media.objects.Album;
import com.animbus.music.media.objects.Song;
import com.animbus.music.ui.activity.nowPlaying.NowPlaying;
import java.util.ArrayList;
import java.util.List;
import static android.content.Intent.ACTION_MEDIA_BUTTON;
import static android.media.AudioManager.AUDIOFOCUS_GAIN;
import static android.media.AudioManager.AUDIOFOCUS_LOSS;
import static android.media.AudioManager.AUDIOFOCUS_LOSS_TRANSIENT;
import static android.media.AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK;
import static android.media.AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
import static android.media.AudioManager.STREAM_MUSIC;
import static android.support.v4.app.NotificationCompat.CATEGORY_TRANSPORT;
import static android.support.v4.app.NotificationCompat.PRIORITY_MAX;
import static android.support.v4.app.NotificationCompat.VISIBILITY_PUBLIC;
import static android.support.v4.media.session.MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS;
import static android.support.v4.media.session.MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS;
import static android.support.v4.media.session.PlaybackStateCompat.ACTION_PAUSE;
import static android.support.v4.media.session.PlaybackStateCompat.ACTION_PLAY;
import static android.support.v4.media.session.PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID;
import static android.support.v4.media.session.PlaybackStateCompat.ACTION_SEEK_TO;
import static android.support.v4.media.session.PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
import static android.support.v4.media.session.PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS;
import static android.support.v4.media.session.PlaybackStateCompat.ACTION_STOP;
import static android.support.v4.media.session.PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN;
import static android.support.v4.media.session.PlaybackStateCompat.STATE_BUFFERING;
import static android.support.v4.media.session.PlaybackStateCompat.STATE_FAST_FORWARDING;
import static android.support.v4.media.session.PlaybackStateCompat.STATE_NONE;
import static android.support.v4.media.session.PlaybackStateCompat.STATE_PAUSED;
import static android.support.v4.media.session.PlaybackStateCompat.STATE_PLAYING;
import static android.support.v4.media.session.PlaybackStateCompat.STATE_REWINDING;
import static android.support.v4.media.session.PlaybackStateCompat.STATE_SKIPPING_TO_NEXT;
import static android.support.v4.media.session.PlaybackStateCompat.STATE_SKIPPING_TO_PREVIOUS;
import static android.support.v4.media.session.PlaybackStateCompat.STATE_STOPPED;
/**
* Created by Adrian on 11/21/2015.
*/
public class MediaService extends Service {
private static final String TAG = "MediaService";
private static final int FOREGROUND_ID = 654321654;
static final String ACTION_START = "GEM_START_SERVICE";
PlaybackStateCompat mState;
MediaSessionCompat mSession;
PlaybackBase IMPL;
///////////////////////////////////////////////////////////////////////////
// Binding
///////////////////////////////////////////////////////////////////////////
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (ACTION_START.equals(intent.getAction())) {
setUp();
} else if (ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
MediaButtonReceiver.handleIntent(mSession, intent);
}
return START_STICKY;
}
///////////////////////////////////////////////////////////////////////////
// A few classes used for media playback
///////////////////////////////////////////////////////////////////////////
static abstract class PlaybackBase extends MediaSessionCompat.Callback {
private static final String TAG = "PlaybackBase";
public static final String ACTION_PLAY_FROM_LIST = "GEM_PLAY_FROM_LIST";
public static final String ACTION_SET_REPEAT = "GEM_SET_REPEAT";
private static final long PREV_RESTARTS_AFTER = 5000;
abstract void init(MediaService service);
abstract void play(Uri uri, boolean notifyPlaybackRemote);
abstract void play(Song song);
abstract void play(List<Song> songs, int startPos);
abstract void resume();
abstract void pause();
abstract void next();
abstract void doPrev();
void prev() {
Log.d(TAG, "prev() called. Calling doPrev() = " + (getCurrentPosInSong() < PREV_RESTARTS_AFTER));
//Previous only plays the previous song up to 5 seconds into the song. Afterwards it just restarts the song.
if (getCurrentPosInSong() < PREV_RESTARTS_AFTER) {
doPrev();
} else {
restart();
}
}
abstract void restart();
abstract void stop();
abstract void repeat(boolean repeating);
abstract void seek(long time);
abstract boolean isPlaying();
abstract boolean isRepeating();
abstract boolean isInitialized();
abstract int getCurrentPosInSong();
@Override
public void onCustomAction(String action, Bundle extras) {
if (ACTION_PLAY_FROM_LIST.equals(action)) {
play(PlaybackRemote.tempSongList, PlaybackRemote.tempListStartPos);
} else if (ACTION_SET_REPEAT.equals(action)) {
repeat(PlaybackRemote.tempRepeating);
}
}
@Override
public void onPlayFromUri(Uri uri, Bundle extras) {
play(uri, PlaybackRemote.tempNotifyListener);
}
@Override
public void onPlayFromMediaId(String mediaId, Bundle extras) {
play(Library.findSongById(Long.valueOf(mediaId)));
}
@Override
public void onPlayFromSearch(String query, Bundle extras) {
//TODO Add this
}
@Override
public void onPlay() {
resume();
}
@Override
public void onPause() {
pause();
}
@Override
public void onSkipToNext() {
next();
}
@Override
public void onSkipToPrevious() {
prev();
}
@Override
public void onSeekTo(long pos) {
seek(pos);
}
@Override
public void onStop() {
stop();
}
}
static class LocalPlayback extends PlaybackBase implements AudioManager.OnAudioFocusChangeListener,
MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener, MediaPlayer.OnPreparedListener {
private static final String TAG = "LocalPlayback";
IntentFilter mNoisyFilter = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
//Actual Media Player
private MediaPlayer mMediaPlayer;
//AudioManager for audiofocus
private AudioManager mAudioManager;
//The service that this has been injected into
private MediaService mService;
//The uri of the currently playing song
private Uri mCurrentUri;
//For when audiofocus is lost and playback was paused.
//Gives a way to be able to tell that playback was paused and thus the playback won't start on an audiofocus gain
private boolean mWasPlaying = true;
///////////////////////////////////////////////////////////////////////////
// Audio Becoming Noisy filter
///////////////////////////////////////////////////////////////////////////
//Self explanatory. Indicates that GEM has audio focus in the system.
private boolean mHasAudioFocus = false;
BroadcastReceiver mAudioNoisyReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) {
Log.d(TAG, "AudioNoisy received. Pausing");
if (isPlaying()) pause();
}
}
};
///////////////////////////////////////////////////////////////////////////
// Configure this with service
///////////////////////////////////////////////////////////////////////////
@Override
public void init(MediaService service) {
Log.d(TAG, "init() called");
mService = service;
mAudioManager = (AudioManager) service.getSystemService(Context.AUDIO_SERVICE);
}
///////////////////////////////////////////////////////////////////////////
// Controls
///////////////////////////////////////////////////////////////////////////
@Override
public void play(Uri uri, boolean notifyPlaybackRemote) {
Log.d(TAG, "play(Uri) called. Uri = " + uri.toString());
requestAudioFocus();
mWasPlaying = true;
mService.registerReceiver(mAudioNoisyReceiver, mNoisyFilter);
Log.d(TAG, "play(Uri): Noisy receiver registered");
if (uri != mCurrentUri) {
Log.d(TAG, "play(Uri): Uri is different. Playing new song");
//Song is different
mCurrentUri = uri;
try {
createMediaPlayerIfNeeded();
mMediaPlayer.setDataSource(mService, uri);
mMediaPlayer.setAudioStreamType(STREAM_MUSIC);
mService.setState(STATE_PLAYING);
prepareAndNotifyService();
} catch (Exception e) {
Log.e(TAG, "play(Uri): Error", e);
}
//Basically gives a song filled with dummy content
if (notifyPlaybackRemote) PlaybackRemote.updateSongListeners(uri);
} else {
Log.d(TAG, "play(Uri): Uri is the same. Restarting this song");
//Same song, restart playback
seek(0);
//Prepares the media player and it will start it eventually
prepareAndNotifyService();
}
}
@Override
public void play(Song song) {
Log.d(TAG, "play(Song) called. Song = " + song.getID());
play(song.getUri(), false);
PlaybackRemote.updateSongListeners(song);
}
@Override
public void play(List<Song> songs, int startPos) {
ArrayList<Song> data = new ArrayList<>(songs);
Log.d(TAG, "play(List, int) called. Start Position = " + startPos);
play(data.get(startPos));
PlaybackRemote.setQueue(data);
PlaybackRemote.setCurrentSongPos(startPos);
}
@Override
public void resume() {
Log.d(TAG, "resume() called");
requestAudioFocus();
mService.setState(STATE_PLAYING);
Log.d(TAG, "resume(): Starting Media Player");
mMediaPlayer.start();
//If interrupted because of audio focus, when foc]us returns then media will resume playing
mWasPlaying = true;
Log.d(TAG, "resume(): Registering Receiver");
mService.registerReceiver(mAudioNoisyReceiver, mNoisyFilter);
}
@Override
public void pause() {
Log.d(TAG, "pause() called. Calling pause(boolean)");
pause(true);
}
private void pause(boolean overrideWasPlaying) {
Log.d(TAG, "pause(boolean) called. overrideWasPlaying = " + overrideWasPlaying);
giveUpAudioFocus();
mService.setState(STATE_PAUSED);
Log.d(TAG, "pause(boolean): Pausing Media Player");
mMediaPlayer.pause();
//If statement because if it is paused because of losing focus we still want to start playing again
if (overrideWasPlaying) {
//If audio focus got taken away and returned, the media won't start playing
mWasPlaying = false;
}
Log.d(TAG, "pause(boolean): Unregistering Receiver");
mService.unregisterReceiver(mAudioNoisyReceiver);
Log.d(TAG, "pause(boolean): Stopping the service from being foreground");
mService.stopForeground(false);
}
@Override
public void next() {
mService.setState(STATE_SKIPPING_TO_NEXT);
Log.d(TAG, "next() called. Calling play(queue, nextSongPos)");
play(PlaybackRemote.getQueue(), PlaybackRemote.getNextSongPos());
}
@Override
public void doPrev() {
mService.setState(STATE_SKIPPING_TO_PREVIOUS);
Log.d(TAG, "doPrev() called. Calling play(queue, prevSongPos)");
play(PlaybackRemote.getQueue(), PlaybackRemote.getPrevSongPos());
}
@Override
void restart() {
Log.d(TAG, "restart() called");
Log.d(TAG, "restart(): Stopping Media Player");
mMediaPlayer.stop();
seek(0);
prepareAndNotifyService();
Log.d(TAG, "restart(): Done");
}
@Override
public void stop() {
Log.d(TAG, "stop() called");
giveUpAudioFocus();
mService.setState(STATE_STOPPED);
mService.stopForeground(true);
Log.d(TAG, "stop(): Unregistering Receiver");
mService.unregisterReceiver(mAudioNoisyReceiver);
Log.d(TAG, "stop(): Stopping player");
mMediaPlayer.stop();
Log.d(TAG, "stop(): Resetting player");
mMediaPlayer.reset();
Log.d(TAG, "stop(): Releasing Player");
mMediaPlayer.release();
Log.d(TAG, "stop(): Making Player null");
mMediaPlayer = null;
Log.d(TAG, "stop(): Killing Service");
mService.stopSelf();
}
@Override
public void repeat(boolean repeating) {
Log.d(TAG, "repeat(boolean) called. repeating = " + repeating);
mMediaPlayer.setLooping(repeating);
}
@Override
public void seek(long time) {
Log.d(TAG, "seek(long) called. time = " + time);
mService.setState(getCurrentPosInSong() != time ? (getCurrentPosInSong() < time ? STATE_FAST_FORWARDING : STATE_REWINDING) : STATE_BUFFERING);
Log.d(TAG, "seek(long): seeking MediaPlayer");
mMediaPlayer.seekTo((int) time);
}
///////////////////////////////////////////////////////////////////////////
// Misc.
///////////////////////////////////////////////////////////////////////////
private void createMediaPlayerIfNeeded() {
Log.d(TAG, "createMediaPlayerIfNeeded() called. Needed = " + (mMediaPlayer == null));
if (mMediaPlayer == null) {
Log.d(TAG, "createMediaPlayerIfNeeded(): Creating Media Player");
mMediaPlayer = new MediaPlayer();
Log.d(TAG, "createMediaPlayerIfNeeded(): Configuring wakelock");
mMediaPlayer.setWakeMode(mService, PowerManager.PARTIAL_WAKE_LOCK);
Log.d(TAG, "createMediaPlayerIfNeeded(): Setting listeners");
mMediaPlayer.setOnCompletionListener(this);
mMediaPlayer.setOnErrorListener(this);
mMediaPlayer.setOnPreparedListener(this);
} else {
//Reset it
Log.d(TAG, "createMediaPlayerIfNeeded(): Resetting Media Player");
mMediaPlayer.reset();
}
}
///////////////////////////////////////////////////////////////////////////
// Variables for service and remote
///////////////////////////////////////////////////////////////////////////
@Override
public boolean isPlaying() {
return mMediaPlayer.isPlaying();
}
@Override
public boolean isRepeating() {
return mMediaPlayer.isLooping();
}
@Override
public boolean isInitialized() {
return mService != null;
}
@Override
int getCurrentPosInSong() {
return mMediaPlayer.getCurrentPosition();
}
void prepareAndNotifyService() {
Log.d(TAG, "prepareAndNotifyService() called");
mService.setState(STATE_BUFFERING);
mMediaPlayer.prepareAsync();
}
///////////////////////////////////////////////////////////////////////////
// Audiofocus
///////////////////////////////////////////////////////////////////////////
private void requestAudioFocus() {
if (!mHasAudioFocus) {
Log.d(TAG, "requestAudioFocus() called. Requesting");
mHasAudioFocus = (mAudioManager.requestAudioFocus(this, STREAM_MUSIC, AUDIOFOCUS_GAIN) == AUDIOFOCUS_REQUEST_GRANTED);
} else {
Log.d(TAG, "requestAudioFocus() called. Already has audio focus");
}
}
private void giveUpAudioFocus() {
if (mHasAudioFocus) {
Log.d(TAG, "giveUpAudioFocus() called. Giving Up");
mHasAudioFocus = !(mAudioManager.abandonAudioFocus(this) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
} else {
Log.d(TAG, "giveUpAudioFocus() called. Doesn't have audio focus anyways");
}
}
@Override
public void onAudioFocusChange(int focusChange) {
mHasAudioFocus = focusChange == AUDIOFOCUS_GAIN;
switch (focusChange) {
case AUDIOFOCUS_GAIN:
if (!isPlaying() && mWasPlaying) {
resume();
}
unDuck();
break;
case AUDIOFOCUS_LOSS:
pause(false);
break;
case AUDIOFOCUS_LOSS_TRANSIENT:
pause(false);
break;
case AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
duck();
break;
}
}
public void duck() {
Log.d(TAG, "duck() called");
mMediaPlayer.setVolume(0.2f, 0.2f);
}
public void unDuck() {
Log.d(TAG, "unDuck() called");
mMediaPlayer.setVolume(1.0f, 1.0f);
}
///////////////////////////////////////////////////////////////////////////
// Listeners for various events
///////////////////////////////////////////////////////////////////////////
@Override
public void onCompletion(MediaPlayer mp) {
next();
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
//Will attempt to play the next song
next();
switch (extra) {
case MediaPlayer.MEDIA_ERROR_UNSUPPORTED:
Toast.makeText(mService, R.string.playback_error_unsupported, Toast.LENGTH_SHORT).show();
return true;
case MediaPlayer.MEDIA_ERROR_IO:
Toast.makeText(mService, R.string.playback_error_IO, Toast.LENGTH_SHORT).show();
return true;
default:
Toast.makeText(mService, R.string.playback_error_generic, Toast.LENGTH_SHORT).show();
return true;
}
}
@Override
public void onPrepared(MediaPlayer mp) {
Log.d(TAG, "onPrepared() called");
//Media player is prepared so we should start it
Log.d(TAG, "onPrepared(): Starting Media Player");
mp.start();
//Make the service foreground
mService.setAsForeground();
}
}
public static class MediaNotification {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//All of the Variables
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
public static final int NOTIFICATION_ID = 1151415975;
public static final int REQ_CODE = 884987321;
static final String ACTION_PLAY = "GEM_NOTIFICATION_PLAY";
static final String ACTION_PAUSE = "GEM_NOTIFICATION_PAUSE";
static final String ACTION_NEXT = "GEM_NOTIFICATION_NEXT";
static final String ACTION_PREV = "GEM_NOTIFICATION_PREV";
static final String ACTION_STOP = "GEM_NOTIFICATION_STOP";
static volatile MediaService mService;
static volatile NotificationCompat.Builder mBuilder;
static final BroadcastReceiver mCommandsReciever = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String s = intent.getAction();
switch (s) {
case ACTION_PLAY:
mService.IMPL.resume();
break;
case ACTION_PAUSE:
mService.IMPL.pause();
break;
case ACTION_NEXT:
mService.IMPL.next();
break;
case ACTION_PREV:
mService.IMPL.prev();
break;
case ACTION_STOP:
mService.IMPL.stop();
mService.unregisterReceiver(this);
break;
}
}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//The constructor
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void init(MediaService service) {
mService = service;
PlaybackRemote.registerStateListener(new PlaybackRemote.StateChangedListener() {
@Override
public void onStateChanged(PlaybackStateCompat newState) {
if (newState.getState() != STATE_NONE && newState.getState() != STATE_STOPPED) update();
}
});
}
static void setUp() {
Song song = PlaybackRemote.getQueue().get(PlaybackRemote.getCurrentSongPos());
PendingIntent stopServiceIntent = PendingIntent.getBroadcast(mService, REQ_CODE, new Intent(ACTION_STOP), PendingIntent.FLAG_CANCEL_CURRENT);
mBuilder = new NotificationCompat.Builder(mService);
mBuilder
.setContentTitle(song.getTitle())
.setContentText(song.getSongArtist())
.setSubText(song.getAlbum().getTitle())
.setStyle(
new NotificationCompat.MediaStyle().setShowActionsInCompactView(0, 1, 2)
.setMediaSession(mService.mSession.getSessionToken()).setShowCancelButton(true).setCancelButtonIntent(stopServiceIntent))
.setSmallIcon(R.mipmap.ic_notificstaion_srini)
.setCategory(CATEGORY_TRANSPORT)
.setVisibility(VISIBILITY_PUBLIC)
.setDeleteIntent(stopServiceIntent)
.setContentIntent(PendingIntent.getActivity(mService, REQ_CODE,
new Intent(mService, NowPlaying.class), PendingIntent.FLAG_CANCEL_CURRENT))
.setShowWhen(false)
.setPriority(PRIORITY_MAX);
song.getAlbum().requestArt(new Album.ArtRequest() {
@Override
public void respond(Bitmap albumArt) {
mBuilder.setLargeIcon(albumArt);
}
});
//The Actions
mBuilder.addAction(R.drawable.ic_skip_previous_white_36dp, mService.getString(R.string.playback_prev), PendingIntent.getBroadcast(mService, REQ_CODE,
new Intent(ACTION_PREV), PendingIntent.FLAG_CANCEL_CURRENT));
if (mService.IMPL.isPlaying()) {
mBuilder.addAction(R.drawable.ic_pause_white_36dp, mService.getString(R.string.playback_pause), PendingIntent.getBroadcast(mService, REQ_CODE,
new Intent(ACTION_PAUSE), PendingIntent.FLAG_CANCEL_CURRENT));
} else {
mBuilder.addAction(R.drawable.ic_play_arrow_white_36dp, mService.getString(R.string.playback_play), PendingIntent.getBroadcast(mService, REQ_CODE,
new Intent(ACTION_PLAY), PendingIntent.FLAG_CANCEL_CURRENT));
}
mBuilder.addAction(R.drawable.ic_skip_next_white_36dp, mService.getString(R.string.playback_next), PendingIntent.getBroadcast(mService, REQ_CODE,
new Intent(ACTION_NEXT), PendingIntent.FLAG_CANCEL_CURRENT));
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_PLAY);
filter.addAction(ACTION_PAUSE);
filter.addAction(ACTION_NEXT);
filter.addAction(ACTION_PREV);
filter.addAction(ACTION_STOP);
mService.registerReceiver(mCommandsReciever, filter);
}
static void update() {
setUp();
if (mService.mSession.isActive())
NotificationManagerCompat.from(mService).notify(NOTIFICATION_ID, getNotification());
}
static Notification getNotification() {
return mBuilder.build();
}
}
///////////////////////////////////////////////////////////////////////////
// The code powering all of the media playback
///////////////////////////////////////////////////////////////////////////
void inject(PlaybackBase impl) {
IMPL = impl;
}
void setUp() {
if (IMPL == null) inject(PlaybackRemote.LOCAL);
IMPL.init(this);
MediaNotification.init(this);
mSession = new MediaSessionCompat(this, TAG);
mSession.setCallback(IMPL);
mSession.setPlaybackToLocal(AudioManager.STREAM_MUSIC);
mSession.setFlags(FLAG_HANDLES_MEDIA_BUTTONS | FLAG_HANDLES_TRANSPORT_CONTROLS);
setState(STATE_NONE);
PlaybackRemote.init(this);
PlaybackRemote.registerSongListener(new PlaybackRemote.SongChangedListener() {
@Override
public void onSongChanged(Song newSong) {
mSession.setMetadata(newSong.data);
}
});
}
void setState(int state) {
Log.d(TAG, "setState(int) called. Building new state");
//This sets up the state
PlaybackStateCompat.Builder mBuilder = new PlaybackStateCompat.Builder();
mBuilder.setActions(
ACTION_PLAY | ACTION_PAUSE | ACTION_SKIP_TO_NEXT | ACTION_SKIP_TO_PREVIOUS | ACTION_STOP |
ACTION_SEEK_TO | ACTION_PLAY_FROM_MEDIA_ID);
long pos;
try {
pos = IMPL.getCurrentPosInSong();
} catch (Exception e) {
pos = PLAYBACK_POSITION_UNKNOWN;
}
mBuilder.setState(state, pos, 1.0f);
mState = mBuilder.build();
//Updates things with the new state
Log.d(TAG, "setState(int): Updating Session with new state");
mSession.setPlaybackState(mState);
PlaybackRemote.updateStateListeners(mState);
//This tells the session weather or not it should be considered active
boolean isActive = state != STATE_NONE && state != STATE_STOPPED && IMPL.isInitialized();
Log.d(TAG, "setState(int): Setting the session's active state to " + isActive);
mSession.setActive(isActive);
}
void setAsForeground() {
Log.d(TAG, "setAsForeground() called");
startForeground(FOREGROUND_ID, MediaNotification.getNotification());
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy() called");
mSession.release();
}
}