Rx Java and Normal compatible for all query
This commit is contained in:
parent
850036e5cc
commit
c2759e3ec0
89 changed files with 2900 additions and 1040 deletions
|
@ -27,12 +27,7 @@ import android.util.Log
|
|||
import android.view.KeyEvent
|
||||
import androidx.core.content.ContextCompat
|
||||
import code.name.monkey.retromusic.BuildConfig
|
||||
import code.name.monkey.retromusic.Constants.ACTION_PAUSE
|
||||
import code.name.monkey.retromusic.Constants.ACTION_PLAY
|
||||
import code.name.monkey.retromusic.Constants.ACTION_REWIND
|
||||
import code.name.monkey.retromusic.Constants.ACTION_SKIP
|
||||
import code.name.monkey.retromusic.Constants.ACTION_STOP
|
||||
import code.name.monkey.retromusic.Constants.ACTION_TOGGLE_PAUSE
|
||||
import code.name.monkey.retromusic.service.MusicService.*
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Hemanth Savarala.
|
||||
*
|
||||
* Licensed under the GNU General Public License v3
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
package code.name.monkey.retromusic.service
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.media.session.MediaSessionCompat
|
||||
import code.name.monkey.retromusic.auto.AutoMediaIDHelper
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote
|
||||
import code.name.monkey.retromusic.helper.ShuffleHelper
|
||||
import code.name.monkey.retromusic.loaders.*
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.providers.MusicPlaybackQueueStore
|
||||
import code.name.monkey.retromusic.service.MusicService.TOGGLE_FAVORITE
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import java.util.*
|
||||
|
||||
|
||||
/**
|
||||
* Created by hemanths on 2019-08-01.
|
||||
*/
|
||||
|
||||
class MediaSessionCallback(private val context: Context,
|
||||
private val musicService: MusicService) : MediaSessionCompat.Callback() {
|
||||
|
||||
override fun onPlay() {
|
||||
super.onPlay()
|
||||
musicService.play()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
musicService.pause()
|
||||
}
|
||||
|
||||
override fun onSkipToNext() {
|
||||
super.onSkipToNext()
|
||||
musicService.playNextSong(true)
|
||||
}
|
||||
|
||||
override fun onSkipToPrevious() {
|
||||
super.onSkipToPrevious()
|
||||
musicService.back(true)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
musicService.quit()
|
||||
}
|
||||
|
||||
override fun onSeekTo(pos: Long) {
|
||||
super.onSeekTo(pos)
|
||||
musicService.seek(pos.toInt())
|
||||
}
|
||||
|
||||
override fun onMediaButtonEvent(mediaButtonIntent: Intent): Boolean {
|
||||
return MediaButtonIntentReceiver.handleIntent(context, mediaButtonIntent)
|
||||
}
|
||||
|
||||
override fun onPlayFromMediaId(mediaId: String?, extras: Bundle?) {
|
||||
super.onPlayFromMediaId(mediaId, extras)
|
||||
|
||||
val musicId = mediaId?.let { AutoMediaIDHelper.extractMusicID(it) }
|
||||
val itemId = musicId?.toInt() ?: -1
|
||||
val songs = arrayListOf<Song>()
|
||||
when (val category = mediaId?.let { AutoMediaIDHelper.extractCategory(it) }) {
|
||||
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_ALBUM -> {
|
||||
val album = AlbumLoader.getAlbum(context, itemId)
|
||||
album.songs?.let { songs.addAll(it) }
|
||||
openQueue(songs, 0, true)
|
||||
}
|
||||
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_ARTIST -> {
|
||||
val artist = ArtistLoader.getArtist(context, itemId)
|
||||
songs.addAll(artist.songs)
|
||||
openQueue(songs, 0, true)
|
||||
}
|
||||
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_PLAYLIST -> {
|
||||
val playlist = PlaylistLoader.getPlaylist(context, itemId)
|
||||
songs.addAll(playlist.getSongs(context))
|
||||
openQueue(songs, 0, true)
|
||||
}
|
||||
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_HISTORY,
|
||||
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_TOP_TRACKS,
|
||||
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_QUEUE -> {
|
||||
val tracks: List<Song>
|
||||
if (category.equals(AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_HISTORY)) {
|
||||
tracks = TopAndRecentlyPlayedTracksLoader.getRecentlyPlayedTracks(context)
|
||||
} else if (category.equals(AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_TOP_TRACKS)) {
|
||||
tracks = TopAndRecentlyPlayedTracksLoader.getTopTracks(context)
|
||||
} else {
|
||||
tracks = MusicPlaybackQueueStore.getInstance(context).savedOriginalPlayingQueue
|
||||
}
|
||||
songs.addAll(tracks)
|
||||
var songIndex = MusicUtil.indexOfSongInList(tracks, itemId)
|
||||
if (songIndex == -1) {
|
||||
songIndex = 0
|
||||
}
|
||||
openQueue(songs, songIndex, true)
|
||||
}
|
||||
AutoMediaIDHelper.MEDIA_ID_MUSICS_BY_SHUFFLE -> {
|
||||
val allSongs = SongLoader.getAllSongs(context)
|
||||
ShuffleHelper.makeShuffleList(allSongs, -1)
|
||||
openQueue(allSongs, 0, true)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun onCustomAction(action: String, extras: Bundle?) {
|
||||
when (action) {
|
||||
/* CYCLE_REPEAT -> {
|
||||
cycleRepeatMode()
|
||||
musicService.updateMediaSessionPlaybackState()
|
||||
}
|
||||
|
||||
TOGGLE_SHUFFLE -> {
|
||||
musicService.toggleShuffle()
|
||||
musicService.updateMediaSessionPlaybackState()
|
||||
}
|
||||
*/
|
||||
TOGGLE_FAVORITE -> {
|
||||
MusicUtil.toggleFavorite(context, MusicPlayerRemote.currentSong)
|
||||
musicService.updateMediaSessionPlaybackState()
|
||||
}
|
||||
else -> {
|
||||
println("Unsupported action: $action")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAndStartPlaying(songs: ArrayList<Song>, itemId: Int) {
|
||||
var songIndex = MusicUtil.indexOfSongInList(songs, itemId)
|
||||
if (songIndex == -1) {
|
||||
songIndex = 0
|
||||
}
|
||||
openQueue(songs, songIndex)
|
||||
}
|
||||
|
||||
private fun openQueue(songs: ArrayList<Song>, index: Int, startPlaying: Boolean = true) {
|
||||
MusicPlayerRemote.openQueue(songs, index, startPlaying)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Hemanth Savarala.
|
||||
*
|
||||
* Licensed under the GNU General Public License v3
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
package code.name.monkey.retromusic.service;
|
||||
|
||||
import android.database.ContentObserver;
|
||||
import android.os.Handler;
|
||||
|
||||
public class MediaStoreObserver extends ContentObserver implements Runnable {
|
||||
// milliseconds to delay before calling refresh to aggregate events
|
||||
private static final long REFRESH_DELAY = 500;
|
||||
private final MusicService musicService;
|
||||
private Handler mHandler;
|
||||
|
||||
MediaStoreObserver(MusicService musicService, Handler handler) {
|
||||
super(handler);
|
||||
this.musicService = musicService;
|
||||
mHandler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
// if a change is detected, remove any scheduled callback
|
||||
// then post a new one. This is intended to prevent closely
|
||||
// spaced events from generating multiple refresh calls
|
||||
mHandler.removeCallbacks(this);
|
||||
mHandler.postDelayed(this, REFRESH_DELAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// actually call refresh when the delayed callback fires
|
||||
// do not send a sticky broadcast here
|
||||
musicService.handleAndSendChangeInternal(MusicService.MEDIA_STORE_CHANGED);
|
||||
}
|
||||
}
|
|
@ -15,7 +15,6 @@
|
|||
package code.name.monkey.retromusic.service;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
|
@ -31,15 +30,15 @@ import android.media.AudioManager;
|
|||
import android.media.audiofx.AudioEffect;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.PowerManager;
|
||||
import android.os.Process;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.v4.media.MediaBrowserCompat;
|
||||
import android.support.v4.media.MediaMetadataCompat;
|
||||
import android.support.v4.media.session.MediaSessionCompat;
|
||||
import android.support.v4.media.session.PlaybackStateCompat;
|
||||
|
@ -50,10 +49,10 @@ import android.widget.Toast;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media.MediaBrowserServiceCompat;
|
||||
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
@ -64,15 +63,14 @@ import code.name.monkey.retromusic.appwidgets.AppWidgetCard;
|
|||
import code.name.monkey.retromusic.appwidgets.AppWidgetClassic;
|
||||
import code.name.monkey.retromusic.appwidgets.AppWidgetSmall;
|
||||
import code.name.monkey.retromusic.appwidgets.AppWidgetText;
|
||||
import code.name.monkey.retromusic.auto.AutoMediaIDHelper;
|
||||
import code.name.monkey.retromusic.auto.AutoMusicProvider;
|
||||
import code.name.monkey.retromusic.glide.BlurTransformation;
|
||||
import code.name.monkey.retromusic.glide.GlideApp;
|
||||
import code.name.monkey.retromusic.glide.GlideRequest;
|
||||
import code.name.monkey.retromusic.glide.RetroGlideExtension;
|
||||
import code.name.monkey.retromusic.glide.RetroSimpleTarget;
|
||||
import code.name.monkey.retromusic.helper.ShuffleHelper;
|
||||
import code.name.monkey.retromusic.helper.StopWatch;
|
||||
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader;
|
||||
import code.name.monkey.retromusic.model.AbsCustomPlaylist;
|
||||
import code.name.monkey.retromusic.model.Playlist;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import code.name.monkey.retromusic.providers.HistoryStore;
|
||||
|
@ -83,57 +81,73 @@ import code.name.monkey.retromusic.service.notification.PlayingNotificationImpl2
|
|||
import code.name.monkey.retromusic.service.notification.PlayingNotificationOreo;
|
||||
import code.name.monkey.retromusic.service.playback.Playback;
|
||||
import code.name.monkey.retromusic.util.MusicUtil;
|
||||
import code.name.monkey.retromusic.util.PackageValidator;
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil;
|
||||
import code.name.monkey.retromusic.util.RetroUtil;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
import static code.name.monkey.retromusic.Constants.ACTION_PAUSE;
|
||||
import static code.name.monkey.retromusic.Constants.ACTION_PENDING_QUIT;
|
||||
import static code.name.monkey.retromusic.Constants.ACTION_PLAY;
|
||||
import static code.name.monkey.retromusic.Constants.ACTION_PLAY_PLAYLIST;
|
||||
import static code.name.monkey.retromusic.Constants.ACTION_QUIT;
|
||||
import static code.name.monkey.retromusic.Constants.ACTION_REWIND;
|
||||
import static code.name.monkey.retromusic.Constants.ACTION_SKIP;
|
||||
import static code.name.monkey.retromusic.Constants.ACTION_STOP;
|
||||
import static code.name.monkey.retromusic.Constants.ACTION_TOGGLE_PAUSE;
|
||||
import static code.name.monkey.retromusic.Constants.APP_WIDGET_UPDATE;
|
||||
import static code.name.monkey.retromusic.Constants.EXTRA_APP_WIDGET_NAME;
|
||||
import static code.name.monkey.retromusic.Constants.INTENT_EXTRA_PLAYLIST;
|
||||
import static code.name.monkey.retromusic.Constants.INTENT_EXTRA_SHUFFLE_MODE;
|
||||
import static code.name.monkey.retromusic.Constants.MEDIA_STORE_CHANGED;
|
||||
import static code.name.monkey.retromusic.Constants.META_CHANGED;
|
||||
import static code.name.monkey.retromusic.Constants.MUSIC_PACKAGE_NAME;
|
||||
import static code.name.monkey.retromusic.Constants.PLAY_STATE_CHANGED;
|
||||
import static code.name.monkey.retromusic.Constants.QUEUE_CHANGED;
|
||||
import static code.name.monkey.retromusic.Constants.REPEAT_MODE_CHANGED;
|
||||
import static code.name.monkey.retromusic.Constants.RETRO_MUSIC_PACKAGE_NAME;
|
||||
import static code.name.monkey.retromusic.Constants.SHUFFLE_MODE_CHANGED;
|
||||
|
||||
/**
|
||||
* @author Karim Abou Zeid (kabouzeid), Andrew Neal
|
||||
*/
|
||||
public class MusicService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener, Playback.PlaybackCallbacks {
|
||||
public class MusicService extends MediaBrowserServiceCompat implements SharedPreferences.OnSharedPreferenceChangeListener, Playback.PlaybackCallbacks {
|
||||
public static final String TAG = MusicService.class.getSimpleName();
|
||||
|
||||
public static final String RETRO_MUSIC_PACKAGE_NAME = "code.name.monkey.retromusic";
|
||||
public static final String MUSIC_PACKAGE_NAME = "com.android.music";
|
||||
|
||||
public static final String ACTION_TOGGLE_PAUSE = RETRO_MUSIC_PACKAGE_NAME + ".togglepause";
|
||||
public static final String ACTION_PLAY = RETRO_MUSIC_PACKAGE_NAME + ".play";
|
||||
public static final String ACTION_PLAY_PLAYLIST = RETRO_MUSIC_PACKAGE_NAME + ".play.playlist";
|
||||
public static final String ACTION_PAUSE = RETRO_MUSIC_PACKAGE_NAME + ".pause";
|
||||
public static final String ACTION_STOP = RETRO_MUSIC_PACKAGE_NAME + ".stop";
|
||||
public static final String ACTION_SKIP = RETRO_MUSIC_PACKAGE_NAME + ".skip";
|
||||
public static final String ACTION_REWIND = RETRO_MUSIC_PACKAGE_NAME + ".rewind";
|
||||
public static final String ACTION_QUIT = RETRO_MUSIC_PACKAGE_NAME + ".quitservice";
|
||||
public static final String ACTION_PENDING_QUIT = RETRO_MUSIC_PACKAGE_NAME + ".pendingquitservice";
|
||||
public static final String INTENT_EXTRA_PLAYLIST = RETRO_MUSIC_PACKAGE_NAME + "intentextra.playlist";
|
||||
public static final String INTENT_EXTRA_SHUFFLE_MODE = RETRO_MUSIC_PACKAGE_NAME + ".intentextra.shufflemode";
|
||||
|
||||
public static final String APP_WIDGET_UPDATE = RETRO_MUSIC_PACKAGE_NAME + ".appwidgetupdate";
|
||||
public static final String EXTRA_APP_WIDGET_NAME = RETRO_MUSIC_PACKAGE_NAME + "app_widget_name";
|
||||
|
||||
// Do not change these three strings as it will break support with other apps (e.g. last.fm scrobbling)
|
||||
public static final String META_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".metachanged";
|
||||
public static final String QUEUE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".queuechanged";
|
||||
public static final String PLAY_STATE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".playstatechanged";
|
||||
|
||||
public static final String FAVORITE_STATE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + "favoritestatechanged";
|
||||
|
||||
public static final String REPEAT_MODE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".repeatmodechanged";
|
||||
public static final String SHUFFLE_MODE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".shufflemodechanged";
|
||||
public static final String MEDIA_STORE_CHANGED = RETRO_MUSIC_PACKAGE_NAME + ".mediastorechanged";
|
||||
|
||||
public static final String CYCLE_REPEAT = RETRO_MUSIC_PACKAGE_NAME + ".cyclerepeat";
|
||||
public static final String TOGGLE_SHUFFLE = RETRO_MUSIC_PACKAGE_NAME + ".toggleshuffle";
|
||||
public static final String TOGGLE_FAVORITE = RETRO_MUSIC_PACKAGE_NAME + ".togglefavorite";
|
||||
|
||||
public static final String SAVED_POSITION = "POSITION";
|
||||
public static final String SAVED_POSITION_IN_TRACK = "POSITION_IN_TRACK";
|
||||
public static final String SAVED_SHUFFLE_MODE = "SHUFFLE_MODE";
|
||||
public static final String SAVED_REPEAT_MODE = "REPEAT_MODE";
|
||||
|
||||
public static final int RELEASE_WAKELOCK = 0;
|
||||
public static final int TRACK_ENDED = 1;
|
||||
public static final int TRACK_WENT_TO_NEXT = 2;
|
||||
public static final int PLAY_SONG = 3;
|
||||
public static final int PREPARE_NEXT = 4;
|
||||
public static final int SET_POSITION = 5;
|
||||
public static final int FOCUS_CHANGE = 6;
|
||||
public static final int DUCK = 7;
|
||||
public static final int UNDUCK = 8;
|
||||
public static final int RESTORE_QUEUES = 9;
|
||||
|
||||
public static final int SHUFFLE_MODE_NONE = 0;
|
||||
public static final int SHUFFLE_MODE_SHUFFLE = 1;
|
||||
|
||||
public static final int REPEAT_MODE_NONE = 0;
|
||||
public static final int REPEAT_MODE_ALL = 1;
|
||||
public static final int REPEAT_MODE_THIS = 2;
|
||||
|
||||
public static final int SAVE_QUEUES = 0;
|
||||
private static final int FOCUS_CHANGE = 6;
|
||||
private static final int DUCK = 7;
|
||||
private static final int UNDUCK = 8;
|
||||
private static final long MEDIA_SESSION_ACTIONS = PlaybackStateCompat.ACTION_PLAY
|
||||
| PlaybackStateCompat.ACTION_PAUSE
|
||||
| PlaybackStateCompat.ACTION_PLAY_PAUSE
|
||||
|
@ -143,6 +157,9 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
| PlaybackStateCompat.ACTION_SEEK_TO;
|
||||
private final IBinder musicBind = new MusicBinder();
|
||||
public boolean pendingQuit = false;
|
||||
public Playback playback;
|
||||
public int position = -1;
|
||||
public int nextPosition = -1;
|
||||
private AppWidgetBig appWidgetBig = AppWidgetBig.Companion.getInstance();
|
||||
private AppWidgetClassic appWidgetClassic = AppWidgetClassic.Companion.getInstance();
|
||||
private AppWidgetSmall appWidgetSmall = AppWidgetSmall.Companion.getInstance();
|
||||
|
@ -179,11 +196,8 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
|
||||
}
|
||||
};
|
||||
private Playback playback;
|
||||
private ArrayList<Song> playingQueue = new ArrayList<>();
|
||||
private ArrayList<Song> originalPlayingQueue = new ArrayList<>();
|
||||
private int position = -1;
|
||||
private int nextPosition = -1;
|
||||
private int shuffleMode;
|
||||
private int repeatMode;
|
||||
private boolean queuesRestored;
|
||||
|
@ -198,7 +212,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
};
|
||||
private PlayingNotification playingNotification;
|
||||
private AudioManager audioManager;
|
||||
@SuppressWarnings("deprecation")
|
||||
private MediaSessionCompat mediaSession;
|
||||
private PowerManager.WakeLock wakeLock;
|
||||
private PlaybackHandler playerHandler;
|
||||
|
@ -235,7 +248,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
super.onCallStateChanged(state, incomingNumber);
|
||||
}
|
||||
};
|
||||
private boolean isServiceBound;
|
||||
private Handler uiThreadHandler;
|
||||
private IntentFilter headsetReceiverIntentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
|
||||
private boolean headsetReceiverRegistered = false;
|
||||
|
@ -260,6 +272,8 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
}
|
||||
}
|
||||
};
|
||||
private PackageValidator mPackageValidator;
|
||||
private AutoMusicProvider mMusicProvider;
|
||||
|
||||
private static String getTrackUri(@NonNull Song song) {
|
||||
return MusicUtil.getSongFileUri(song.getId()).toString();
|
||||
|
@ -278,7 +292,6 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
@ -314,8 +327,8 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
|
||||
initNotification();
|
||||
|
||||
mediaStoreObserver = new MediaStoreObserver(playerHandler);
|
||||
throttledSeekHandler = new ThrottledSeekHandler(playerHandler);
|
||||
mediaStoreObserver = new MediaStoreObserver(this, playerHandler);
|
||||
throttledSeekHandler = new ThrottledSeekHandler(this, playerHandler);
|
||||
getContentResolver().registerContentObserver(
|
||||
MediaStore.Audio.Media.INTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
getContentResolver().registerContentObserver(
|
||||
|
@ -324,14 +337,11 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
PreferenceUtil.getInstance().registerOnSharedPreferenceChangedListener(this);
|
||||
|
||||
restoreState();
|
||||
|
||||
mediaSession.setActive(true);
|
||||
|
||||
mPackageValidator = new PackageValidator(this, R.xml.allowed_media_browser_callers);
|
||||
mMusicProvider = new AutoMusicProvider(this);
|
||||
sendBroadcast(new Intent("code.name.monkey.retromusic.RETRO_MUSIC_SERVICE_CREATED"));
|
||||
|
||||
registerHeadsetEvents();
|
||||
|
||||
|
||||
}
|
||||
|
||||
private AudioManager getAudioManager() {
|
||||
|
@ -354,50 +364,14 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
"RetroMusicPlayer",
|
||||
mediaButtonReceiverComponentName,
|
||||
mediaButtonReceiverPendingIntent);
|
||||
mediaSession.setCallback(new MediaSessionCompat.Callback() {
|
||||
|
||||
@Override
|
||||
public void onPlay() {
|
||||
play();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
pause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToNext() {
|
||||
playNextSong(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToPrevious() {
|
||||
back(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
quit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSeekTo(long pos) {
|
||||
seek((int) pos);
|
||||
updateMediaSessionPlaybackState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMediaButtonEvent(Intent mediaButtonEvent) {
|
||||
return MediaButtonIntentReceiver.Companion.handleIntent(MusicService.this, mediaButtonEvent);
|
||||
}
|
||||
});
|
||||
|
||||
MediaSessionCallback mediasessionCallback = new MediaSessionCallback(getApplicationContext(), this);
|
||||
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS
|
||||
| MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS
|
||||
);
|
||||
|
||||
mediaSession.setCallback(mediasessionCallback);
|
||||
mediaSession.setActive(true);
|
||||
mediaSession.setMediaButtonReceiver(mediaButtonReceiverPendingIntent);
|
||||
setSessionToken(mediaSession.getSessionToken());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -437,6 +411,9 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
case ACTION_PENDING_QUIT:
|
||||
pendingQuit = true;
|
||||
break;
|
||||
case TOGGLE_FAVORITE:
|
||||
MusicUtil.toggleFavorite(getApplicationContext(), getCurrentSong());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -447,22 +424,21 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
private void playFromPlaylist(Intent intent) {
|
||||
Playlist playlist = intent.getParcelableExtra(INTENT_EXTRA_PLAYLIST);
|
||||
int shuffleMode = intent.getIntExtra(INTENT_EXTRA_SHUFFLE_MODE, getShuffleMode());
|
||||
|
||||
if (playlist != null) {
|
||||
if (playlist instanceof AbsCustomPlaylist) {
|
||||
((AbsCustomPlaylist) playlist).getSongs(getApplicationContext())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(songs -> {
|
||||
playSongs(shuffleMode, songs);
|
||||
}, throwable -> {
|
||||
});
|
||||
ArrayList<Song> playlistSongs = playlist.getSongs(getApplicationContext());
|
||||
if (!playlistSongs.isEmpty()) {
|
||||
if (shuffleMode == SHUFFLE_MODE_SHUFFLE) {
|
||||
int startPosition = 0;
|
||||
if (!playlistSongs.isEmpty()) {
|
||||
startPosition = new Random().nextInt(playlistSongs.size());
|
||||
}
|
||||
openQueue(playlistSongs, startPosition, true);
|
||||
setShuffleMode(shuffleMode);
|
||||
} else {
|
||||
openQueue(playlistSongs, 0, true);
|
||||
}
|
||||
} else {
|
||||
PlaylistSongsLoader.INSTANCE.getPlaylistSongList(getApplicationContext(), playlist.id)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(songs -> {
|
||||
playSongs(shuffleMode, songs);
|
||||
}, throwable -> {
|
||||
});
|
||||
Toast.makeText(getApplicationContext(), R.string.playlist_is_empty, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(getApplicationContext(), R.string.playlist_is_empty, Toast.LENGTH_LONG).show();
|
||||
|
@ -507,25 +483,43 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
isServiceBound = true;
|
||||
return musicBind;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) {
|
||||
if (!mPackageValidator.isKnownCaller(clientPackageName, clientUid)) {
|
||||
return new BrowserRoot(AutoMediaIDHelper.MEDIA_ID_EMPTY_ROOT, null);
|
||||
}
|
||||
return new BrowserRoot(AutoMediaIDHelper.MEDIA_ID_ROOT, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadChildren(@NonNull String parentId, @NonNull Result<List<MediaBrowserCompat.MediaItem>> result) {
|
||||
if (AutoMediaIDHelper.MEDIA_ID_EMPTY_ROOT.equals(parentId)) {
|
||||
result.sendResult(new ArrayList<>());
|
||||
} else if (mMusicProvider.isInitialized()) {
|
||||
result.sendResult(mMusicProvider.getChildren(parentId, getResources()));
|
||||
} else {
|
||||
result.detach();
|
||||
mMusicProvider.retrieveMediaAsync(success -> result.sendResult(mMusicProvider.getChildren(parentId, getResources())));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRebind(Intent intent) {
|
||||
isServiceBound = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onUnbind(Intent intent) {
|
||||
isServiceBound = false;
|
||||
if (!isPlaying()) {
|
||||
stopSelf();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void saveQueuesImpl() {
|
||||
public void saveQueuesImpl() {
|
||||
MusicPlaybackQueueStore.getInstance(this).saveQueues(playingQueue, originalPlayingQueue);
|
||||
}
|
||||
|
||||
|
@ -533,7 +527,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
PreferenceManager.getDefaultSharedPreferences(this).edit().putInt(SAVED_POSITION, getPosition()).apply();
|
||||
}
|
||||
|
||||
private void savePositionInTrack() {
|
||||
public void savePositionInTrack() {
|
||||
PreferenceManager.getDefaultSharedPreferences(this).edit().putInt(SAVED_POSITION_IN_TRACK, getSongProgressMillis()).apply();
|
||||
}
|
||||
|
||||
|
@ -558,14 +552,10 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
playerHandler.sendEmptyMessage(RESTORE_QUEUES);
|
||||
}
|
||||
|
||||
private synchronized void restoreQueuesAndPositionIfNecessary() {
|
||||
public synchronized void restoreQueuesAndPositionIfNecessary() {
|
||||
if (!queuesRestored && playingQueue.isEmpty()) {
|
||||
ArrayList<Song> restoredQueue = MusicPlaybackQueueStore.getInstance(this).getSavedPlayingQueue()
|
||||
.blockingFirst();
|
||||
|
||||
ArrayList<Song> restoredOriginalQueue = MusicPlaybackQueueStore.getInstance(this).getSavedOriginalPlayingQueue()
|
||||
.blockingFirst();
|
||||
|
||||
ArrayList<Song> restoredQueue = MusicPlaybackQueueStore.getInstance(this).getSavedPlayingQueue();
|
||||
ArrayList<Song> restoredOriginalQueue = MusicPlaybackQueueStore.getInstance(this).getSavedOriginalPlayingQueue();
|
||||
int restoredPosition = PreferenceManager.getDefaultSharedPreferences(this).getInt(SAVED_POSITION, -1);
|
||||
int restoredPositionInTrack = PreferenceManager.getDefaultSharedPreferences(this).getInt(SAVED_POSITION_IN_TRACK, -1);
|
||||
|
||||
|
@ -587,20 +577,16 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
queuesRestored = true;
|
||||
}
|
||||
|
||||
private int quit() {
|
||||
public void quit() {
|
||||
pause();
|
||||
playingNotification.stop();
|
||||
|
||||
if (isServiceBound) {
|
||||
return START_STICKY;
|
||||
} else {
|
||||
closeAudioEffectSession();
|
||||
getAudioManager().abandonAudioFocus(audioFocusListener);
|
||||
stopSelf();
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
closeAudioEffectSession();
|
||||
getAudioManager().abandonAudioFocus(audioFocusListener);
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
|
||||
private void releaseResources() {
|
||||
playerHandler.removeCallbacksAndMessages(null);
|
||||
musicPlayerHandlerThread.quitSafely();
|
||||
|
@ -629,7 +615,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
playSongAt(getNextPosition(force));
|
||||
}
|
||||
|
||||
private boolean openTrackAndPrepareNextAt(int position) {
|
||||
public boolean openTrackAndPrepareNextAt(int position) {
|
||||
synchronized (this) {
|
||||
this.position = position;
|
||||
boolean prepared = openCurrent();
|
||||
|
@ -655,7 +641,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
playerHandler.obtainMessage(PREPARE_NEXT).sendToTarget();
|
||||
}
|
||||
|
||||
private boolean prepareNextImpl() {
|
||||
public boolean prepareNextImpl() {
|
||||
synchronized (this) {
|
||||
try {
|
||||
int nextPosition = getNextPosition(false);
|
||||
|
@ -694,13 +680,14 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
}
|
||||
}
|
||||
|
||||
private void updateMediaSessionPlaybackState() {
|
||||
mediaSession.setPlaybackState(
|
||||
new PlaybackStateCompat.Builder()
|
||||
.setActions(MEDIA_SESSION_ACTIONS)
|
||||
.setState(isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,
|
||||
getSongProgressMillis(), 1)
|
||||
.build());
|
||||
public void updateMediaSessionPlaybackState() {
|
||||
PlaybackStateCompat.Builder stateBuilder = new PlaybackStateCompat.Builder()
|
||||
.setActions(MEDIA_SESSION_ACTIONS)
|
||||
.setState(isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,
|
||||
getSongProgressMillis(), 1);
|
||||
|
||||
|
||||
mediaSession.setPlaybackState(stateBuilder.build());
|
||||
}
|
||||
|
||||
private void updateMediaSessionMetaData() {
|
||||
|
@ -801,7 +788,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
return position;
|
||||
}
|
||||
|
||||
private boolean isLastTrack() {
|
||||
public boolean isLastTrack() {
|
||||
return getPosition() == getPlayingQueue().size() - 1;
|
||||
}
|
||||
|
||||
|
@ -946,7 +933,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
playerHandler.obtainMessage(PLAY_SONG, position, 0).sendToTarget();
|
||||
}
|
||||
|
||||
private void playSongAtImpl(int position) {
|
||||
public void playSongAtImpl(int position) {
|
||||
if (openTrackAndPrepareNextAt(position)) {
|
||||
play();
|
||||
} else {
|
||||
|
@ -1128,18 +1115,18 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
notifyChange(QUEUE_CHANGED);
|
||||
}
|
||||
|
||||
private void notifyChange(@NonNull final String what) {
|
||||
public void notifyChange(@NonNull final String what) {
|
||||
handleAndSendChangeInternal(what);
|
||||
sendPublicIntent(what);
|
||||
}
|
||||
|
||||
private void handleAndSendChangeInternal(@NonNull final String what) {
|
||||
public void handleAndSendChangeInternal(@NonNull final String what) {
|
||||
handleChangeInternal(what);
|
||||
sendChangeInternal(what);
|
||||
}
|
||||
|
||||
// to let other apps know whats playing. i.E. last.fm (scrobbling) or musixmatch
|
||||
private void sendPublicIntent(@NonNull final String what) {
|
||||
public void sendPublicIntent(@NonNull final String what) {
|
||||
final Intent intent = new Intent(what.replace(RETRO_MUSIC_PACKAGE_NAME, MUSIC_PACKAGE_NAME));
|
||||
|
||||
final Song song = getCurrentSong();
|
||||
|
@ -1266,187 +1253,12 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
playerHandler.sendEmptyMessage(TRACK_ENDED);
|
||||
}
|
||||
|
||||
|
||||
private static final class QueueSaveHandler extends Handler {
|
||||
@NonNull
|
||||
private final WeakReference<MusicService> mService;
|
||||
|
||||
QueueSaveHandler(final MusicService service, @NonNull final Looper looper) {
|
||||
super(looper);
|
||||
mService = new WeakReference<>(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(@NonNull Message msg) {
|
||||
final MusicService service = mService.get();
|
||||
if (msg.what == SAVE_QUEUES) {
|
||||
service.saveQueuesImpl();
|
||||
}
|
||||
}
|
||||
public boolean isPausedByTransientLossOfFocus() {
|
||||
return pausedByTransientLossOfFocus;
|
||||
}
|
||||
|
||||
private static final class PlaybackHandler extends Handler {
|
||||
@NonNull
|
||||
private final WeakReference<MusicService> mService;
|
||||
private float currentDuckVolume = 1.0f;
|
||||
|
||||
PlaybackHandler(final MusicService service, @NonNull final Looper looper) {
|
||||
super(looper);
|
||||
mService = new WeakReference<>(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(@NonNull final Message msg) {
|
||||
final MusicService service = mService.get();
|
||||
if (service == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg.what) {
|
||||
case DUCK:
|
||||
if (PreferenceUtil.getInstance().audioDucking()) {
|
||||
currentDuckVolume -= .05f;
|
||||
if (currentDuckVolume > .2f) {
|
||||
sendEmptyMessageDelayed(DUCK, 10);
|
||||
} else {
|
||||
currentDuckVolume = .2f;
|
||||
}
|
||||
} else {
|
||||
currentDuckVolume = 1f;
|
||||
}
|
||||
service.playback.setVolume(currentDuckVolume);
|
||||
break;
|
||||
|
||||
case UNDUCK:
|
||||
if (PreferenceUtil.getInstance().audioDucking()) {
|
||||
currentDuckVolume += .03f;
|
||||
if (currentDuckVolume < 1f) {
|
||||
sendEmptyMessageDelayed(UNDUCK, 10);
|
||||
} else {
|
||||
currentDuckVolume = 1f;
|
||||
}
|
||||
} else {
|
||||
currentDuckVolume = 1f;
|
||||
}
|
||||
service.playback.setVolume(currentDuckVolume);
|
||||
break;
|
||||
|
||||
case TRACK_WENT_TO_NEXT:
|
||||
if (service.getRepeatMode() == REPEAT_MODE_NONE && service.isLastTrack()) {
|
||||
service.pause();
|
||||
service.seek(0);
|
||||
} else {
|
||||
service.position = service.nextPosition;
|
||||
service.prepareNextImpl();
|
||||
service.notifyChange(META_CHANGED);
|
||||
}
|
||||
break;
|
||||
|
||||
case TRACK_ENDED:
|
||||
// if there is a timer finished, don't continue
|
||||
if (service.pendingQuit ||
|
||||
service.getRepeatMode() == REPEAT_MODE_NONE && service.isLastTrack()) {
|
||||
service.notifyChange(PLAY_STATE_CHANGED);
|
||||
service.seek(0);
|
||||
if (service.pendingQuit) {
|
||||
service.pendingQuit = false;
|
||||
service.quit();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
service.playNextSong(false);
|
||||
}
|
||||
sendEmptyMessage(RELEASE_WAKELOCK);
|
||||
break;
|
||||
|
||||
case RELEASE_WAKELOCK:
|
||||
service.releaseWakeLock();
|
||||
break;
|
||||
|
||||
case PLAY_SONG:
|
||||
service.playSongAtImpl(msg.arg1);
|
||||
break;
|
||||
|
||||
case SET_POSITION:
|
||||
service.openTrackAndPrepareNextAt(msg.arg1);
|
||||
service.notifyChange(PLAY_STATE_CHANGED);
|
||||
break;
|
||||
|
||||
case PREPARE_NEXT:
|
||||
service.prepareNextImpl();
|
||||
break;
|
||||
|
||||
case RESTORE_QUEUES:
|
||||
service.restoreQueuesAndPositionIfNecessary();
|
||||
break;
|
||||
|
||||
case FOCUS_CHANGE:
|
||||
switch (msg.arg1) {
|
||||
case AudioManager.AUDIOFOCUS_GAIN:
|
||||
if (!service.isPlaying() && service.pausedByTransientLossOfFocus) {
|
||||
service.play();
|
||||
service.pausedByTransientLossOfFocus = false;
|
||||
}
|
||||
removeMessages(DUCK);
|
||||
sendEmptyMessage(UNDUCK);
|
||||
break;
|
||||
|
||||
case AudioManager.AUDIOFOCUS_LOSS:
|
||||
// Lost focus for an unbounded amount of time: stop playback and release media playback
|
||||
service.pause();
|
||||
break;
|
||||
|
||||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
|
||||
// Lost focus for a short time, but we have to stop
|
||||
// playback. We don't release the media playback because playback
|
||||
// is likely to resume
|
||||
boolean wasPlaying = service.isPlaying();
|
||||
service.pause();
|
||||
service.pausedByTransientLossOfFocus = wasPlaying;
|
||||
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
|
||||
removeMessages(UNDUCK);
|
||||
sendEmptyMessage(DUCK);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class SongPlayCountHelper {
|
||||
public static final String TAG = SongPlayCountHelper.class.getSimpleName();
|
||||
|
||||
private StopWatch stopWatch = new StopWatch();
|
||||
private Song song = Song.getEmptySong();
|
||||
|
||||
public Song getSong() {
|
||||
return song;
|
||||
}
|
||||
|
||||
boolean shouldBumpPlayCount() {
|
||||
return song.getDuration() * 0.5d < stopWatch.getElapsedTime();
|
||||
}
|
||||
|
||||
void notifySongChanged(Song song) {
|
||||
synchronized (this) {
|
||||
stopWatch.reset();
|
||||
this.song = song;
|
||||
}
|
||||
}
|
||||
|
||||
void notifyPlayStateChanged(boolean isPlaying) {
|
||||
synchronized (this) {
|
||||
if (isPlaying) {
|
||||
stopWatch.start();
|
||||
} else {
|
||||
stopWatch.pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
public void setPausedByTransientLossOfFocus(boolean pausedByTransientLossOfFocus) {
|
||||
this.pausedByTransientLossOfFocus = pausedByTransientLossOfFocus;
|
||||
}
|
||||
|
||||
public class MusicBinder extends Binder {
|
||||
|
@ -1455,52 +1267,4 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
|
|||
return MusicService.this;
|
||||
}
|
||||
}
|
||||
|
||||
private class MediaStoreObserver extends ContentObserver implements Runnable {
|
||||
// milliseconds to delay before calling refresh to aggregate events
|
||||
private static final long REFRESH_DELAY = 500;
|
||||
private Handler mHandler;
|
||||
|
||||
MediaStoreObserver(Handler handler) {
|
||||
super(handler);
|
||||
mHandler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
// if a change is detected, remove any scheduled callback
|
||||
// then post a new one. This is intended to prevent closely
|
||||
// spaced events from generating multiple refresh calls
|
||||
mHandler.removeCallbacks(this);
|
||||
mHandler.postDelayed(this, REFRESH_DELAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// actually call refresh when the delayed callback fires
|
||||
// do not send a sticky broadcast here
|
||||
handleAndSendChangeInternal(MEDIA_STORE_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
private class ThrottledSeekHandler implements Runnable {
|
||||
// milliseconds to throttle before calling run() to aggregate events
|
||||
private static final long THROTTLE = 500;
|
||||
private Handler mHandler;
|
||||
|
||||
ThrottledSeekHandler(Handler handler) {
|
||||
mHandler = handler;
|
||||
}
|
||||
|
||||
void notifySeek() {
|
||||
mHandler.removeCallbacks(this);
|
||||
mHandler.postDelayed(this, THROTTLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
savePositionInTrack();
|
||||
sendPublicIntent(PLAY_STATE_CHANGED); // for musixmatch synced lyrics
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Hemanth Savarala.
|
||||
*
|
||||
* Licensed under the GNU General Public License v3
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
package code.name.monkey.retromusic.service;
|
||||
|
||||
import android.media.AudioManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil;
|
||||
|
||||
import static code.name.monkey.retromusic.service.MusicService.DUCK;
|
||||
import static code.name.monkey.retromusic.service.MusicService.META_CHANGED;
|
||||
import static code.name.monkey.retromusic.service.MusicService.PLAY_STATE_CHANGED;
|
||||
import static code.name.monkey.retromusic.service.MusicService.REPEAT_MODE_NONE;
|
||||
import static code.name.monkey.retromusic.service.MusicService.TRACK_ENDED;
|
||||
import static code.name.monkey.retromusic.service.MusicService.TRACK_WENT_TO_NEXT;
|
||||
|
||||
class PlaybackHandler extends Handler {
|
||||
@NonNull
|
||||
private final WeakReference<MusicService> mService;
|
||||
private float currentDuckVolume = 1.0f;
|
||||
|
||||
PlaybackHandler(final MusicService service, @NonNull final Looper looper) {
|
||||
super(looper);
|
||||
mService = new WeakReference<>(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(@NonNull final Message msg) {
|
||||
final MusicService service = mService.get();
|
||||
if (service == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg.what) {
|
||||
case MusicService.DUCK:
|
||||
if (PreferenceUtil.getInstance().audioDucking()) {
|
||||
currentDuckVolume -= .05f;
|
||||
if (currentDuckVolume > .2f) {
|
||||
sendEmptyMessageDelayed(DUCK, 10);
|
||||
} else {
|
||||
currentDuckVolume = .2f;
|
||||
}
|
||||
} else {
|
||||
currentDuckVolume = 1f;
|
||||
}
|
||||
service.playback.setVolume(currentDuckVolume);
|
||||
break;
|
||||
|
||||
case MusicService.UNDUCK:
|
||||
if (PreferenceUtil.getInstance().audioDucking()) {
|
||||
currentDuckVolume += .03f;
|
||||
if (currentDuckVolume < 1f) {
|
||||
sendEmptyMessageDelayed(MusicService.UNDUCK, 10);
|
||||
} else {
|
||||
currentDuckVolume = 1f;
|
||||
}
|
||||
} else {
|
||||
currentDuckVolume = 1f;
|
||||
}
|
||||
service.playback.setVolume(currentDuckVolume);
|
||||
break;
|
||||
|
||||
case TRACK_WENT_TO_NEXT:
|
||||
if (service.getRepeatMode() == REPEAT_MODE_NONE && service.isLastTrack()) {
|
||||
service.pause();
|
||||
service.seek(0);
|
||||
} else {
|
||||
service.position = service.nextPosition;
|
||||
service.prepareNextImpl();
|
||||
service.notifyChange(META_CHANGED);
|
||||
}
|
||||
break;
|
||||
|
||||
case TRACK_ENDED:
|
||||
// if there is a timer finished, don't continue
|
||||
if (service.pendingQuit ||
|
||||
service.getRepeatMode() == REPEAT_MODE_NONE && service.isLastTrack()) {
|
||||
service.notifyChange(PLAY_STATE_CHANGED);
|
||||
service.seek(0);
|
||||
if (service.pendingQuit) {
|
||||
service.pendingQuit = false;
|
||||
service.quit();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
service.playNextSong(false);
|
||||
}
|
||||
sendEmptyMessage(MusicService.RELEASE_WAKELOCK);
|
||||
break;
|
||||
|
||||
case MusicService.RELEASE_WAKELOCK:
|
||||
service.releaseWakeLock();
|
||||
break;
|
||||
|
||||
case MusicService.PLAY_SONG:
|
||||
service.playSongAtImpl(msg.arg1);
|
||||
break;
|
||||
|
||||
case MusicService.SET_POSITION:
|
||||
service.openTrackAndPrepareNextAt(msg.arg1);
|
||||
service.notifyChange(PLAY_STATE_CHANGED);
|
||||
break;
|
||||
|
||||
case MusicService.PREPARE_NEXT:
|
||||
service.prepareNextImpl();
|
||||
break;
|
||||
|
||||
case MusicService.RESTORE_QUEUES:
|
||||
service.restoreQueuesAndPositionIfNecessary();
|
||||
break;
|
||||
|
||||
case MusicService.FOCUS_CHANGE:
|
||||
switch (msg.arg1) {
|
||||
case AudioManager.AUDIOFOCUS_GAIN:
|
||||
if (!service.isPlaying() && service.isPausedByTransientLossOfFocus()) {
|
||||
service.play();
|
||||
service.setPausedByTransientLossOfFocus(false);
|
||||
}
|
||||
removeMessages(DUCK);
|
||||
sendEmptyMessage(MusicService.UNDUCK);
|
||||
break;
|
||||
|
||||
case AudioManager.AUDIOFOCUS_LOSS:
|
||||
// Lost focus for an unbounded amount of time: stop playback and release media playback
|
||||
service.pause();
|
||||
break;
|
||||
|
||||
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
|
||||
// Lost focus for a short time, but we have to stop
|
||||
// playback. We don't release the media playback because playback
|
||||
// is likely to resume
|
||||
boolean wasPlaying = service.isPlaying();
|
||||
service.pause();
|
||||
service.setPausedByTransientLossOfFocus(wasPlaying);
|
||||
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
|
||||
removeMessages(MusicService.UNDUCK);
|
||||
sendEmptyMessage(DUCK);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Hemanth Savarala.
|
||||
*
|
||||
* Licensed under the GNU General Public License v3
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
package code.name.monkey.retromusic.service;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import static code.name.monkey.retromusic.service.MusicService.SAVE_QUEUES;
|
||||
|
||||
class QueueSaveHandler extends Handler {
|
||||
@NonNull
|
||||
private final WeakReference<MusicService> mService;
|
||||
|
||||
QueueSaveHandler(final MusicService service, @NonNull final Looper looper) {
|
||||
super(looper);
|
||||
mService = new WeakReference<>(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(@NonNull Message msg) {
|
||||
final MusicService service = mService.get();
|
||||
if (msg.what == SAVE_QUEUES) {
|
||||
service.saveQueuesImpl();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Hemanth Savarala.
|
||||
*
|
||||
* Licensed under the GNU General Public License v3
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
package code.name.monkey.retromusic.service;
|
||||
|
||||
import code.name.monkey.retromusic.helper.StopWatch;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
|
||||
public class SongPlayCountHelper {
|
||||
public static final String TAG = SongPlayCountHelper.class.getSimpleName();
|
||||
|
||||
private StopWatch stopWatch = new StopWatch();
|
||||
private Song song = Song.getEmptySong();
|
||||
|
||||
public Song getSong() {
|
||||
return song;
|
||||
}
|
||||
|
||||
boolean shouldBumpPlayCount() {
|
||||
return song.getDuration() * 0.5d < stopWatch.getElapsedTime();
|
||||
}
|
||||
|
||||
void notifySongChanged(Song song) {
|
||||
synchronized (this) {
|
||||
stopWatch.reset();
|
||||
this.song = song;
|
||||
}
|
||||
}
|
||||
|
||||
void notifyPlayStateChanged(boolean isPlaying) {
|
||||
synchronized (this) {
|
||||
if (isPlaying) {
|
||||
stopWatch.start();
|
||||
} else {
|
||||
stopWatch.pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2019 Hemanth Savarala.
|
||||
*
|
||||
* Licensed under the GNU General Public License v3
|
||||
*
|
||||
* This is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
package code.name.monkey.retromusic.service;
|
||||
|
||||
|
||||
import android.os.Handler;
|
||||
|
||||
import static code.name.monkey.retromusic.service.MusicService.PLAY_STATE_CHANGED;
|
||||
|
||||
public class ThrottledSeekHandler implements Runnable {
|
||||
// milliseconds to throttle before calling run() to aggregate events
|
||||
private static final long THROTTLE = 500;
|
||||
private final MusicService musicService;
|
||||
private Handler handler;
|
||||
|
||||
ThrottledSeekHandler(MusicService musicService, Handler handler) {
|
||||
this.musicService = musicService;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
void notifySeek() {
|
||||
handler.removeCallbacks(this);
|
||||
handler.postDelayed(this, THROTTLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
musicService.savePositionInTrack();
|
||||
musicService.sendPublicIntent(PLAY_STATE_CHANGED); // for musixmatch synced lyrics
|
||||
}
|
||||
}
|
|
@ -24,12 +24,13 @@ import android.os.AsyncTask;
|
|||
import android.os.Bundle;
|
||||
import android.service.media.MediaBrowserService;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
|
||||
import code.name.monkey.retromusic.loaders.AlbumLoader;
|
||||
|
@ -194,7 +195,7 @@ public class WearBrowserService extends MediaBrowserService {
|
|||
} else {
|
||||
switch (Integer.parseInt(Character.toString(parentId.charAt(0)))) {
|
||||
case TYPE_ARTIST:
|
||||
List<Artist> artistList = ArtistLoader.INSTANCE.getAllArtists(mContext).blockingFirst();
|
||||
List<Artist> artistList = ArtistLoader.INSTANCE.getAllArtists(mContext) ;
|
||||
for (Artist artist : artistList) {
|
||||
String albumNmber = String.format("%d %s", artist.getAlbums().size(), artist.getAlbums().size() > 1 ? "Albums" : "Album");
|
||||
String songCount = String.format("%d %s", artist.getSongs().size(), artist.getSongs().size() > 1 ? "Songs" : "Song");
|
||||
|
@ -215,7 +216,7 @@ public class WearBrowserService extends MediaBrowserService {
|
|||
Uri.parse("android.resource://code.name.monkey.retromusic/drawable/default_artist_art"),
|
||||
MediaBrowser.MediaItem.FLAG_BROWSABLE);
|
||||
|
||||
List<Album> artistAlbums = ArtistLoader.INSTANCE.getArtist(mContext, Integer.parseInt(parentId.substring(1))).blockingFirst().getAlbums(); //ArtistAlbumLoader.getAlbumsForArtist(mContext, Long.parseLong(parentId.substring(1)));
|
||||
List<Album> artistAlbums = ArtistLoader.INSTANCE.getArtist(mContext, Integer.parseInt(parentId.substring(1))).getAlbums(); //ArtistAlbumLoader.getAlbumsForArtist(mContext, Long.parseLong(parentId.substring(1)));
|
||||
for (Album album : artistAlbums) {
|
||||
String songCount = String.format("%d %s", album.getSongs().size(), album.getSongs().size() > 1 ? "Songs" : "Song");
|
||||
fillMediaItems(mediaItems,
|
||||
|
@ -227,7 +228,7 @@ public class WearBrowserService extends MediaBrowserService {
|
|||
}
|
||||
break;
|
||||
case TYPE_ALBUM:
|
||||
List<Album> albumList = AlbumLoader.Companion.getAllAlbums(mContext).blockingFirst();
|
||||
List<Album> albumList = AlbumLoader.INSTANCE.getAllAlbums(mContext);
|
||||
for (Album album : albumList) {
|
||||
fillMediaItems(mediaItems,
|
||||
Integer.toString(TYPE_ALBUM_SONGS) + Long.toString(album.getId()),
|
||||
|
@ -238,7 +239,7 @@ public class WearBrowserService extends MediaBrowserService {
|
|||
}
|
||||
break;
|
||||
case TYPE_SONG:
|
||||
List<Song> songList = SongLoader.INSTANCE.getAllSongs(mContext).blockingFirst();
|
||||
List<Song> songList = SongLoader.INSTANCE.getAllSongs(mContext);
|
||||
for (Song song : songList) {
|
||||
fillMediaItems(mediaItems,
|
||||
String.valueOf(song.getId()),
|
||||
|
@ -250,7 +251,7 @@ public class WearBrowserService extends MediaBrowserService {
|
|||
break;
|
||||
|
||||
case TYPE_ALBUM_SONGS:
|
||||
List<Song> albumSongList = AlbumLoader.Companion.getAlbum(mContext, Integer.parseInt(parentId.substring(1))).blockingFirst().getSongs();
|
||||
List<Song> albumSongList = AlbumLoader.INSTANCE.getAlbum(mContext, Integer.parseInt(parentId.substring(1))).getSongs();
|
||||
for (Song song : albumSongList) {
|
||||
fillMediaItems(mediaItems,
|
||||
String.valueOf(song.getId()),
|
||||
|
@ -261,7 +262,7 @@ public class WearBrowserService extends MediaBrowserService {
|
|||
}
|
||||
break;
|
||||
case TYPE_ARTIST_ALL_SONGS:
|
||||
List<Song> artistSongs = ArtistLoader.INSTANCE.getArtist(mContext, Integer.parseInt(parentId.substring(1))).blockingFirst().getSongs();
|
||||
List<Song> artistSongs = ArtistLoader.INSTANCE.getArtist(mContext, Integer.parseInt(parentId.substring(1))).getSongs();
|
||||
for (Song song : artistSongs) {
|
||||
fillMediaItems(mediaItems,
|
||||
String.valueOf(song.getId()),
|
||||
|
@ -272,9 +273,9 @@ public class WearBrowserService extends MediaBrowserService {
|
|||
}
|
||||
break;
|
||||
case TYPE_PLAYLIST:
|
||||
List<Playlist> playlistList = PlaylistLoader.INSTANCE.getAllPlaylists(mContext).blockingFirst();
|
||||
List<Playlist> playlistList = PlaylistLoader.INSTANCE.getAllPlaylists(mContext);
|
||||
for (Playlist playlist : playlistList) {
|
||||
int size = PlaylistSongsLoader.INSTANCE.getPlaylistSongList(mContext, playlist).blockingFirst().size();
|
||||
int size = PlaylistSongsLoader.INSTANCE.getPlaylistSongList(mContext, playlist).size();
|
||||
String songCount = String.format("%d %s", size, size > 1 ? "Songs" : "Song");
|
||||
fillMediaItems(mediaItems,
|
||||
Integer.toString(TYPE_PLAYLIST_ALL_SONGS) + Long.toString(playlist.id),
|
||||
|
@ -285,7 +286,7 @@ public class WearBrowserService extends MediaBrowserService {
|
|||
}
|
||||
break;
|
||||
case TYPE_PLAYLIST_ALL_SONGS:
|
||||
List<Song> playlistSongs = PlaylistSongsLoader.INSTANCE.getPlaylistSongList(mContext, Integer.parseInt(parentId.substring(1))).blockingFirst();
|
||||
List<Song> playlistSongs = PlaylistSongsLoader.INSTANCE.getPlaylistSongList(mContext, Integer.parseInt(parentId.substring(1)));
|
||||
for (Song song : playlistSongs) {
|
||||
fillMediaItems(mediaItems,
|
||||
String.valueOf(song.getId()),
|
||||
|
@ -326,7 +327,7 @@ public class WearBrowserService extends MediaBrowserService {
|
|||
long songId = Long.parseLong(mediaId);
|
||||
setSessionActive();
|
||||
ArrayList<Song> songs = new ArrayList<>();
|
||||
songs.add(SongLoader.INSTANCE.getSong(mContext, Integer.parseInt(mediaId)).blockingFirst());
|
||||
songs.add(SongLoader.INSTANCE.getSong(mContext, Integer.parseInt(mediaId)));
|
||||
MusicPlayerRemote.INSTANCE.openQueue(songs, 0, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,10 +28,6 @@ import android.widget.RemoteViews
|
|||
import androidx.core.app.NotificationCompat
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||
import code.name.monkey.retromusic.Constants.ACTION_QUIT
|
||||
import code.name.monkey.retromusic.Constants.ACTION_REWIND
|
||||
import code.name.monkey.retromusic.Constants.ACTION_SKIP
|
||||
import code.name.monkey.retromusic.Constants.ACTION_TOGGLE_PAUSE
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.activities.MainActivity
|
||||
import code.name.monkey.retromusic.appwidgets.base.BaseAppWidget.Companion.createBitmap
|
||||
|
@ -40,6 +36,7 @@ import code.name.monkey.retromusic.glide.RetroGlideExtension
|
|||
import code.name.monkey.retromusic.glide.RetroSimpleTarget
|
||||
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.service.MusicService.*
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.RetroColorUtil
|
||||
import code.name.monkey.retromusic.util.RetroUtil
|
||||
|
|
|
@ -24,17 +24,15 @@ import android.graphics.drawable.Drawable
|
|||
import android.os.Build
|
||||
import android.text.Html
|
||||
import androidx.core.app.NotificationCompat
|
||||
import code.name.monkey.retromusic.Constants.ACTION_QUIT
|
||||
import code.name.monkey.retromusic.Constants.ACTION_REWIND
|
||||
import code.name.monkey.retromusic.Constants.ACTION_SKIP
|
||||
import code.name.monkey.retromusic.Constants.ACTION_TOGGLE_PAUSE
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.activities.MainActivity
|
||||
import code.name.monkey.retromusic.glide.GlideApp
|
||||
import code.name.monkey.retromusic.glide.RetroGlideExtension
|
||||
import code.name.monkey.retromusic.glide.RetroSimpleTarget
|
||||
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.activities.MainActivity
|
||||
import code.name.monkey.retromusic.service.MusicService.*
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.RetroColorUtil
|
||||
import com.bumptech.glide.request.target.Target
|
||||
|
@ -48,12 +46,18 @@ class PlayingNotificationImpl24 : PlayingNotification() {
|
|||
|
||||
val song = service.currentSong
|
||||
val isPlaying = service.isPlaying
|
||||
|
||||
val isFavorite = MusicUtil.isFavorite(service, song)
|
||||
val playButtonResId = if (isPlaying)
|
||||
R.drawable.ic_pause_white_24dp
|
||||
else
|
||||
R.drawable.ic_play_arrow_white_32dp
|
||||
|
||||
val favoriteResId = if (isFavorite)
|
||||
R.drawable.ic_favorite_white_24dp
|
||||
else
|
||||
R.drawable.ic_favorite_border_white_24dp
|
||||
|
||||
|
||||
val action = Intent(service, MainActivity::class.java)
|
||||
action.putExtra("expand", true)
|
||||
action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
|
@ -93,6 +97,12 @@ class PlayingNotificationImpl24 : PlayingNotification() {
|
|||
if (bitmapFinal == null) {
|
||||
bitmapFinal = BitmapFactory.decodeResource(service.resources, R.drawable.default_album_art)
|
||||
}
|
||||
|
||||
|
||||
val toggleFavorite = NotificationCompat.Action(favoriteResId,
|
||||
service.getString(R.string.action_toggle_favorite),
|
||||
retrievePlaybackAction(TOGGLE_FAVORITE))
|
||||
|
||||
val playPauseAction = NotificationCompat.Action(
|
||||
playButtonResId,
|
||||
service.getString(R.string.action_play_pause),
|
||||
|
@ -114,7 +124,7 @@ class PlayingNotificationImpl24 : PlayingNotification() {
|
|||
retrievePlaybackAction(ACTION_SKIP))
|
||||
|
||||
val builder = NotificationCompat.Builder(service,
|
||||
PlayingNotification.NOTIFICATION_CHANNEL_ID)
|
||||
NOTIFICATION_CHANNEL_ID)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setLargeIcon(bitmapFinal)
|
||||
.setContentIntent(clickIntent)
|
||||
|
|
|
@ -25,10 +25,6 @@ import android.widget.RemoteViews
|
|||
import androidx.core.app.NotificationCompat
|
||||
import code.name.monkey.appthemehelper.util.ColorUtil
|
||||
import code.name.monkey.appthemehelper.util.MaterialValueHelper
|
||||
import code.name.monkey.retromusic.Constants.ACTION_QUIT
|
||||
import code.name.monkey.retromusic.Constants.ACTION_REWIND
|
||||
import code.name.monkey.retromusic.Constants.ACTION_SKIP
|
||||
import code.name.monkey.retromusic.Constants.ACTION_TOGGLE_PAUSE
|
||||
import code.name.monkey.retromusic.R
|
||||
import code.name.monkey.retromusic.activities.MainActivity
|
||||
import code.name.monkey.retromusic.glide.GlideApp
|
||||
|
@ -37,6 +33,7 @@ import code.name.monkey.retromusic.glide.RetroSimpleTarget
|
|||
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.service.MusicService.*
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import code.name.monkey.retromusic.util.RetroUtil
|
||||
import code.name.monkey.retromusic.util.RetroUtil.createBitmap
|
||||
|
@ -155,14 +152,14 @@ class PlayingNotificationOreo : PlayingNotification() {
|
|||
val primary = MaterialValueHelper.getPrimaryTextColor(service, dark)
|
||||
val secondary = MaterialValueHelper.getSecondaryTextColor(service, dark)
|
||||
|
||||
val close = createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_close_white_24dp, primary)!!, PlayingNotification.NOTIFICATION_CONTROLS_SIZE_MULTIPLIER)
|
||||
val prev = createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_previous_white_24dp, primary)!!, PlayingNotification.NOTIFICATION_CONTROLS_SIZE_MULTIPLIER)
|
||||
val next = createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_next_white_24dp, primary)!!, PlayingNotification.NOTIFICATION_CONTROLS_SIZE_MULTIPLIER)
|
||||
val close = createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_close_white_24dp, primary)!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER)
|
||||
val prev = createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_previous_white_24dp, primary)!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER)
|
||||
val next = createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_next_white_24dp, primary)!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER)
|
||||
val playPause = createBitmap(RetroUtil.getTintedVectorDrawable(service,
|
||||
if (isPlaying)
|
||||
R.drawable.ic_pause_white_24dp
|
||||
else
|
||||
R.drawable.ic_play_arrow_white_32dp, primary)!!, PlayingNotification.NOTIFICATION_CONTROLS_SIZE_MULTIPLIER)
|
||||
R.drawable.ic_play_arrow_white_32dp, primary)!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER)
|
||||
|
||||
notificationLayout.setTextColor(R.id.title, primary)
|
||||
notificationLayout.setTextColor(R.id.subtitle, secondary)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue