Code refactor and Flat, Fit, Full, Circle theme toolbar shadow fixes

This commit is contained in:
= 2020-02-26 22:19:24 +05:30
parent 954dfb6327
commit 724f743627
304 changed files with 3874 additions and 3524 deletions

View file

@ -87,7 +87,7 @@ class MediaButtonIntentReceiver : BroadcastReceiver() {
val intentAction = intent.action
if (Intent.ACTION_MEDIA_BUTTON == intentAction) {
val event = intent.getParcelableExtra<KeyEvent>(Intent.EXTRA_KEY_EVENT)
?: return false
?: return false
val keycode = event.keyCode
val action = event.action
@ -99,7 +99,8 @@ class MediaButtonIntentReceiver : BroadcastReceiver() {
var command: String? = null
when (keycode) {
KeyEvent.KEYCODE_MEDIA_STOP -> command = ACTION_STOP
KeyEvent.KEYCODE_HEADSETHOOK, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> command = ACTION_TOGGLE_PAUSE
KeyEvent.KEYCODE_HEADSETHOOK, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> command =
ACTION_TOGGLE_PAUSE
KeyEvent.KEYCODE_MEDIA_NEXT -> command = ACTION_SKIP
KeyEvent.KEYCODE_MEDIA_PREVIOUS -> command = ACTION_REWIND
KeyEvent.KEYCODE_MEDIA_PAUSE -> command = ACTION_PAUSE
@ -125,7 +126,8 @@ class MediaButtonIntentReceiver : BroadcastReceiver() {
mHandler.removeMessages(MSG_HEADSET_DOUBLE_CLICK_TIMEOUT)
val msg = mHandler.obtainMessage(
MSG_HEADSET_DOUBLE_CLICK_TIMEOUT, mClickCounter, 0, context)
MSG_HEADSET_DOUBLE_CLICK_TIMEOUT, mClickCounter, 0, context
)
val delay = (if (mClickCounter < 3) DOUBLE_CLICK else 0).toLong()
if (mClickCounter >= 3) {
@ -164,7 +166,10 @@ class MediaButtonIntentReceiver : BroadcastReceiver() {
if (wakeLock == null) {
val appContext = context.applicationContext
val pm = appContext.getSystemService(Context.POWER_SERVICE) as PowerManager
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "RetroMusicApp:Wakelock headset button")
wakeLock = pm.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK,
"RetroMusicApp:Wakelock headset button"
)
wakeLock!!.setReferenceCounted(false)
}
if (DEBUG) Log.v(TAG, "Acquiring wake lock and sending " + msg.what)

View file

@ -30,8 +30,9 @@ import java.util.*
* Created by hemanths on 2019-08-01.
*/
class MediaSessionCallback(private val context: Context,
private val musicService: MusicService
class MediaSessionCallback(
private val context: Context,
private val musicService: MusicService
) : MediaSessionCompat.Callback() {
override fun onPlay() {

View file

@ -18,8 +18,8 @@ import android.database.ContentObserver
import android.os.Handler
class MediaStoreObserver(
private val musicService: MusicService,
private val mHandler: Handler
private val musicService: MusicService,
private val mHandler: Handler
) : ContentObserver(mHandler), Runnable {
override fun onChange(selfChange: Boolean) {

View file

@ -21,11 +21,12 @@ import android.media.MediaPlayer;
import android.media.audiofx.AudioEffect;
import android.net.Uri;
import android.os.PowerManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.service.playback.Playback;
import code.name.monkey.retromusic.util.PreferenceUtil;

View file

@ -47,9 +47,21 @@ import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.PreferenceManager;
import com.bumptech.glide.BitmapRequestBuilder;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SimpleTarget;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.appwidgets.AppWidgetBig;
import code.name.monkey.retromusic.appwidgets.AppWidgetCard;
@ -71,14 +83,6 @@ import code.name.monkey.retromusic.service.playback.Playback;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.PreferenceUtil;
import code.name.monkey.retromusic.util.RetroUtil;
import com.bumptech.glide.BitmapRequestBuilder;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SimpleTarget;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Random;
/**
* @author Karim Abou Zeid (kabouzeid), Andrew Neal
@ -86,107 +90,53 @@ import java.util.Random;
public class MusicService extends Service implements
SharedPreferences.OnSharedPreferenceChangeListener, Playback.PlaybackCallbacks {
public class MusicBinder extends Binder {
@NonNull
public MusicService getService() {
return MusicService.this;
}
}
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 long MEDIA_SESSION_ACTIONS = PlaybackStateCompat.ACTION_PLAY
| PlaybackStateCompat.ACTION_PAUSE
| PlaybackStateCompat.ACTION_PLAY_PAUSE
@ -194,7 +144,7 @@ public class MusicService extends Service implements
| PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
| PlaybackStateCompat.ACTION_STOP
| PlaybackStateCompat.ACTION_SEEK_TO;
private final IBinder musicBind = new MusicBinder();
public int nextPosition = -1;
public boolean pendingQuit = false;
@ -213,144 +163,6 @@ public class MusicService extends Service implements
private AppWidgetSmall appWidgetSmall = AppWidgetSmall.Companion.getInstance();
private AppWidgetText appWidgetText = AppWidgetText.Companion.getInstance();
private AudioManager audioManager;
private IntentFilter becomingNoisyReceiverIntentFilter = new IntentFilter(
AudioManager.ACTION_AUDIO_BECOMING_NOISY);
private boolean becomingNoisyReceiverRegistered;
private IntentFilter bluetoothConnectedIntentFilter = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);
private boolean bluetoothConnectedRegistered = false;
private IntentFilter headsetReceiverIntentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
private boolean headsetReceiverRegistered = false;
private MediaSessionCompat mediaSession;
private ContentObserver mediaStoreObserver;
private final IBinder musicBind = new MusicBinder();
private HandlerThread musicPlayerHandlerThread;
private boolean notHandledMetaChangedForCurrentTrack;
private ArrayList<Song> originalPlayingQueue = new ArrayList<>();
private boolean pausedByTransientLossOfFocus;
private final BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, @NonNull Intent intent) {
if (intent.getAction() != null && intent.getAction().equals(AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
pause();
}
}
};
private PlaybackHandler playerHandler;
private final AudioManager.OnAudioFocusChangeListener audioFocusListener
= new AudioManager.OnAudioFocusChangeListener() {
@Override
public void onAudioFocusChange(final int focusChange) {
playerHandler.obtainMessage(FOCUS_CHANGE, focusChange, 0).sendToTarget();
}
};
private PlayingNotification playingNotification;
private ArrayList<Song> playingQueue = new ArrayList<>();
private QueueSaveHandler queueSaveHandler;
private HandlerThread queueSaveHandlerThread;
private boolean queuesRestored;
private int repeatMode;
private int shuffleMode;
private SongPlayCountHelper songPlayCountHelper = new SongPlayCountHelper();
private final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
String action = intent.getAction();
if (action != null) {
if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action) &&
PreferenceUtil.getInstance(context).bluetoothSpeaker()) {
if (VERSION.SDK_INT >= VERSION_CODES.M) {
if (getAudioManager().getDevices(AudioManager.GET_DEVICES_OUTPUTS).length > 0) {
play();
}
} else {
if (getAudioManager().isBluetoothA2dpOn()) {
play();
}
}
}
}
}
};
private PhoneStateListener phoneStateListener = new PhoneStateListener() {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
//Not in call: Play music
play();
break;
case TelephonyManager.CALL_STATE_RINGING:
case TelephonyManager.CALL_STATE_OFFHOOK:
//A call is dialing, active or on hold
pause();
break;
default:
}
super.onCallStateChanged(state, incomingNumber);
}
};
private BroadcastReceiver headsetReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action != null) {
if (Intent.ACTION_HEADSET_PLUG.equals(action)) {
int state = intent.getIntExtra("state", -1);
switch (state) {
case 0:
pause();
break;
case 1:
play();
break;
}
}
}
}
};
private ThrottledSeekHandler throttledSeekHandler;
private Handler uiThreadHandler;
private final BroadcastReceiver updateFavoriteReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
updateNotification();
}
};
private PowerManager.WakeLock wakeLock;
private final BroadcastReceiver widgetIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
@ -383,6 +195,134 @@ public class MusicService extends Service implements
}
};
private AudioManager audioManager;
private IntentFilter becomingNoisyReceiverIntentFilter = new IntentFilter(
AudioManager.ACTION_AUDIO_BECOMING_NOISY);
private boolean becomingNoisyReceiverRegistered;
private IntentFilter bluetoothConnectedIntentFilter = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);
private boolean bluetoothConnectedRegistered = false;
private IntentFilter headsetReceiverIntentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
private boolean headsetReceiverRegistered = false;
private MediaSessionCompat mediaSession;
private ContentObserver mediaStoreObserver;
private HandlerThread musicPlayerHandlerThread;
private boolean notHandledMetaChangedForCurrentTrack;
private ArrayList<Song> originalPlayingQueue = new ArrayList<>();
private boolean pausedByTransientLossOfFocus;
private final BroadcastReceiver becomingNoisyReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, @NonNull Intent intent) {
if (intent.getAction() != null && intent.getAction().equals(AudioManager.ACTION_AUDIO_BECOMING_NOISY)) {
pause();
}
}
};
private PlaybackHandler playerHandler;
private final AudioManager.OnAudioFocusChangeListener audioFocusListener
= new AudioManager.OnAudioFocusChangeListener() {
@Override
public void onAudioFocusChange(final int focusChange) {
playerHandler.obtainMessage(FOCUS_CHANGE, focusChange, 0).sendToTarget();
}
};
private PlayingNotification playingNotification;
private final BroadcastReceiver updateFavoriteReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
updateNotification();
}
};
private ArrayList<Song> playingQueue = new ArrayList<>();
private QueueSaveHandler queueSaveHandler;
private HandlerThread queueSaveHandlerThread;
private boolean queuesRestored;
private int repeatMode;
private int shuffleMode;
private SongPlayCountHelper songPlayCountHelper = new SongPlayCountHelper();
private final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
String action = intent.getAction();
if (action != null) {
if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action) &&
PreferenceUtil.getInstance(context).bluetoothSpeaker()) {
if (VERSION.SDK_INT >= VERSION_CODES.M) {
if (getAudioManager().getDevices(AudioManager.GET_DEVICES_OUTPUTS).length > 0) {
play();
}
} else {
if (getAudioManager().isBluetoothA2dpOn()) {
play();
}
}
}
}
}
};
private PhoneStateListener phoneStateListener = new PhoneStateListener() {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
//Not in call: Play music
play();
break;
case TelephonyManager.CALL_STATE_RINGING:
case TelephonyManager.CALL_STATE_OFFHOOK:
//A call is dialing, active or on hold
pause();
break;
default:
}
super.onCallStateChanged(state, incomingNumber);
}
};
private BroadcastReceiver headsetReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action != null) {
if (Intent.ACTION_HEADSET_PLUG.equals(action)) {
int state = intent.getIntExtra("state", -1);
switch (state) {
case 0:
pause();
break;
case 1:
play();
break;
}
}
}
}
};
private ThrottledSeekHandler throttledSeekHandler;
private Handler uiThreadHandler;
private PowerManager.WakeLock wakeLock;
private static Bitmap copy(Bitmap bitmap) {
Bitmap.Config config = bitmap.getConfig();
if (config == null) {
config = Bitmap.Config.RGB_565;
}
try {
return bitmap.copy(config, false);
} catch (OutOfMemoryError e) {
e.printStackTrace();
return null;
}
}
private static String getTrackUri(@NonNull Song song) {
return MusicUtil.getSongFileUri(song.getId()).toString();
}
@Override
public void onCreate() {
@ -876,7 +816,7 @@ public class MusicService extends Service implements
}
public void openQueue(@Nullable final List<Song> playingQueue, final int startPosition,
final boolean startPlaying) {
final boolean startPlaying) {
if (playingQueue != null && !playingQueue.isEmpty() && startPosition >= 0 && startPosition < playingQueue
.size()) {
// it is important to copy the playing queue here first as we might add/remove songs later
@ -1424,20 +1364,11 @@ public class MusicService extends Service implements
}
private static Bitmap copy(Bitmap bitmap) {
Bitmap.Config config = bitmap.getConfig();
if (config == null) {
config = Bitmap.Config.RGB_565;
}
try {
return bitmap.copy(config, false);
} catch (OutOfMemoryError e) {
e.printStackTrace();
return null;
}
}
public class MusicBinder extends Binder {
private static String getTrackUri(@NonNull Song song) {
return MusicUtil.getSongFileUri(song.getId()).toString();
@NonNull
public MusicService getService() {
return MusicService.this;
}
}
}

View file

@ -14,6 +14,17 @@
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;
@ -21,20 +32,11 @@ 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;
import android.media.AudioManager;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import androidx.annotation.NonNull;
import code.name.monkey.retromusic.util.PreferenceUtil;
import java.lang.ref.WeakReference;
class PlaybackHandler extends Handler {
private float currentDuckVolume = 1.0f;
@NonNull
private final WeakReference<MusicService> mService;
private float currentDuckVolume = 1.0f;
PlaybackHandler(final MusicService service, @NonNull final Looper looper) {
super(looper);

View file

@ -21,8 +21,8 @@ import code.name.monkey.retromusic.service.MusicService.SAVE_QUEUES
import java.lang.ref.WeakReference
internal class QueueSaveHandler(
musicService: MusicService,
looper: Looper
musicService: MusicService,
looper: Looper
) : Handler(looper) {
private val service: WeakReference<MusicService> = WeakReference(musicService)

View file

@ -20,8 +20,8 @@ import android.os.Handler
import code.name.monkey.retromusic.service.MusicService.PLAY_STATE_CHANGED
class ThrottledSeekHandler(
private val musicService: MusicService,
private val handler: Handler
private val musicService: MusicService,
private val handler: Handler
) : Runnable {
fun notifySeek() {

View file

@ -73,12 +73,15 @@ abstract class PlayingNotification {
@RequiresApi(26)
private fun createNotificationChannel() {
var notificationChannel: NotificationChannel? = notificationManager!!
.getNotificationChannel(NOTIFICATION_CHANNEL_ID)
.getNotificationChannel(NOTIFICATION_CHANNEL_ID)
if (notificationChannel == null) {
notificationChannel = NotificationChannel(NOTIFICATION_CHANNEL_ID,
service.getString(R.string.playing_notification_name),
NotificationManager.IMPORTANCE_LOW)
notificationChannel.description = service.getString(R.string.playing_notification_description)
notificationChannel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
service.getString(R.string.playing_notification_name),
NotificationManager.IMPORTANCE_LOW
)
notificationChannel.description =
service.getString(R.string.playing_notification_description)
notificationChannel.enableLights(false)
notificationChannel.enableVibration(false)
notificationChannel.setShowBadge(false)

View file

@ -48,13 +48,16 @@ class PlayingNotificationImpl : PlayingNotification() {
val song = service.currentSong
val isPlaying = service.isPlaying
val isFavorite = MusicUtil.isFavorite(service, song)
val playButtonResId = if (isPlaying) R.drawable.ic_pause_white_48dp else R.drawable.ic_play_arrow_white_48dp
val favoriteResId = if (isFavorite) R.drawable.ic_favorite_white_24dp else R.drawable.ic_favorite_border_white_24dp
val playButtonResId =
if (isPlaying) R.drawable.ic_pause_white_48dp else R.drawable.ic_play_arrow_white_48dp
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
val clickIntent = PendingIntent.getActivity(service, 0, action, PendingIntent.FLAG_UPDATE_CURRENT)
val clickIntent =
PendingIntent.getActivity(service, 0, action, PendingIntent.FLAG_UPDATE_CURRENT)
val serviceName = ComponentName(service, MusicService::class.java)
val intent = Intent(ACTION_QUIT)
@ -62,71 +65,108 @@ class PlayingNotificationImpl : PlayingNotification() {
val deleteIntent = PendingIntent.getService(service, 0, intent, 0)
val bigNotificationImageSize = service.resources
.getDimensionPixelSize(R.dimen.notification_big_image_size)
.getDimensionPixelSize(R.dimen.notification_big_image_size)
service.runOnUiThread {
if (target != null) {
Glide.clear(target)
}
target = SongGlideRequest.Builder.from(Glide.with(service), song)
.checkIgnoreMediaStore(service)
.generatePalette(service).build()
.centerCrop()
.into(object : SimpleTarget<BitmapPaletteWrapper>(bigNotificationImageSize, bigNotificationImageSize) {
override fun onResourceReady(resource: BitmapPaletteWrapper, glideAnimation: GlideAnimation<in BitmapPaletteWrapper>) {
update(resource.bitmap, when {
PreferenceUtil.getInstance(service).isDominantColor -> RetroColorUtil.getDominantColor(resource.bitmap, Color.TRANSPARENT)
.checkIgnoreMediaStore(service)
.generatePalette(service).build()
.centerCrop()
.into(object : SimpleTarget<BitmapPaletteWrapper>(
bigNotificationImageSize,
bigNotificationImageSize
) {
override fun onResourceReady(
resource: BitmapPaletteWrapper,
glideAnimation: GlideAnimation<in BitmapPaletteWrapper>
) {
update(
resource.bitmap, when {
PreferenceUtil.getInstance(service).isDominantColor -> RetroColorUtil.getDominantColor(
resource.bitmap,
Color.TRANSPARENT
)
else -> RetroColorUtil.getColor(resource.palette, Color.TRANSPARENT)
})
}
)
}
override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
super.onLoadFailed(e, errorDrawable)
update(null, Color.TRANSPARENT)
}
fun update(bitmap: Bitmap?, color: Int) {
var bitmapFinal = bitmap
if (bitmapFinal == null) {
bitmapFinal = BitmapFactory.decodeResource(
service.resources,
R.drawable.default_audio_art
)
}
override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
super.onLoadFailed(e, errorDrawable)
update(null, Color.TRANSPARENT)
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),
retrievePlaybackAction(ACTION_TOGGLE_PAUSE)
)
val previousAction = NotificationCompat.Action(
R.drawable.ic_skip_previous_round_white_32dp,
service.getString(R.string.action_previous),
retrievePlaybackAction(ACTION_REWIND)
)
val nextAction = NotificationCompat.Action(
R.drawable.ic_skip_next_round_white_32dp,
service.getString(R.string.action_next),
retrievePlaybackAction(ACTION_SKIP)
)
val builder = NotificationCompat.Builder(
service,
NOTIFICATION_CHANNEL_ID
)
.setSmallIcon(R.drawable.ic_notification)
.setLargeIcon(bitmapFinal)
.setContentIntent(clickIntent)
.setDeleteIntent(deleteIntent)
.setContentTitle(Html.fromHtml("<b>" + song.title + "</b>"))
.setContentText(song.artistName)
.setSubText(Html.fromHtml("<b>" + song.albumName + "</b>"))
.setOngoing(isPlaying)
.setShowWhen(false)
.addAction(toggleFavorite)
.addAction(previousAction)
.addAction(playPauseAction)
.addAction(nextAction)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder.setStyle(
MediaStyle()
.setMediaSession(service.mediaSession.sessionToken)
.setShowActionsInCompactView(1, 2, 3)
)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O && PreferenceUtil.getInstance(
service
).coloredNotification()
) {
builder.color = color
}
}
fun update(bitmap: Bitmap?, color: Int) {
var bitmapFinal = bitmap
if (bitmapFinal == null) {
bitmapFinal = BitmapFactory.decodeResource(service.resources, R.drawable.default_audio_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), retrievePlaybackAction(ACTION_TOGGLE_PAUSE))
val previousAction = NotificationCompat.Action(R.drawable.ic_skip_previous_round_white_32dp, service.getString(R.string.action_previous), retrievePlaybackAction(ACTION_REWIND))
val nextAction = NotificationCompat.Action(R.drawable.ic_skip_next_round_white_32dp, service.getString(R.string.action_next), retrievePlaybackAction(ACTION_SKIP))
val builder = NotificationCompat.Builder(service,
NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setLargeIcon(bitmapFinal)
.setContentIntent(clickIntent)
.setDeleteIntent(deleteIntent)
.setContentTitle(Html.fromHtml("<b>" + song.title + "</b>"))
.setContentText(song.artistName)
.setSubText(Html.fromHtml("<b>" + song.albumName + "</b>"))
.setOngoing(isPlaying)
.setShowWhen(false)
.addAction(toggleFavorite)
.addAction(previousAction)
.addAction(playPauseAction)
.addAction(nextAction)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder.setStyle(MediaStyle()
.setMediaSession(service.mediaSession.sessionToken)
.setShowActionsInCompactView(1, 2, 3))
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O && PreferenceUtil.getInstance(service).coloredNotification()) {
builder.color = color
}
}
if (stopped) {
return // notification has been stopped before loading was finished
}
updateNotifyModeAndPostNotification(builder.build())
if (stopped) {
return // notification has been stopped before loading was finished
}
})
updateNotifyModeAndPostNotification(builder.build())
}
})
}
}

View file

@ -50,8 +50,14 @@ class PlayingNotificationOreo : PlayingNotification() {
private var target: Target<BitmapPaletteWrapper>? = null
private fun getCombinedRemoteViews(collapsed: Boolean, song: Song): RemoteViews {
val remoteViews = RemoteViews(service.packageName, if (collapsed) R.layout.layout_notification_collapsed else R.layout.layout_notification_expanded)
remoteViews.setTextViewText(R.id.appName, service.getString(R.string.app_name) + "" + song.albumName)
val remoteViews = RemoteViews(
service.packageName,
if (collapsed) R.layout.layout_notification_collapsed else R.layout.layout_notification_expanded
)
remoteViews.setTextViewText(
R.id.appName,
service.getString(R.string.app_name) + "" + song.albumName
)
remoteViews.setTextViewText(R.id.title, song.title)
remoteViews.setTextViewText(R.id.subtitle, song.artistName)
linkButtons(remoteViews)
@ -71,103 +77,162 @@ class PlayingNotificationOreo : PlayingNotification() {
action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
val clickIntent = PendingIntent
.getActivity(service, 0, action, PendingIntent.FLAG_UPDATE_CURRENT)
.getActivity(service, 0, action, PendingIntent.FLAG_UPDATE_CURRENT)
val deleteIntent = buildPendingIntent(service, ACTION_QUIT, null)
val builder = NotificationCompat.Builder(service, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setContentIntent(clickIntent)
.setDeleteIntent(deleteIntent)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setCustomContentView(notificationLayout)
.setCustomBigContentView(notificationLayoutBig)
.setOngoing(isPlaying)
.setSmallIcon(R.drawable.ic_notification)
.setContentIntent(clickIntent)
.setDeleteIntent(deleteIntent)
.setCategory(NotificationCompat.CATEGORY_SERVICE)
.setPriority(NotificationCompat.PRIORITY_MAX)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setCustomContentView(notificationLayout)
.setCustomBigContentView(notificationLayoutBig)
.setOngoing(isPlaying)
val bigNotificationImageSize = service.resources
.getDimensionPixelSize(R.dimen.notification_big_image_size)
.getDimensionPixelSize(R.dimen.notification_big_image_size)
service.runOnUiThread {
if (target != null) {
Glide.clear(target)
}
target = SongGlideRequest.Builder.from(Glide.with(service), song)
.checkIgnoreMediaStore(service)
.generatePalette(service).build()
.centerCrop()
.into(object : SimpleTarget<BitmapPaletteWrapper>(bigNotificationImageSize, bigNotificationImageSize) {
override fun onResourceReady(resource: BitmapPaletteWrapper, glideAnimation: GlideAnimation<in BitmapPaletteWrapper>) {
val mediaNotificationProcessor = MediaNotificationProcessor(service, service) { i, _ -> update(resource.bitmap, i) }
mediaNotificationProcessor.processNotification(resource.bitmap)
.checkIgnoreMediaStore(service)
.generatePalette(service).build()
.centerCrop()
.into(object : SimpleTarget<BitmapPaletteWrapper>(
bigNotificationImageSize,
bigNotificationImageSize
) {
override fun onResourceReady(
resource: BitmapPaletteWrapper,
glideAnimation: GlideAnimation<in BitmapPaletteWrapper>
) {
val mediaNotificationProcessor = MediaNotificationProcessor(
service,
service
) { i, _ -> update(resource.bitmap, i) }
mediaNotificationProcessor.processNotification(resource.bitmap)
}
override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
super.onLoadFailed(e, errorDrawable)
update(
null,
ATHUtil.resolveColor(service, R.attr.colorSurface, Color.WHITE)
)
}
private fun update(bitmap: Bitmap?, bgColor: Int) {
var bgColorFinal = bgColor
if (bitmap != null) {
notificationLayout.setImageViewBitmap(R.id.largeIcon, bitmap)
notificationLayoutBig.setImageViewBitmap(R.id.largeIcon, bitmap)
} else {
notificationLayout.setImageViewResource(
R.id.largeIcon,
R.drawable.default_audio_art
)
notificationLayoutBig.setImageViewResource(
R.id.largeIcon,
R.drawable.default_audio_art
)
}
override fun onLoadFailed(e: Exception?, errorDrawable: Drawable?) {
super.onLoadFailed(e, errorDrawable)
update(null, ATHUtil.resolveColor(service, R.attr.colorSurface, Color.WHITE))
if (!PreferenceUtil.getInstance(service).coloredNotification()) {
bgColorFinal =
ATHUtil.resolveColor(service, R.attr.colorPrimary, Color.WHITE)
}
setBackgroundColor(bgColorFinal)
setNotificationContent(ColorUtil.isColorLight(bgColorFinal))
private fun update(bitmap: Bitmap?, bgColor: Int) {
var bgColorFinal = bgColor
if (bitmap != null) {
notificationLayout.setImageViewBitmap(R.id.largeIcon, bitmap)
notificationLayoutBig.setImageViewBitmap(R.id.largeIcon, bitmap)
} else {
notificationLayout.setImageViewResource(R.id.largeIcon, R.drawable.default_audio_art)
notificationLayoutBig.setImageViewResource(R.id.largeIcon, R.drawable.default_audio_art)
}
if (!PreferenceUtil.getInstance(service).coloredNotification()) {
bgColorFinal = ATHUtil.resolveColor(service, R.attr.colorPrimary, Color.WHITE)
}
setBackgroundColor(bgColorFinal)
setNotificationContent(ColorUtil.isColorLight(bgColorFinal))
if (stopped) {
return // notification has been stopped before loading was finished
}
updateNotifyModeAndPostNotification(builder.build())
if (stopped) {
return // notification has been stopped before loading was finished
}
updateNotifyModeAndPostNotification(builder.build())
}
private fun setBackgroundColor(color: Int) {
notificationLayout.setInt(R.id.image, "setBackgroundColor", color)
notificationLayoutBig.setInt(R.id.image, "setBackgroundColor", color)
}
private fun setBackgroundColor(color: Int) {
notificationLayout.setInt(R.id.image, "setBackgroundColor", color)
notificationLayoutBig.setInt(R.id.image, "setBackgroundColor", color)
}
private fun setNotificationContent(dark: Boolean) {
val primary = MaterialValueHelper.getPrimaryTextColor(service, dark)
val secondary = MaterialValueHelper.getSecondaryTextColor(service, dark)
private fun setNotificationContent(dark: Boolean) {
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)!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER)
val prev = createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_previous_round_white_32dp, primary)!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER)
val next = createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_next_round_white_32dp, primary)!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER)
val playPause = createBitmap(RetroUtil.getTintedVectorDrawable(service,
if (isPlaying)
R.drawable.ic_pause_white_48dp
else
R.drawable.ic_play_arrow_white_48dp, primary)!!, 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_round_white_32dp,
primary
)!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER
)
val next = createBitmap(
RetroUtil.getTintedVectorDrawable(
service,
R.drawable.ic_skip_next_round_white_32dp,
primary
)!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER
)
val playPause = createBitmap(
RetroUtil.getTintedVectorDrawable(
service,
if (isPlaying)
R.drawable.ic_pause_white_48dp
else
R.drawable.ic_play_arrow_white_48dp, primary
)!!, NOTIFICATION_CONTROLS_SIZE_MULTIPLIER
)
notificationLayout.setTextColor(R.id.title, primary)
notificationLayout.setTextColor(R.id.subtitle, secondary)
notificationLayout.setTextColor(R.id.appName, secondary)
notificationLayout.setTextColor(R.id.title, primary)
notificationLayout.setTextColor(R.id.subtitle, secondary)
notificationLayout.setTextColor(R.id.appName, secondary)
notificationLayout.setImageViewBitmap(R.id.action_prev, prev)
notificationLayout.setImageViewBitmap(R.id.action_next, next)
notificationLayout.setImageViewBitmap(R.id.action_play_pause, playPause)
notificationLayout.setImageViewBitmap(R.id.action_prev, prev)
notificationLayout.setImageViewBitmap(R.id.action_next, next)
notificationLayout.setImageViewBitmap(R.id.action_play_pause, playPause)
notificationLayoutBig.setTextColor(R.id.title, primary)
notificationLayoutBig.setTextColor(R.id.subtitle, secondary)
notificationLayoutBig.setTextColor(R.id.appName, secondary)
notificationLayoutBig.setTextColor(R.id.title, primary)
notificationLayoutBig.setTextColor(R.id.subtitle, secondary)
notificationLayoutBig.setTextColor(R.id.appName, secondary)
notificationLayoutBig.setImageViewBitmap(R.id.action_quit, close)
notificationLayoutBig.setImageViewBitmap(R.id.action_prev, prev)
notificationLayoutBig.setImageViewBitmap(R.id.action_next, next)
notificationLayoutBig.setImageViewBitmap(R.id.action_play_pause, playPause)
notificationLayoutBig.setImageViewBitmap(R.id.action_quit, close)
notificationLayoutBig.setImageViewBitmap(R.id.action_prev, prev)
notificationLayoutBig.setImageViewBitmap(R.id.action_next, next)
notificationLayoutBig.setImageViewBitmap(R.id.action_play_pause, playPause)
notificationLayout.setImageViewBitmap(R.id.smallIcon, createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_notification, secondary)!!, 0.6f))
notificationLayoutBig.setImageViewBitmap(R.id.smallIcon, createBitmap(RetroUtil.getTintedVectorDrawable(service, R.drawable.ic_notification, secondary)!!, 0.6f))
notificationLayout.setImageViewBitmap(
R.id.smallIcon,
createBitmap(
RetroUtil.getTintedVectorDrawable(
service,
R.drawable.ic_notification,
secondary
)!!, 0.6f
)
)
notificationLayoutBig.setImageViewBitmap(
R.id.smallIcon,
createBitmap(
RetroUtil.getTintedVectorDrawable(
service,
R.drawable.ic_notification,
secondary
)!!, 0.6f
)
)
}
})
}
})
}
if (stopped) {
@ -177,8 +242,10 @@ class PlayingNotificationOreo : PlayingNotification() {
}
private fun buildPendingIntent(context: Context, action: String,
serviceName: ComponentName?): PendingIntent {
private fun buildPendingIntent(
context: Context, action: String,
serviceName: ComponentName?
): PendingIntent {
val intent = Intent(action)
intent.component = serviceName
return PendingIntent.getService(context, 0, intent, 0)