ultrasonic-app-subsonic-and.../ultrasonic/src/main/java/org/moire/ultrasonic/service/MediaPlayerService.java

669 lines
25 KiB
Java
Raw Normal View History

2020-06-21 09:31:38 +02:00
package org.moire.ultrasonic.service;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import org.koin.java.standalone.KoinJavaComponent;
import org.moire.ultrasonic.R;
import org.moire.ultrasonic.activity.DownloadActivity;
import org.moire.ultrasonic.activity.SubsonicTabActivity;
import org.moire.ultrasonic.domain.MusicDirectory;
import org.moire.ultrasonic.domain.PlayerState;
import org.moire.ultrasonic.domain.RepeatMode;
import org.moire.ultrasonic.featureflags.Feature;
import org.moire.ultrasonic.featureflags.FeatureStorage;
import org.moire.ultrasonic.provider.UltraSonicAppWidgetProvider4x1;
import org.moire.ultrasonic.provider.UltraSonicAppWidgetProvider4x2;
import org.moire.ultrasonic.provider.UltraSonicAppWidgetProvider4x3;
import org.moire.ultrasonic.provider.UltraSonicAppWidgetProvider4x4;
import org.moire.ultrasonic.util.FileUtil;
import org.moire.ultrasonic.util.ShufflePlayBuffer;
import org.moire.ultrasonic.util.SimpleServiceBinder;
import org.moire.ultrasonic.util.Util;
import kotlin.Lazy;
import static org.koin.java.standalone.KoinJavaComponent.inject;
2020-06-21 09:31:38 +02:00
import static org.moire.ultrasonic.domain.PlayerState.COMPLETED;
import static org.moire.ultrasonic.domain.PlayerState.DOWNLOADING;
import static org.moire.ultrasonic.domain.PlayerState.IDLE;
import static org.moire.ultrasonic.domain.PlayerState.PAUSED;
import static org.moire.ultrasonic.domain.PlayerState.PREPARING;
import static org.moire.ultrasonic.domain.PlayerState.STARTED;
import static org.moire.ultrasonic.domain.PlayerState.STOPPED;
public class MediaPlayerService extends Service
{
private static final String TAG = MediaPlayerService.class.getSimpleName();
private static final String NOTIFICATION_CHANNEL_ID = "org.moire.ultrasonic";
private static final String NOTIFICATION_CHANNEL_NAME = "Ultrasonic background service";
private static final int NOTIFICATION_ID = 3033;
private static MediaPlayerService instance = null;
private final IBinder binder = new SimpleServiceBinder<>(this);
private final Scrobbler scrobbler = new Scrobbler();
public Lazy<JukeboxService> jukeboxService = inject(JukeboxService.class);
private Lazy<DownloadQueueSerializer> downloadQueueSerializer = inject(DownloadQueueSerializer.class);
private Lazy<ShufflePlayBuffer> shufflePlayBufferLazy = inject(ShufflePlayBuffer.class);
private Lazy<Downloader> downloaderLazy = inject(Downloader.class);
private Lazy<Player> playerLazy = inject(Player.class);
private Player player;
private Downloader downloader;
private ShufflePlayBuffer shufflePlayBuffer;
2020-06-21 09:31:38 +02:00
private boolean isInForeground = false;
private NotificationCompat.Builder notificationBuilder;
public RepeatMode getRepeatMode() { return Util.getRepeatMode(this); }
public static MediaPlayerService getInstance(Context context)
{
for (int i = 0; i < 5; i++)
{
if (instance != null) return instance;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
context.startForegroundService(new Intent(context, MediaPlayerService.class));
}
else
{
context.startService(new Intent(context, MediaPlayerService.class));
}
Util.sleepQuietly(50L);
}
return instance;
}
public static MediaPlayerService getRunningInstance()
{
return instance;
}
@Nullable
@Override
public IBinder onBind(Intent intent)
{
return binder;
}
@Override
public void onCreate()
{
super.onCreate();
downloader = downloaderLazy.getValue();
player = playerLazy.getValue();
shufflePlayBuffer = shufflePlayBufferLazy.getValue();
2020-06-21 09:31:38 +02:00
downloader.onCreate();
shufflePlayBuffer.onCreate();
player.onCreate();
2020-06-23 18:40:44 +02:00
setupOnCurrentPlayingChangedHandler();
setupOnPlayerStateChangedHandler();
setupOnSongCompletedHandler();
player.onPrepared = new Runnable() {
@Override
2020-06-23 18:40:44 +02:00
public void run() {
downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList,
downloader.getCurrentPlayingIndex(), getPlayerPosition());
}
};
player.onNextSongRequested = new Runnable() {
2020-06-23 18:40:44 +02:00
@Override
public void run() {
setNextPlaying();
2020-06-21 09:31:38 +02:00
}
2020-06-23 18:40:44 +02:00
};
2020-06-21 09:31:38 +02:00
// Create Notification Channel
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//The suggested importance of a startForeground service notification is IMPORTANCE_LOW
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
channel.setLightColor(android.R.color.holo_blue_dark);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.createNotificationChannel(channel);
}
// We should use a single notification builder, otherwise the notification may not be updated
notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
// Update notification early. It is better to show an empty one temporarily than waiting too long and letting Android kill the app
2020-06-23 18:40:44 +02:00
updateNotification(IDLE, null);
2020-06-21 09:31:38 +02:00
instance = this;
Log.i(TAG, "MediaPlayerService created");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId)
{
super.onStartCommand(intent, flags, startId);
return START_NOT_STICKY;
}
@Override
public void onDestroy()
{
super.onDestroy();
instance = null;
try
{
player.onDestroy();
shufflePlayBuffer.onDestroy();
downloader.onDestroy();
2020-06-21 09:31:38 +02:00
}
catch (Throwable ignored)
{
}
Log.i(TAG, "MediaPlayerService stopped");
}
public synchronized void seekTo(int position)
{
2020-06-23 18:40:44 +02:00
if (jukeboxService.getValue().isEnabled())
2020-06-21 09:31:38 +02:00
{
jukeboxService.getValue().skip(downloader.getCurrentPlayingIndex(), position / 1000);
2020-06-21 09:31:38 +02:00
}
2020-06-23 18:40:44 +02:00
else
2020-06-21 09:31:38 +02:00
{
player.seekTo(position);
2020-06-21 09:31:38 +02:00
}
}
public synchronized int getPlayerPosition()
{
if (player.playerState == IDLE || player.playerState == DOWNLOADING || player.playerState == PREPARING)
2020-06-21 09:31:38 +02:00
{
return 0;
}
2020-06-23 18:40:44 +02:00
return jukeboxService.getValue().isEnabled() ? jukeboxService.getValue().getPositionSeconds() * 1000 :
player.getPlayerPosition();
2020-06-21 09:31:38 +02:00
}
2020-06-23 18:40:44 +02:00
public synchronized int getPlayerDuration()
2020-06-21 09:31:38 +02:00
{
return player.getPlayerDuration();
2020-06-21 09:31:38 +02:00
}
public synchronized void setCurrentPlaying(int currentPlayingIndex)
{
try
{
player.setCurrentPlaying(downloader.downloadList.get(currentPlayingIndex));
2020-06-21 09:31:38 +02:00
}
catch (IndexOutOfBoundsException x)
{
// Ignored
}
}
2020-06-23 18:40:44 +02:00
public void setupOnCurrentPlayingChangedHandler()
2020-06-21 09:31:38 +02:00
{
player.onCurrentPlayingChanged = new Consumer<DownloadFile>() {
2020-06-23 18:40:44 +02:00
@Override
public void accept(DownloadFile currentPlaying) {
if (currentPlaying != null)
{
Util.broadcastNewTrackInfo(MediaPlayerService.this, currentPlaying.getSong());
Util.broadcastA2dpMetaDataChange(MediaPlayerService.this, getPlayerPosition(), currentPlaying,
downloader.getDownloads().size(), downloader.getCurrentPlayingIndex() + 1);
2020-06-23 18:40:44 +02:00
}
else
{
Util.broadcastNewTrackInfo(MediaPlayerService.this, null);
Util.broadcastA2dpMetaDataChange(MediaPlayerService.this, getPlayerPosition(), null,
downloader.getDownloads().size(), downloader.getCurrentPlayingIndex() + 1);
2020-06-23 18:40:44 +02:00
}
2020-06-21 09:31:38 +02:00
2020-06-23 18:40:44 +02:00
// Update widget
PlayerState playerState = player.playerState;
2020-06-23 18:40:44 +02:00
MusicDirectory.Entry song = currentPlaying == null? null : currentPlaying.getSong();
UltraSonicAppWidgetProvider4x1.getInstance().notifyChange(MediaPlayerService.this, song, playerState == PlayerState.STARTED, false);
UltraSonicAppWidgetProvider4x2.getInstance().notifyChange(MediaPlayerService.this, song, playerState == PlayerState.STARTED, true);
UltraSonicAppWidgetProvider4x3.getInstance().notifyChange(MediaPlayerService.this, song, playerState == PlayerState.STARTED, false);
UltraSonicAppWidgetProvider4x4.getInstance().notifyChange(MediaPlayerService.this, song, playerState == PlayerState.STARTED, false);
2020-06-21 09:31:38 +02:00
2020-06-23 18:40:44 +02:00
SubsonicTabActivity tabInstance = SubsonicTabActivity.getInstance();
2020-06-21 09:31:38 +02:00
2020-06-23 18:40:44 +02:00
if (currentPlaying != null)
{
if (tabInstance != null) {
updateNotification(player.playerState, currentPlaying);
2020-06-23 18:40:44 +02:00
tabInstance.showNowPlaying();
}
}
else
{
if (tabInstance != null)
{
tabInstance.hideNowPlaying();
stopForeground(true);
player.clearRemoteControl();
2020-06-23 18:40:44 +02:00
isInForeground = false;
stopSelf();
}
}
2020-06-21 09:31:38 +02:00
}
2020-06-23 18:40:44 +02:00
};
2020-06-21 09:31:38 +02:00
}
public synchronized void setNextPlaying()
{
boolean gaplessPlayback = Util.getGaplessPlaybackPreference(this);
if (!gaplessPlayback)
{
player.setNextPlaying(null);
2020-06-21 09:31:38 +02:00
return;
}
int index = downloader.getCurrentPlayingIndex();
2020-06-21 09:31:38 +02:00
if (index != -1)
{
switch (getRepeatMode())
{
case OFF:
index += 1;
break;
case ALL:
index = (index + 1) % downloader.downloadList.size();
2020-06-21 09:31:38 +02:00
break;
case SINGLE:
break;
default:
break;
}
}
player.clearNextPlaying();
2020-06-21 09:31:38 +02:00
if (index < downloader.downloadList.size() && index != -1)
2020-06-21 09:31:38 +02:00
{
player.setNextPlaying(downloader.downloadList.get(index));
2020-06-21 09:31:38 +02:00
}
else
{
player.setNextPlaying(null);
2020-06-21 09:31:38 +02:00
}
}
public synchronized void togglePlayPause()
{
if (player.playerState == PAUSED || player.playerState == COMPLETED || player.playerState == STOPPED)
2020-06-21 09:31:38 +02:00
{
start();
}
else if (player.playerState == IDLE)
2020-06-21 09:31:38 +02:00
{
play();
}
else if (player.playerState == STARTED)
2020-06-21 09:31:38 +02:00
{
pause();
}
}
/**
* Plays either the current song (resume) or the first/next one in queue.
*/
public synchronized void play()
{
int current = downloader.getCurrentPlayingIndex();
2020-06-21 09:31:38 +02:00
if (current == -1)
{
play(0);
}
else
{
play(current);
}
}
public synchronized void play(int index)
{
play(index, true);
}
public synchronized void play(int index, boolean start)
{
Log.v(TAG, String.format("play requested for %d", index));
if (index < 0 || index >= downloader.downloadList.size())
2020-06-21 09:31:38 +02:00
{
resetPlayback();
}
else
{
if (start)
{
if (jukeboxService.getValue().isEnabled())
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
jukeboxService.getValue().skip(index, 0);
player.setPlayerState(STARTED);
2020-06-21 09:31:38 +02:00
}
else
{
player.play(downloader.downloadList.get(index));
2020-06-21 09:31:38 +02:00
}
}
downloader.checkDownloads();
2020-06-21 09:31:38 +02:00
setNextPlaying();
}
}
private synchronized void resetPlayback()
{
player.reset();
player.setCurrentPlaying(null);
downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList,
downloader.getCurrentPlayingIndex(), getPlayerPosition());
2020-06-21 09:31:38 +02:00
}
2020-06-23 18:40:44 +02:00
public synchronized void pause()
2020-06-21 09:31:38 +02:00
{
if (player.playerState == STARTED)
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
if (jukeboxService.getValue().isEnabled())
{
jukeboxService.getValue().stop();
}
else
{
player.pause();
2020-06-23 18:40:44 +02:00
}
player.setPlayerState(PAUSED);
2020-06-21 09:31:38 +02:00
}
2020-06-23 18:40:44 +02:00
}
public synchronized void stop()
{
if (player.playerState == STARTED)
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
if (jukeboxService.getValue().isEnabled())
{
jukeboxService.getValue().stop();
}
else
{
player.pause();
2020-06-23 18:40:44 +02:00
}
2020-06-21 09:31:38 +02:00
}
player.setPlayerState(STOPPED);
2020-06-21 09:31:38 +02:00
}
2020-06-23 18:40:44 +02:00
public synchronized void start()
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
if (jukeboxService.getValue().isEnabled())
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
jukeboxService.getValue().start();
2020-06-21 09:31:38 +02:00
}
2020-06-23 18:40:44 +02:00
else
{
player.start();
2020-06-23 18:40:44 +02:00
}
player.setPlayerState(STARTED);
2020-06-21 09:31:38 +02:00
}
2020-06-23 18:40:44 +02:00
public void setupOnPlayerStateChangedHandler()
2020-06-21 09:31:38 +02:00
{
player.onPlayerStateChanged = new BiConsumer<PlayerState, DownloadFile>() {
2020-06-23 18:40:44 +02:00
@Override
public void accept(PlayerState playerState, DownloadFile currentPlaying) {
if (playerState == PAUSED)
2020-06-21 09:31:38 +02:00
{
downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList, downloader.getCurrentPlayingIndex(), getPlayerPosition());
2020-06-21 09:31:38 +02:00
}
2020-06-23 18:40:44 +02:00
boolean showWhenPaused = (playerState != PlayerState.STOPPED && Util.isNotificationAlwaysEnabled(MediaPlayerService.this));
boolean show = playerState == PlayerState.STARTED || showWhenPaused;
2020-06-21 09:31:38 +02:00
2020-06-23 18:40:44 +02:00
Util.broadcastPlaybackStatusChange(MediaPlayerService.this, playerState);
Util.broadcastA2dpPlayStatusChange(MediaPlayerService.this, playerState, currentPlaying.getSong(),
downloader.downloadList.size() + downloader.backgroundDownloadList.size(),
downloader.downloadList.indexOf(currentPlaying) + 1, getPlayerPosition());
2020-06-21 09:31:38 +02:00
2020-06-23 18:40:44 +02:00
MusicDirectory.Entry song = currentPlaying.getSong();
// Update widget
UltraSonicAppWidgetProvider4x1.getInstance().notifyChange(MediaPlayerService.this, song, playerState == PlayerState.STARTED, false);
UltraSonicAppWidgetProvider4x2.getInstance().notifyChange(MediaPlayerService.this, song, playerState == PlayerState.STARTED, true);
UltraSonicAppWidgetProvider4x3.getInstance().notifyChange(MediaPlayerService.this, song, playerState == PlayerState.STARTED, false);
UltraSonicAppWidgetProvider4x4.getInstance().notifyChange(MediaPlayerService.this, song, playerState == PlayerState.STARTED, false);
SubsonicTabActivity tabInstance = SubsonicTabActivity.getInstance();
2020-06-21 09:31:38 +02:00
2020-06-23 18:40:44 +02:00
if (show)
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
if (tabInstance != null)
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
// Only update notification is player state is one that will change the icon
if (playerState == PlayerState.STARTED || playerState == PlayerState.PAUSED)
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
updateNotification(playerState, currentPlaying);
tabInstance.showNowPlaying();
2020-06-21 09:31:38 +02:00
}
}
}
2020-06-23 18:40:44 +02:00
else
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
if (tabInstance != null)
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
stopForeground(true);
player.clearRemoteControl();
2020-06-23 18:40:44 +02:00
isInForeground = false;
tabInstance.hideNowPlaying();
stopSelf();
2020-06-21 09:31:38 +02:00
}
}
2020-06-23 18:40:44 +02:00
if (playerState == STARTED)
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
scrobbler.scrobble(MediaPlayerService.this, currentPlaying, false);
2020-06-21 09:31:38 +02:00
}
2020-06-23 18:40:44 +02:00
else if (playerState == COMPLETED)
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
scrobbler.scrobble(MediaPlayerService.this, currentPlaying, true);
2020-06-21 09:31:38 +02:00
}
2020-06-23 18:40:44 +02:00
}
};
2020-06-21 09:31:38 +02:00
}
2020-06-23 18:40:44 +02:00
private void setupOnSongCompletedHandler()
2020-06-21 09:31:38 +02:00
{
player.onSongCompleted = new Consumer<DownloadFile>() {
2020-06-21 09:31:38 +02:00
@Override
2020-06-23 18:40:44 +02:00
public void accept(DownloadFile currentPlaying) {
int index = downloader.getCurrentPlayingIndex();
2020-06-21 09:31:38 +02:00
2020-06-23 18:40:44 +02:00
if (currentPlaying != null)
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
final MusicDirectory.Entry song = currentPlaying.getSong();
2020-06-21 09:31:38 +02:00
2020-06-23 18:40:44 +02:00
if (song != null && song.getBookmarkPosition() > 0 && Util.getShouldClearBookmark(MediaPlayerService.this))
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
MusicService musicService = MusicServiceFactory.getMusicService(MediaPlayerService.this);
try
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
musicService.deleteBookmark(song.getId(), MediaPlayerService.this, null);
2020-06-21 09:31:38 +02:00
}
2020-06-23 18:40:44 +02:00
catch (Exception ignored)
2020-06-21 09:31:38 +02:00
{
}
}
2020-06-23 18:40:44 +02:00
}
2020-06-21 09:31:38 +02:00
2020-06-23 18:40:44 +02:00
if (index != -1)
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
switch (getRepeatMode())
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
case OFF:
if (index + 1 < 0 || index + 1 >= downloader.downloadList.size())
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
if (Util.getShouldClearPlaylist(MediaPlayerService.this))
2020-06-21 09:31:38 +02:00
{
2020-06-23 18:40:44 +02:00
clear(true);
jukeboxService.getValue().updatePlaylist();
2020-06-21 09:31:38 +02:00
}
2020-06-23 18:40:44 +02:00
resetPlayback();
break;
2020-06-21 09:31:38 +02:00
}
2020-06-23 18:40:44 +02:00
play(index + 1);
break;
case ALL:
play((index + 1) % downloader.downloadList.size());
2020-06-23 18:40:44 +02:00
break;
case SINGLE:
play(index);
break;
default:
2020-06-21 09:31:38 +02:00
break;
}
}
}
2020-06-23 18:40:44 +02:00
};
2020-06-21 09:31:38 +02:00
}
2020-06-23 18:40:44 +02:00
public synchronized void clear(boolean serialize)
2020-06-21 09:31:38 +02:00
{
player.reset();
downloader.clear();
player.setCurrentPlaying(null);
2020-06-21 09:31:38 +02:00
2020-06-23 18:40:44 +02:00
setNextPlaying();
2020-06-21 09:31:38 +02:00
2020-06-23 18:40:44 +02:00
if (serialize) {
downloadQueueSerializer.getValue().serializeDownloadQueue(downloader.downloadList,
downloader.getCurrentPlayingIndex(), getPlayerPosition());
2020-06-21 09:31:38 +02:00
}
}
2020-06-23 18:40:44 +02:00
public void updateNotification(PlayerState playerState, DownloadFile currentPlaying)
2020-06-21 09:31:38 +02:00
{
if (Util.isNotificationEnabled(this)) {
if (isInForeground == true) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
2020-06-23 18:40:44 +02:00
notificationManager.notify(NOTIFICATION_ID, buildForegroundNotification(playerState, currentPlaying));
2020-06-21 09:31:38 +02:00
}
else {
final NotificationManagerCompat notificationManager =
NotificationManagerCompat.from(this);
2020-06-23 18:40:44 +02:00
notificationManager.notify(NOTIFICATION_ID, buildForegroundNotification(playerState, currentPlaying));
2020-06-21 09:31:38 +02:00
}
Log.w(TAG, "--- Updated notification");
}
else {
2020-06-23 18:40:44 +02:00
startForeground(NOTIFICATION_ID, buildForegroundNotification(playerState, currentPlaying));
2020-06-21 09:31:38 +02:00
isInForeground = true;
Log.w(TAG, "--- Created Foreground notification");
}
}
}
@SuppressWarnings("IconColors")
2020-06-23 18:40:44 +02:00
private Notification buildForegroundNotification(PlayerState playerState, DownloadFile currentPlaying) {
2020-06-21 09:31:38 +02:00
notificationBuilder.setSmallIcon(R.drawable.ic_stat_ultrasonic);
notificationBuilder.setAutoCancel(false);
notificationBuilder.setOngoing(true);
notificationBuilder.setOnlyAlertOnce(true);
notificationBuilder.setWhen(System.currentTimeMillis());
notificationBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
notificationBuilder.setPriority(NotificationCompat.PRIORITY_LOW);
RemoteViews contentView = new RemoteViews(this.getPackageName(), R.layout.notification);
Util.linkButtons(this, contentView, false);
RemoteViews bigView = new RemoteViews(this.getPackageName(), R.layout.notification_large);
Util.linkButtons(this, bigView, false);
notificationBuilder.setContent(contentView);
Intent notificationIntent = new Intent(this, DownloadActivity.class);
notificationBuilder.setContentIntent(PendingIntent.getActivity(this, 0, notificationIntent, 0));
if (playerState == PlayerState.PAUSED || playerState == PlayerState.IDLE) {
contentView.setImageViewResource(R.id.control_play, R.drawable.media_start_normal_dark);
bigView.setImageViewResource(R.id.control_play, R.drawable.media_start_normal_dark);
} else if (playerState == PlayerState.STARTED) {
contentView.setImageViewResource(R.id.control_play, R.drawable.media_pause_normal_dark);
bigView.setImageViewResource(R.id.control_play, R.drawable.media_pause_normal_dark);
}
if (currentPlaying != null) {
final MusicDirectory.Entry song = currentPlaying.getSong();
final String title = song.getTitle();
final String text = song.getArtist();
final String album = song.getAlbum();
final int rating = song.getUserRating() == null ? 0 : song.getUserRating();
final int imageSize = Util.getNotificationImageSize(this);
try {
final Bitmap nowPlayingImage = FileUtil.getAlbumArtBitmap(this, currentPlaying.getSong(), imageSize, true);
if (nowPlayingImage == null) {
contentView.setImageViewResource(R.id.notification_image, R.drawable.unknown_album);
bigView.setImageViewResource(R.id.notification_image, R.drawable.unknown_album);
} else {
contentView.setImageViewBitmap(R.id.notification_image, nowPlayingImage);
bigView.setImageViewBitmap(R.id.notification_image, nowPlayingImage);
}
} catch (Exception x) {
Log.w(TAG, "Failed to get notification cover art", x);
contentView.setImageViewResource(R.id.notification_image, R.drawable.unknown_album);
bigView.setImageViewResource(R.id.notification_image, R.drawable.unknown_album);
}
contentView.setTextViewText(R.id.trackname, title);
bigView.setTextViewText(R.id.trackname, title);
contentView.setTextViewText(R.id.artist, text);
bigView.setTextViewText(R.id.artist, text);
contentView.setTextViewText(R.id.album, album);
bigView.setTextViewText(R.id.album, album);
boolean useFiveStarRating = KoinJavaComponent.get(FeatureStorage.class).isFeatureEnabled(Feature.FIVE_STAR_RATING);
if (!useFiveStarRating)
bigView.setViewVisibility(R.id.notification_rating, View.INVISIBLE);
else {
bigView.setImageViewResource(R.id.notification_five_star_1, rating > 0 ? R.drawable.ic_star_full_dark : R.drawable.ic_star_hollow_dark);
bigView.setImageViewResource(R.id.notification_five_star_2, rating > 1 ? R.drawable.ic_star_full_dark : R.drawable.ic_star_hollow_dark);
bigView.setImageViewResource(R.id.notification_five_star_3, rating > 2 ? R.drawable.ic_star_full_dark : R.drawable.ic_star_hollow_dark);
bigView.setImageViewResource(R.id.notification_five_star_4, rating > 3 ? R.drawable.ic_star_full_dark : R.drawable.ic_star_hollow_dark);
bigView.setImageViewResource(R.id.notification_five_star_5, rating > 4 ? R.drawable.ic_star_full_dark : R.drawable.ic_star_hollow_dark);
}
}
Notification notification = notificationBuilder.build();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
notification.bigContentView = bigView;
}
return notification;
}
}