Finish current music when Sleep Timer stops (#629)

Implement #329.
This commit adds a CheckBox to dialog_sleep_timer, and a curresponding
option `TIMER_FINISH_MUSIC` in PreferenceUtil.

In MusicService, a new flag `pendingQuit` is to indicate if it should
stop after current music stops. A new action `ACTION_PENDING_QUIT` will
set that flag.

Canceling is a little tricky. I must bind MusicService in Dialog
activity to check if `pendingQuit` is set, and show the corresponding
canceling button.
This commit is contained in:
Peng Guanwen 2019-01-08 10:45:33 +08:00 committed by Eugene
commit 2111c41836
6 changed files with 94 additions and 25 deletions

View file

@ -11,6 +11,7 @@ import android.os.CountDownTimer;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.widget.CheckBox;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
@ -20,6 +21,7 @@ import com.afollestad.materialdialogs.MaterialDialog;
import com.afollestad.materialdialogs.internal.ThemeSingleton;
import com.kabouzeid.gramophone.App;
import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.service.MusicService;
import com.kabouzeid.gramophone.ui.activities.PurchaseActivity;
import com.kabouzeid.gramophone.util.MusicUtil;
@ -37,6 +39,8 @@ public class SleepTimerDialog extends DialogFragment {
SeekArc seekArc;
@BindView(R.id.timer_display)
TextView timerDisplay;
@BindView(R.id.should_finish_last_song)
CheckBox shouldFinishLastSong;
private int seekArcProgress;
private MaterialDialog materialDialog;
@ -65,6 +69,8 @@ public class SleepTimerDialog extends DialogFragment {
return;
}
PreferenceUtil.getInstance(getActivity()).setSleepTimerFinishMusic(shouldFinishLastSong.isChecked());
final int minutes = seekArcProgress;
PendingIntent pi = makeTimerPendingIntent(PendingIntent.FLAG_CANCEL_CURRENT);
@ -87,6 +93,12 @@ public class SleepTimerDialog extends DialogFragment {
previous.cancel();
Toast.makeText(getActivity(), getActivity().getResources().getString(R.string.sleep_timer_canceled), Toast.LENGTH_SHORT).show();
}
MusicService musicService = MusicPlayerRemote.musicService;
if (musicService != null && musicService.pendingQuit) {
musicService.pendingQuit = false;
Toast.makeText(getActivity(), getActivity().getResources().getString(R.string.sleep_timer_canceled), Toast.LENGTH_SHORT).show();
}
})
.showListener(dialog -> {
if (makeTimerPendingIntent(PendingIntent.FLAG_NO_CREATE) != null) {
@ -102,6 +114,9 @@ public class SleepTimerDialog extends DialogFragment {
ButterKnife.bind(this, materialDialog.getCustomView());
boolean finishMusic = PreferenceUtil.getInstance(getActivity()).getSleepTimerFinishMusic();
shouldFinishLastSong.setChecked(finishMusic);
seekArc.setProgressColor(ThemeSingleton.get().positiveColor.getDefaultColor());
seekArc.setThumbColor(ThemeSingleton.get().positiveColor.getDefaultColor());
@ -153,8 +168,20 @@ public class SleepTimerDialog extends DialogFragment {
}
private Intent makeTimerIntent() {
return new Intent(getActivity(), MusicService.class)
.setAction(MusicService.ACTION_QUIT);
Intent intent = new Intent(getActivity(), MusicService.class);
if (shouldFinishLastSong.isChecked()) {
return intent.setAction(MusicService.ACTION_PENDING_QUIT);
}
return intent.setAction(MusicService.ACTION_QUIT);
}
private void updateCancelButton() {
MusicService musicService = MusicPlayerRemote.musicService;
if (musicService != null && musicService.pendingQuit) {
materialDialog.setActionButton(DialogAction.NEUTRAL, materialDialog.getContext().getString(R.string.cancel_current_timer));
} else {
materialDialog.setActionButton(DialogAction.NEUTRAL, null);
}
}
private class TimerUpdater extends CountDownTimer {
@ -169,7 +196,7 @@ public class SleepTimerDialog extends DialogFragment {
@Override
public void onFinish() {
materialDialog.setActionButton(DialogAction.NEUTRAL, null);
updateCancelButton();
}
}
}
}

View file

@ -83,6 +83,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
public static final String ACTION_SKIP = PHONOGRAPH_PACKAGE_NAME + ".skip";
public static final String ACTION_REWIND = PHONOGRAPH_PACKAGE_NAME + ".rewind";
public static final String ACTION_QUIT = PHONOGRAPH_PACKAGE_NAME + ".quitservice";
public static final String ACTION_PENDING_QUIT = PHONOGRAPH_PACKAGE_NAME + ".pendingquitservice";
public static final String INTENT_EXTRA_PLAYLIST = PHONOGRAPH_PACKAGE_NAME + "intentextra.playlist";
public static final String INTENT_EXTRA_SHUFFLE_MODE = PHONOGRAPH_PACKAGE_NAME + ".intentextra.shufflemode";
@ -125,6 +126,8 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
private final IBinder musicBind = new MusicBinder();
public boolean pendingQuit = false;
private AppWidgetBig appWidgetBig = AppWidgetBig.getInstance();
private AppWidgetClassic appWidgetClassic = AppWidgetClassic.getInstance();
private AppWidgetSmall appWidgetSmall = AppWidgetSmall.getInstance();
@ -335,8 +338,12 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
break;
case ACTION_STOP:
case ACTION_QUIT:
pendingQuit = false;
quit();
break;
case ACTION_PENDING_QUIT:
pendingQuit = true;
break;
}
}
}
@ -1193,9 +1200,16 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP
break;
case TRACK_ENDED:
if (service.getRepeatMode() == REPEAT_MODE_NONE && service.isLastTrack()) {
// 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);
}

