diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b91807b9d..50942be0c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -122,6 +122,11 @@ android:name=".appshortcuts.AppShortcutLauncherActivity" android:launchMode="singleInstance" android:theme="@android:style/Theme.Translucent.NoTitleBar" /> + { if (getActivity() == null) { return; } - final PendingIntent previous = makeTimerPendingIntent(PendingIntent.FLAG_NO_CREATE); + final PendingIntent previous = SleepTimerUtil.getCurrentTimer(getActivity()); if (previous != null) { AlarmManager am = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE); am.cancel(previous); previous.cancel(); + getActivity().sendBroadcast(new Intent(MusicService.SLEEP_TIMER_CHANGED)); Toast.makeText(getActivity(), getActivity().getResources().getString(R.string.sleep_timer_canceled), Toast.LENGTH_SHORT).show(); } @@ -101,7 +106,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { } }) .showListener(dialog -> { - if (makeTimerPendingIntent(PendingIntent.FLAG_NO_CREATE) != null) { + if (SleepTimerUtil.isTimerRunning(getActivity())) { timerUpdater.start(); } }) @@ -199,4 +204,8 @@ public void onFinish() { updateCancelButton(); } } + + public interface DismissListener { + void onDismissed(); + } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java b/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java index e860f0862..cbbfccc86 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java +++ b/app/src/main/java/com/kabouzeid/gramophone/service/MusicService.java @@ -98,6 +98,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP public static final String REPEAT_MODE_CHANGED = PHONOGRAPH_PACKAGE_NAME + ".repeatmodechanged"; public static final String SHUFFLE_MODE_CHANGED = PHONOGRAPH_PACKAGE_NAME + ".shufflemodechanged"; public static final String MEDIA_STORE_CHANGED = PHONOGRAPH_PACKAGE_NAME + ".mediastorechanged"; + public static final String SLEEP_TIMER_CHANGED = PHONOGRAPH_PACKAGE_NAME + ".sleeptimerchanged"; public static final String SAVED_POSITION = "POSITION"; public static final String SAVED_POSITION_IN_TRACK = "POSITION_IN_TRACK"; @@ -169,6 +170,14 @@ public void onReceive(Context context, @NonNull Intent intent) { } } }; + + private final BroadcastReceiver sleepTimerReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, @NonNull Intent intent) { + updateNotification(); + } + }; + private ContentObserver mediaStoreObserver; private boolean notHandledMetaChangedForCurrentTrack; @@ -203,6 +212,7 @@ public void onCreate() { uiThreadHandler = new Handler(); registerReceiver(widgetIntentReceiver, new IntentFilter(APP_WIDGET_UPDATE)); + registerReceiver(sleepTimerReceiver, new IntentFilter(SLEEP_TIMER_CHANGED)); initNotification(); @@ -354,6 +364,7 @@ public int onStartCommand(@Nullable Intent intent, int flags, int startId) { @Override public void onDestroy() { unregisterReceiver(widgetIntentReceiver); + unregisterReceiver(sleepTimerReceiver); if (becomingNoisyReceiverRegistered) { unregisterReceiver(becomingNoisyReceiver); becomingNoisyReceiverRegistered = false; diff --git a/app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotification.java b/app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotification.java index b17e91ba8..bb9664cb9 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotification.java +++ b/app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotification.java @@ -3,11 +3,16 @@ import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Intent; import android.os.Build; import android.support.annotation.RequiresApi; import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.service.MusicService; +import com.kabouzeid.gramophone.ui.activities.MainActivity; +import com.kabouzeid.gramophone.ui.activities.SleepTimerActivity; +import com.kabouzeid.gramophone.util.SleepTimerUtil; import static android.content.Context.NOTIFICATION_SERVICE; @@ -41,6 +46,24 @@ public synchronized void stop() { notificationManager.cancel(NOTIFICATION_ID); } + PendingIntent clickAction() { + Intent intent = new Intent(service, MainActivity.class).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); + return PendingIntent.getActivity(service, 0, intent, 0); + } + + PendingIntent playbackAction(final String action) { + Intent intent = new Intent(service, MusicService.class).setAction(action); + return PendingIntent.getService(service, 0, intent, 0); + } + + PendingIntent deleteAction() { + return PendingIntent.getService(service, 0, SleepTimerUtil.getTimerAction(service), 0); + } + + PendingIntent sleepTimerAction() { + return PendingIntent.getActivity(service, 0, new Intent(service, SleepTimerActivity.class), 0); + } + void updateNotifyModeAndPostNotification(Notification notification) { int newNotifyMode; if (service.isPlaying()) { diff --git a/app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotificationImpl.java b/app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotificationImpl.java index 17065d5fc..08bea9144 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotificationImpl.java +++ b/app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotificationImpl.java @@ -2,12 +2,11 @@ import android.app.Notification; import android.app.PendingIntent; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.drawable.Drawable; +import android.os.CountDownTimer; +import android.os.SystemClock; import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; import android.text.TextUtils; @@ -29,11 +28,17 @@ import com.kabouzeid.gramophone.util.ImageUtil; import com.kabouzeid.gramophone.util.PhonographColorUtil; import com.kabouzeid.gramophone.util.PreferenceUtil; +import com.kabouzeid.gramophone.util.SleepTimerUtil; + +import java.util.concurrent.TimeUnit; public class PlayingNotificationImpl extends PlayingNotification { private Target target; + private CountDownTimer countdown; + private long timerStopTime; + @Override public synchronized void update() { stopped = false; @@ -45,6 +50,38 @@ public synchronized void update() { final RemoteViews notificationLayout = new RemoteViews(service.getPackageName(), R.layout.notification); final RemoteViews notificationLayoutBig = new RemoteViews(service.getPackageName(), R.layout.notification_big); + if (SleepTimerUtil.isTimerRunning(service)) { + long stopTime = PreferenceUtil.getInstance(service).getNextSleepTimerElapsedRealTime(); + + if (countdown != null && stopTime != timerStopTime) { + countdown.cancel(); + countdown = null; + } + + if (countdown == null) { + timerStopTime = stopTime; + countdown = new CountDownTimer(timerStopTime - SystemClock.elapsedRealtime(), 60 * 1000) { + @Override + public void onTick(long millisUntilFinished) { + update(); + } + + @Override + public void onFinish() { + countdown = null; + } + }; + countdown.start(); + } + + notificationLayoutBig.setViewVisibility(R.id.sleep_timer, View.VISIBLE); + } else if (countdown != null) { + countdown.cancel(); + countdown = null; + + notificationLayoutBig.setViewVisibility(R.id.sleep_timer, View.GONE); + } + if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName)) { notificationLayout.setViewVisibility(R.id.media_titles, View.INVISIBLE); } else { @@ -64,15 +101,10 @@ public synchronized void update() { linkButtons(notificationLayout, notificationLayoutBig); - Intent action = new Intent(service, MainActivity.class); - action.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); - final PendingIntent clickIntent = PendingIntent.getActivity(service, 0, action, 0); - final PendingIntent deleteIntent = buildPendingIntent(service, MusicService.ACTION_QUIT, null); - final Notification notification = new NotificationCompat.Builder(service, NOTIFICATION_CHANNEL_ID) .setSmallIcon(R.drawable.ic_notification) - .setContentIntent(clickIntent) - .setDeleteIntent(deleteIntent) + .setContentIntent(clickAction()) + .setDeleteIntent(deleteAction()) .setCategory(NotificationCompat.CATEGORY_SERVICE) .setPriority(NotificationCompat.PRIORITY_MAX) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) @@ -135,6 +167,7 @@ private void setNotificationContent(boolean dark) { Bitmap prev = ImageUtil.createBitmap(ImageUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_previous_white_24dp, primary), 1.5f); Bitmap next = ImageUtil.createBitmap(ImageUtil.getTintedVectorDrawable(service, R.drawable.ic_skip_next_white_24dp, primary), 1.5f); Bitmap playPause = ImageUtil.createBitmap(ImageUtil.getTintedVectorDrawable(service, isPlaying ? R.drawable.ic_pause_white_24dp : R.drawable.ic_play_arrow_white_24dp, primary), 1.5f); + Bitmap sleepTimer = ImageUtil.createBitmap(ImageUtil.getTintedVectorDrawable(service, R.drawable.ic_timer_white_24dp, primary), 1.5f); notificationLayout.setTextColor(R.id.title, primary); notificationLayout.setTextColor(R.id.text, secondary); @@ -145,9 +178,21 @@ private void setNotificationContent(boolean dark) { notificationLayoutBig.setTextColor(R.id.title, primary); notificationLayoutBig.setTextColor(R.id.text, secondary); notificationLayoutBig.setTextColor(R.id.text2, secondary); + notificationLayoutBig.setTextColor(R.id.sleep_timer, primary); 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_sleep_timer, sleepTimer); + + if (SleepTimerUtil.isTimerRunning(service)) { + long millis = PreferenceUtil.getInstance(service).getNextSleepTimerElapsedRealTime() - SystemClock.elapsedRealtime(); + long minutes = TimeUnit.MINUTES.convert(millis, TimeUnit.MILLISECONDS) + 1; + String text = String.format("%d min left", minutes) ; + notificationLayoutBig.setTextViewText(R.id.sleep_timer, text); + notificationLayoutBig.setViewVisibility(R.id.sleep_timer,View.VISIBLE); + } else { + notificationLayoutBig.setViewVisibility(R.id.sleep_timer, View.GONE); + } } }); } @@ -155,30 +200,21 @@ private void setNotificationContent(boolean dark) { } private void linkButtons(final RemoteViews notificationLayout, final RemoteViews notificationLayoutBig) { - PendingIntent pendingIntent; - - final ComponentName serviceName = new ComponentName(service, MusicService.class); + PendingIntent previous = playbackAction(MusicService.ACTION_REWIND); + notificationLayout.setOnClickPendingIntent(R.id.action_prev, previous); + notificationLayoutBig.setOnClickPendingIntent(R.id.action_prev, previous); - // Previous track - pendingIntent = buildPendingIntent(service, MusicService.ACTION_REWIND, serviceName); - notificationLayout.setOnClickPendingIntent(R.id.action_prev, pendingIntent); - notificationLayoutBig.setOnClickPendingIntent(R.id.action_prev, pendingIntent); + PendingIntent playPause = playbackAction(MusicService.ACTION_TOGGLE_PAUSE); + notificationLayout.setOnClickPendingIntent(R.id.action_play_pause, playPause); + notificationLayoutBig.setOnClickPendingIntent(R.id.action_play_pause, playPause); - // Play and pause - pendingIntent = buildPendingIntent(service, MusicService.ACTION_TOGGLE_PAUSE, serviceName); - notificationLayout.setOnClickPendingIntent(R.id.action_play_pause, pendingIntent); - notificationLayoutBig.setOnClickPendingIntent(R.id.action_play_pause, pendingIntent); - - // Next track - pendingIntent = buildPendingIntent(service, MusicService.ACTION_SKIP, serviceName); - notificationLayout.setOnClickPendingIntent(R.id.action_next, pendingIntent); - notificationLayoutBig.setOnClickPendingIntent(R.id.action_next, pendingIntent); - } + PendingIntent next = playbackAction(MusicService.ACTION_SKIP); + notificationLayout.setOnClickPendingIntent(R.id.action_next, next); + notificationLayoutBig.setOnClickPendingIntent(R.id.action_next, next); - private PendingIntent buildPendingIntent(Context context, final String action, final ComponentName serviceName) { - Intent intent = new Intent(action); - intent.setComponent(serviceName); - return PendingIntent.getService(context, 0, intent, 0); + PendingIntent sleepTimer = sleepTimerAction(); + notificationLayout.setOnClickPendingIntent(R.id.action_sleep_timer, sleepTimer); + notificationLayoutBig.setOnClickPendingIntent(R.id.action_sleep_timer, sleepTimer); } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotificationImpl24.java b/app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotificationImpl24.java index bd0ee315f..903b6043b 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotificationImpl24.java +++ b/app/src/main/java/com/kabouzeid/gramophone/service/notification/PlayingNotificationImpl24.java @@ -1,15 +1,15 @@ package com.kabouzeid.gramophone.service.notification; +import android.app.Notification; import android.app.PendingIntent; -import android.content.ComponentName; -import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.os.Build; -import android.support.v4.app.NotificationCompat; -import android.support.v4.media.app.NotificationCompat.MediaStyle; +import android.os.SystemClock; +import android.support.annotation.NonNull; +import android.support.annotation.RequiresApi; import android.support.v7.graphics.Palette; import com.bumptech.glide.Glide; @@ -23,11 +23,13 @@ import com.kabouzeid.gramophone.ui.activities.MainActivity; import com.kabouzeid.gramophone.util.MusicUtil; import com.kabouzeid.gramophone.util.PreferenceUtil; +import com.kabouzeid.gramophone.util.SleepTimerUtil; import static com.kabouzeid.gramophone.service.MusicService.ACTION_REWIND; import static com.kabouzeid.gramophone.service.MusicService.ACTION_SKIP; import static com.kabouzeid.gramophone.service.MusicService.ACTION_TOGGLE_PAUSE; +@RequiresApi(24) public class PlayingNotificationImpl24 extends PlayingNotification { @Override @@ -42,14 +44,9 @@ public synchronized void update() { final int playButtonResId = isPlaying ? R.drawable.ic_pause_white_24dp : R.drawable.ic_play_arrow_white_24dp; - Intent action = new Intent(service, MainActivity.class); - action.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); - final PendingIntent clickIntent = PendingIntent.getActivity(service, 0, action, 0); - - final ComponentName serviceName = new ComponentName(service, MusicService.class); - Intent intent = new Intent(MusicService.ACTION_QUIT); - intent.setComponent(serviceName); - final PendingIntent deleteIntent = PendingIntent.getService(service, 0, intent, 0); + final PendingIntent clickIntent = clickAction(); + final PendingIntent deleteIntent = deleteAction(); + PendingIntent sleepTimerIntent = sleepTimerAction(); final int bigNotificationImageSize = service.getResources().getDimensionPixelSize(R.dimen.notification_big_image_size); service.runOnUiThread(() -> SongGlideRequest.Builder.from(Glide.with(service), song) @@ -70,16 +67,21 @@ public void onLoadFailed(Exception e, Drawable errorDrawable) { void update(Bitmap bitmap, int color) { if (bitmap == null) bitmap = BitmapFactory.decodeResource(service.getResources(), R.drawable.default_album_art); - NotificationCompat.Action playPauseAction = new NotificationCompat.Action(playButtonResId, + long time = PreferenceUtil.getInstance(service).getNextSleepTimerElapsedRealTime(); + boolean sleepTimer = SleepTimerUtil.isTimerRunning(service); + Notification.Action playPauseAction = new Notification.Action(playButtonResId, service.getString(R.string.action_play_pause), - retrievePlaybackAction(ACTION_TOGGLE_PAUSE)); - NotificationCompat.Action previousAction = new NotificationCompat.Action(R.drawable.ic_skip_previous_white_24dp, + playbackAction(ACTION_TOGGLE_PAUSE)); + Notification.Action previousAction = new Notification.Action(R.drawable.ic_skip_previous_white_24dp, service.getString(R.string.action_previous), - retrievePlaybackAction(ACTION_REWIND)); - NotificationCompat.Action nextAction = new NotificationCompat.Action(R.drawable.ic_skip_next_white_24dp, + playbackAction(ACTION_REWIND)); + Notification.Action nextAction = new Notification.Action(R.drawable.ic_skip_next_white_24dp, service.getString(R.string.action_next), - retrievePlaybackAction(ACTION_SKIP)); - NotificationCompat.Builder builder = new NotificationCompat.Builder(service, NOTIFICATION_CHANNEL_ID) + playbackAction(ACTION_SKIP)); + Notification.Action sleepTimerAction = new Notification.Action(R.drawable.ic_timer_white_24dp, + service.getString(R.string.action_sleep_timer), + sleepTimerIntent); + Notification.Builder builder = builder() .setSmallIcon(R.drawable.ic_notification) .setLargeIcon(bitmap) .setContentIntent(clickIntent) @@ -87,16 +89,18 @@ void update(Bitmap bitmap, int color) { .setContentTitle(song.title) .setContentText(text) .setOngoing(isPlaying) - .setShowWhen(false) + .setShowWhen(sleepTimer) + .setUsesChronometer(true) + .setChronometerCountDown(true) + .setWhen(sleepTimer ? System.currentTimeMillis() + (time - SystemClock.elapsedRealtime()) : 0) .addAction(previousAction) .addAction(playPauseAction) - .addAction(nextAction); + .addAction(nextAction) + .addAction(sleepTimerAction) + .setStyle(new Notification.MediaStyle().setMediaSession((android.media.session.MediaSession.Token)service.getMediaSession().getSessionToken().getToken()).setShowActionsInCompactView(0, 1, 2)); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - builder.setStyle(new MediaStyle().setMediaSession(service.getMediaSession().getSessionToken()).setShowActionsInCompactView(0, 1, 2)) - .setVisibility(NotificationCompat.VISIBILITY_PUBLIC); - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O && PreferenceUtil.getInstance(service).coloredNotification()) - builder.setColor(color); + if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.O && PreferenceUtil.getInstance(service).coloredNotification()) { + builder.setColor(color); } if (stopped) @@ -106,10 +110,11 @@ void update(Bitmap bitmap, int color) { })); } - private PendingIntent retrievePlaybackAction(final String action) { - final ComponentName serviceName = new ComponentName(service, MusicService.class); - Intent intent = new Intent(action); - intent.setComponent(serviceName); - return PendingIntent.getService(service, 0, intent, 0); + @NonNull + private Notification.Builder builder() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + return new Notification.Builder(service, NOTIFICATION_CHANNEL_ID); + } + return new Notification.Builder(service); } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SleepTimerActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SleepTimerActivity.java new file mode 100644 index 000000000..4e952cd62 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SleepTimerActivity.java @@ -0,0 +1,45 @@ +package com.kabouzeid.gramophone.ui.activities; + +import android.os.Bundle; + +import android.support.annotation.Nullable; + +import com.afollestad.materialdialogs.Theme; +import com.kabouzeid.appthemehelper.ATHActivity; +import com.kabouzeid.gramophone.R; +import com.kabouzeid.gramophone.dialogs.SleepTimerDialog; +import com.kabouzeid.gramophone.util.PreferenceUtil; + + +public class SleepTimerActivity extends ATHActivity implements SleepTimerDialog.DismissListener { + + @Override + public void onDismissed() { + finish(); + } + + @Override + protected int getThemeRes() { + // the SleepTimerDialog theme is chosen by the primary text color of the context. We + // therefore have to match the overall theme + return (getDialogTheme() == Theme.LIGHT) + ? R.style.Activity_Light_Dialog + : R.style.Activity_Dark_Dialog; + } + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + new SleepTimerDialog().show(getSupportFragmentManager(), "fragment_dialog"); + } + + private Theme getDialogTheme() { + switch (PreferenceUtil.getInstance(this).getTheme()) { + case "dark": + case "black": + return Theme.DARK; + default: + return Theme.LIGHT; + } + } +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java b/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java index 6eecd2f55..7a57083e1 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java +++ b/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java @@ -127,7 +127,11 @@ public void unregisterOnSharedPreferenceChangedListener(SharedPreferences.OnShar @StyleRes public int getGeneralTheme() { - return getThemeResFromPrefValue(mPreferences.getString(GENERAL_THEME, "light")); + return getThemeResFromPrefValue(getTheme()); + } + + public String getTheme() { + return mPreferences.getString(GENERAL_THEME, "light"); } public void setGeneralTheme(String theme) { diff --git a/app/src/main/java/com/kabouzeid/gramophone/util/SleepTimerUtil.java b/app/src/main/java/com/kabouzeid/gramophone/util/SleepTimerUtil.java new file mode 100644 index 000000000..458b6c7c0 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/util/SleepTimerUtil.java @@ -0,0 +1,46 @@ +package com.kabouzeid.gramophone.util; + +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.os.SystemClock; + +import com.kabouzeid.gramophone.service.MusicService; + + +public class SleepTimerUtil { + + public static PendingIntent createTimer(Context context) { + return makeTimerIntent(context, PendingIntent.FLAG_CANCEL_CURRENT); + } + + public static Intent getTimerAction(Context context) { + return new Intent(context, MusicService.class).setAction(MusicService.ACTION_QUIT); + } + + /** + * Returns the current sleep timer, if any. + * @param context the context. + * @return the current timer. Returns {@code null} if the sleep timer is not running. + */ + public static PendingIntent getCurrentTimer(Context context) { + return makeTimerIntent(context, PendingIntent.FLAG_NO_CREATE); + } + + public static boolean isTimerRunning(Context context) { + PendingIntent running = getCurrentTimer(context); + + if (running != null) { + // AlarmManager does not seem to cancel intents after the alarm went off. We must + // therefore check if it expired to determine whether the sleep timer is actually + // running + return PreferenceUtil.getInstance(context).getNextSleepTimerElapsedRealTime() - SystemClock.elapsedRealtime() > 0; + } + + return false; + } + + private static PendingIntent makeTimerIntent(Context context, int flag) { + return PendingIntent.getService(context, 110110110, getTimerAction(context), flag); + } +} diff --git a/app/src/main/res/layout/notification_big.xml b/app/src/main/res/layout/notification_big.xml index 50428d2f3..5d8f8aebb 100644 --- a/app/src/main/res/layout/notification_big.xml +++ b/app/src/main/res/layout/notification_big.xml @@ -14,7 +14,7 @@ ~ limitations under the License --> - + - - @@ -66,17 +54,37 @@ android:singleLine="true" android:textAppearance="@style/Theme.Phonograph.Notification.Title" /> - + android:layout_gravity="fill" + android:columnCount="2" + android:rowCount="1"> + + + + + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 8cb384a3c..c2624b749 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -37,4 +37,13 @@ toolbar + + +