View file

@ -68,6 +68,7 @@ public final class PreferenceUtil {
public static final String LAST_SLEEP_TIMER_VALUE = "last_sleep_timer_value";
public static final String NEXT_SLEEP_TIMER_ELAPSED_REALTIME = "next_sleep_timer_elapsed_real_time";
public static final String SLEEP_TIMER_FINISH_SONG = "sleep_timer_finish_music";
public static final String IGNORE_MEDIA_STORE_ARTWORK = "ignore_media_store_artwork";
@ -363,6 +364,16 @@ public final class PreferenceUtil {
editor.apply();
}
public boolean getSleepTimerFinishMusic() {
return mPreferences.getBoolean(SLEEP_TIMER_FINISH_SONG, false);
}
public void setSleepTimerFinishMusic(final boolean value) {
final SharedPreferences.Editor editor = mPreferences.edit();
editor.putBoolean(SLEEP_TIMER_FINISH_SONG, value);
editor.apply();
}
public void setAlbumGridSize(final int gridSize) {
final SharedPreferences.Editor editor = mPreferences.edit();
editor.putInt(ALBUM_GRID_SIZE, gridSize);

View file

@ -1,28 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:seekarc="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:orientation="vertical">
<com.triggertrap.seekarc.SeekArc
android:id="@+id/seek_arc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="30dp"
seekarc:SeekArc_clockwise="false"
seekarc:SeekArc_max="120"
seekarc:SeekArc_progressColor="?colorAccent"
seekarc:SeekArc_rotation="180"
seekarc:SeekArc_startAngle="30"
seekarc:SeekArc_sweepAngle="300" />
<TextView
android:id="@+id/timer_display"
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textAppearance="?android:textAppearanceLarge" />
android:layout_height="wrap_content">
</FrameLayout>
<com.triggertrap.seekarc.SeekArc
android:id="@+id/seek_arc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="30dp"
seekarc:SeekArc_clockwise="false"
seekarc:SeekArc_max="120"
seekarc:SeekArc_progressColor="?colorAccent"
seekarc:SeekArc_rotation="180"
seekarc:SeekArc_startAngle="30"
seekarc:SeekArc_sweepAngle="300" />
<TextView
android:id="@+id/timer_display"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textAppearance="?android:textAppearanceLarge" />
</FrameLayout>
<com.kabouzeid.appthemehelper.common.views.ATECheckBox
android:id="@+id/should_finish_last_song"
android:layout_width="wrap_content"
android:layout_height="42dp"
android:layout_gravity="bottom"
android:layout_margin="20dp"
android:text="@string/finish_current_music_sleep_timer" />
</LinearLayout>

View file

@ -294,4 +294,5 @@
<string name="sort_order_artist">艺术家</string>
<string name="sort_order_album">专辑</string>
<string name="sort_order_year">年份</string>
<string name="finish_current_music_sleep_timer">播完当前音乐</string>
</resources>

View file

@ -312,4 +312,5 @@
<string name="sort_order_artist">Artist</string>
<string name="sort_order_album">Album</string>
<string name="sort_order_year">Year</string>
<string name="finish_current_music_sleep_timer">Finish last song</string>
</resources>