From b94e94a63660cf6741157d06d9070a3dec170d4f Mon Sep 17 00:00:00 2001 From: h4h13 Date: Thu, 16 May 2019 00:15:42 +0530 Subject: [PATCH] Added last song play in sleep timer --- .../code/name/monkey/retromusic/Constants.kt | 2 + .../dialogs/BlacklistFolderChooserDialog.kt | 7 +- .../retromusic/dialogs/SleepTimerDialog.kt | 188 ++++++++++++++---- .../retromusic/helper/MusicPlayerRemote.kt | 2 +- .../retromusic/service/MusicService.java | 32 ++- .../retromusic/util/PreferenceUtil.java | 12 ++ .../main/res/layout/dialog_sleep_timer.xml | 88 +++----- app/src/main/res/layout/fragment_folder.xml | 3 + app/src/main/res/layout/fragment_library.xml | 1 + app/src/main/res/values/strings.xml | 1 + 10 files changed, 217 insertions(+), 119 deletions(-) diff --git a/app/src/main/java/code/name/monkey/retromusic/Constants.kt b/app/src/main/java/code/name/monkey/retromusic/Constants.kt index b805c349..e4781b1c 100644 --- a/app/src/main/java/code/name/monkey/retromusic/Constants.kt +++ b/app/src/main/java/code/name/monkey/retromusic/Constants.kt @@ -43,6 +43,8 @@ object Constants { @JvmField val ACTION_QUIT = "$RETRO_MUSIC_PACKAGE_NAME.quitservice" @JvmField + val ACTION_PENDING_QUIT = "$RETRO_MUSIC_PACKAGE_NAME.pendingquitservice" + @JvmField val INTENT_EXTRA_PLAYLIST = RETRO_MUSIC_PACKAGE_NAME + "intentextra.playlist" @JvmField val INTENT_EXTRA_SHUFFLE_MODE = "$RETRO_MUSIC_PACKAGE_NAME.intentextra.shufflemode" diff --git a/app/src/main/java/code/name/monkey/retromusic/dialogs/BlacklistFolderChooserDialog.kt b/app/src/main/java/code/name/monkey/retromusic/dialogs/BlacklistFolderChooserDialog.kt index e5525a6b..29264b45 100644 --- a/app/src/main/java/code/name/monkey/retromusic/dialogs/BlacklistFolderChooserDialog.kt +++ b/app/src/main/java/code/name/monkey/retromusic/dialogs/BlacklistFolderChooserDialog.kt @@ -24,6 +24,7 @@ import androidx.core.app.ActivityCompat import androidx.fragment.app.DialogFragment import code.name.monkey.retromusic.R import com.afollestad.materialdialogs.MaterialDialog +import com.afollestad.materialdialogs.bottomsheets.BottomSheet import com.afollestad.materialdialogs.list.listItems import java.io.File import java.util.* @@ -95,9 +96,9 @@ class BlacklistFolderChooserDialog : DialogFragment() { checkIfCanGoUp() parentContents = listFiles() - return MaterialDialog(activity!!).show { + return MaterialDialog(activity!!, BottomSheet()).show { title(text = parentFolder!!.absolutePath) - listItems(items = contentsArray(), waitForPositiveButton = false) { dialog, index, text -> + listItems(items = contentsArray(), waitForPositiveButton = false) { _, index, _ -> onSelection(index) } noAutoDismiss() @@ -138,7 +139,7 @@ class BlacklistFolderChooserDialog : DialogFragment() { dialog?.apply { setTitle(parentFolder!!.absolutePath) - listItems(items = contentsArray()) { dialog, index, text -> + listItems(items = contentsArray()) { _, index, _ -> onSelection(index) } } diff --git a/app/src/main/java/code/name/monkey/retromusic/dialogs/SleepTimerDialog.kt b/app/src/main/java/code/name/monkey/retromusic/dialogs/SleepTimerDialog.kt index 641e3ac1..d46e16bb 100755 --- a/app/src/main/java/code/name/monkey/retromusic/dialogs/SleepTimerDialog.kt +++ b/app/src/main/java/code/name/monkey/retromusic/dialogs/SleepTimerDialog.kt @@ -15,6 +15,7 @@ package code.name.monkey.retromusic.dialogs import android.app.AlarmManager +import android.app.Dialog import android.app.PendingIntent import android.content.Context import android.content.DialogInterface @@ -22,50 +23,172 @@ import android.content.Intent import android.os.Bundle import android.os.CountDownTimer import android.os.SystemClock -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup +import android.widget.CheckBox import android.widget.SeekBar +import android.widget.TextView import android.widget.Toast -import androidx.core.content.ContextCompat +import androidx.fragment.app.DialogFragment import code.name.monkey.appthemehelper.ThemeStore -import code.name.monkey.appthemehelper.util.MaterialUtil -import code.name.monkey.retromusic.Constants.ACTION_QUIT +import code.name.monkey.retromusic.Constants import code.name.monkey.retromusic.R +import code.name.monkey.retromusic.helper.MusicPlayerRemote 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.ViewUtil -import code.name.monkey.retromusic.views.RoundedBottomSheetDialogFragment -import kotlinx.android.synthetic.main.dialog_sleep_timer.* -import java.util.* +import com.afollestad.materialdialogs.MaterialDialog +import com.afollestad.materialdialogs.WhichButton +import com.afollestad.materialdialogs.actions.getActionButton +import com.afollestad.materialdialogs.bottomsheets.BottomSheet +import com.afollestad.materialdialogs.callbacks.onShow +import com.afollestad.materialdialogs.customview.customView +import com.afollestad.materialdialogs.customview.getCustomView -class SleepTimerDialog : RoundedBottomSheetDialogFragment() { + +class SleepTimerDialog : DialogFragment() { private var seekArcProgress: Int = 0 private lateinit var timerUpdater: TimerUpdater + private lateinit var materialDialog: MaterialDialog + private lateinit var shouldFinishLastSong: CheckBox + private lateinit var seekBar: SeekBar + private lateinit var timerDisplay: TextView - override fun onDismiss(dialog: DialogInterface) { - super.onDismiss(dialog) - timerUpdater.cancel() + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { + timerUpdater = TimerUpdater() + + materialDialog = MaterialDialog(activity!!, BottomSheet()) + .title(R.string.action_sleep_timer) + .positiveButton(R.string.action_set) { + PreferenceUtil.getInstance().sleepTimerFinishMusic = shouldFinishLastSong.isChecked + + val minutes = seekArcProgress + + val pi = makeTimerPendingIntent(PendingIntent.FLAG_CANCEL_CURRENT) + + val nextSleepTimerElapsedTime = SystemClock.elapsedRealtime() + minutes * 60 * 1000 + PreferenceUtil.getInstance().setNextSleepTimerElapsedRealtime(nextSleepTimerElapsedTime) + val am = activity!!.getSystemService(Context.ALARM_SERVICE) as AlarmManager + am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextSleepTimerElapsedTime, pi) + + Toast.makeText(activity, activity!!.resources.getString(R.string.sleep_timer_set, minutes), Toast.LENGTH_SHORT).show() + } + .negativeButton(android.R.string.cancel) { + if (activity == null) { + return@negativeButton + } + val previous = makeTimerPendingIntent(PendingIntent.FLAG_NO_CREATE) + if (previous != null) { + val am = activity!!.getSystemService(Context.ALARM_SERVICE) as AlarmManager + am.cancel(previous) + previous.cancel() + Toast.makeText(activity, activity!!.resources.getString(R.string.sleep_timer_canceled), Toast.LENGTH_SHORT).show() + } + + val musicService = MusicPlayerRemote.musicService + if (musicService != null && musicService.pendingQuit) { + musicService.pendingQuit = false + Toast.makeText(activity, activity!!.resources.getString(R.string.sleep_timer_canceled), Toast.LENGTH_SHORT).show() + } + } + .customView(R.layout.dialog_sleep_timer, scrollable = false) + .show { + onShow { + if (makeTimerPendingIntent(PendingIntent.FLAG_NO_CREATE) != null) { + timerUpdater.start() + } + } + } + + if (activity == null || materialDialog.getCustomView() == null) { + return materialDialog + } + + shouldFinishLastSong = materialDialog.getCustomView().findViewById(R.id.shouldFinishLastSong) + seekBar = materialDialog.getCustomView().findViewById(R.id.seekBar) + timerDisplay = materialDialog.getCustomView().findViewById(R.id.timerDisplay) + + + val finishMusic = PreferenceUtil.getInstance().sleepTimerFinishMusic + shouldFinishLastSong.isChecked = finishMusic + + + seekArcProgress = PreferenceUtil.getInstance().lastSleepTimerValue + updateTimeDisplayTime() + seekBar.progress = seekArcProgress + + setProgressBarColor(ThemeStore.accentColor(context!!)) + + seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { + override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) { + if (i < 1) { + seekBar.progress = 1 + return + } + seekArcProgress = i + updateTimeDisplayTime() + } + + override fun onStartTrackingTouch(seekBar: SeekBar) { + + } + + override fun onStopTrackingTouch(seekBar: SeekBar) { + PreferenceUtil.getInstance().lastSleepTimerValue = seekArcProgress + } + }) + + return materialDialog } - override fun onResume() { - super.onResume() - if (makeTimerPendingIntent(PendingIntent.FLAG_NO_CREATE) != null) { - timerUpdater.start() + private fun updateTimeDisplayTime() { + timerDisplay.text = "$seekArcProgress min" + } + + + private fun makeTimerPendingIntent(flag: Int): PendingIntent { + return PendingIntent.getService(activity, 0, makeTimerIntent(), flag) + } + + private fun makeTimerIntent(): Intent { + val intent = Intent(activity, MusicService::class.java) + return if (shouldFinishLastSong.isChecked) { + intent.setAction(Constants.ACTION_PENDING_QUIT) + } else intent.setAction(Constants.ACTION_QUIT) + } + + + private fun updateCancelButton() { + val musicService = MusicPlayerRemote.musicService + if (musicService != null && musicService.pendingQuit) { + materialDialog.getActionButton(WhichButton.NEGATIVE).text = materialDialog.context.getString(R.string.cancel_current_timer) + } else { + materialDialog.getActionButton(WhichButton.NEGATIVE).text = null } } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { - return inflater.inflate(R.layout.dialog_sleep_timer, container, false) + private inner class TimerUpdater internal constructor() : CountDownTimer(PreferenceUtil.getInstance().nextSleepTimerElapsedRealTime - SystemClock.elapsedRealtime(), 1000) { + + override fun onTick(millisUntilFinished: Long) { + materialDialog.getActionButton(WhichButton.NEGATIVE).text = + String.format("%s %s", materialDialog.context.getString(R.string.cancel_current_timer), + " (" + MusicUtil.getReadableDurationString(millisUntilFinished) + ")") + } + + override fun onFinish() { + updateCancelButton() + } } + /* override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.dialog_sleep_timer, container, false) + }*/ + private fun setProgressBarColor(dark: Int) { ViewUtil.setProgressDrawable(progressSlider = seekBar, newColor = dark) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + /*override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) MaterialUtil.setTint(actionCancel, false) @@ -127,30 +250,7 @@ class SleepTimerDialog : RoundedBottomSheetDialogFragment() { dismiss() } } - } + }*/ - private fun updateTimeDisplayTime() { - timerDisplay!!.text = String.format(Locale.getDefault(), "%d min", seekArcProgress) - } - private fun makeTimerPendingIntent(flag: Int): PendingIntent? { - return PendingIntent.getService(activity, 0, makeTimerIntent(), flag) - } - - private fun makeTimerIntent(): Intent { - return Intent(activity, MusicService::class.java) - .setAction(ACTION_QUIT) - } - - private inner class TimerUpdater internal constructor() : CountDownTimer(PreferenceUtil.getInstance().nextSleepTimerElapsedRealTime - SystemClock.elapsedRealtime(), 1000) { - - override fun onTick(millisUntilFinished: Long) { - actionCancel.text = String.format("%s (%s)", getString(R.string.cancel_current_timer), MusicUtil.getReadableDurationString(millisUntilFinished)) - } - - override fun onFinish() { - actionCancel.text = null - actionCancel.visibility = View.GONE - } - } } \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/helper/MusicPlayerRemote.kt b/app/src/main/java/code/name/monkey/retromusic/helper/MusicPlayerRemote.kt index 443e973a..cf3e33f8 100644 --- a/app/src/main/java/code/name/monkey/retromusic/helper/MusicPlayerRemote.kt +++ b/app/src/main/java/code/name/monkey/retromusic/helper/MusicPlayerRemote.kt @@ -38,7 +38,7 @@ import java.util.* object MusicPlayerRemote { - val TAG = MusicPlayerRemote::class.java.simpleName + val TAG: String = MusicPlayerRemote::class.java.simpleName private val mConnectionMap = WeakHashMap() var musicService: MusicService? = null diff --git a/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java b/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java index a35c64b2..4db87c68 100644 --- a/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java +++ b/app/src/main/java/code/name/monkey/retromusic/service/MusicService.java @@ -49,6 +49,9 @@ import android.telephony.TelephonyManager; import android.util.Log; import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.bumptech.glide.request.transition.Transition; import java.lang.ref.WeakReference; @@ -56,8 +59,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Random; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import code.name.monkey.retromusic.R; import code.name.monkey.retromusic.appwidgets.AppWidgetBig; import code.name.monkey.retromusic.appwidgets.AppWidgetCard; @@ -87,6 +88,7 @@ import code.name.monkey.retromusic.util.PreferenceUtil; import code.name.monkey.retromusic.util.RetroUtil; 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; @@ -176,6 +178,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP } }; + public boolean pendingQuit = false; private Playback playback; private ArrayList playingQueue = new ArrayList<>(); private ArrayList originalPlayingQueue = new ArrayList<>(); @@ -448,7 +451,12 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP break; case ACTION_STOP: case ACTION_QUIT: - return quit(); + pendingQuit = false; + quit(); + break; + case ACTION_PENDING_QUIT: + pendingQuit = true; + break; } } } @@ -1178,6 +1186,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP return playback.getAudioSessionId(); } + @NonNull public MediaSessionCompat getMediaSession() { return mediaSession; } @@ -1193,7 +1202,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP } @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + public void onSharedPreferenceChanged(@NonNull SharedPreferences sharedPreferences, @NonNull String key) { switch (key) { case PreferenceUtil.GAPLESS_PLAYBACK: if (sharedPreferences.getBoolean(key, false)) { @@ -1251,10 +1260,8 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP @Override public void handleMessage(@NonNull Message msg) { final MusicService service = mService.get(); - switch (msg.what) { - case SAVE_QUEUES: - service.saveQueuesImpl(); - break; + if (msg.what == SAVE_QUEUES) { + service.saveQueuesImpl(); } } } @@ -1317,9 +1324,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); } diff --git a/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.java b/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.java index 632b9ef0..26fdd4fa 100644 --- a/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.java +++ b/app/src/main/java/code/name/monkey/retromusic/util/PreferenceUtil.java @@ -57,6 +57,7 @@ public final class PreferenceUtil { public static final String GAPLESS_PLAYBACK = "gapless_playback"; public static final String ALBUM_ART_ON_LOCKSCREEN = "album_art_on_lockscreen"; public static final String BLURRED_ALBUM_ART = "blurred_album_art"; + public static final String SLEEP_TIMER_FINISH_SONG = "sleep_timer_finish_song"; public static final String TOGGLE_HEADSET = "toggle_headset"; public static final String DOMINANT_COLOR = "dominant_color"; public static final String GENERAL_THEME = "general_theme"; @@ -156,6 +157,17 @@ public final class PreferenceUtil { } } + public void setSleepTimerFinishMusic(final boolean value) { + final SharedPreferences.Editor editor = mPreferences.edit(); + editor.putBoolean(SLEEP_TIMER_FINISH_SONG, value); + editor.apply(); + } + + public boolean getSleepTimerFinishMusic() { + return mPreferences.getBoolean(SLEEP_TIMER_FINISH_SONG, false); + } + + public String getUserBio() { return mPreferences.getString(USER_BIO, ""); } diff --git a/app/src/main/res/layout/dialog_sleep_timer.xml b/app/src/main/res/layout/dialog_sleep_timer.xml index b8ed7a09..a8ec4cfa 100644 --- a/app/src/main/res/layout/dialog_sleep_timer.xml +++ b/app/src/main/res/layout/dialog_sleep_timer.xml @@ -1,71 +1,35 @@ - + android:orientation="vertical"> - + + + + android:maxHeight="3dp" + android:paddingTop="12dp" + android:progressDrawable="@drawable/color_progress_seek" + android:splitTrack="false" + android:thumb="@drawable/switch_thumb_material" + tools:progress="20" /> - + - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_folder.xml b/app/src/main/res/layout/fragment_folder.xml index d4db9947..627f8c65 100644 --- a/app/src/main/res/layout/fragment_folder.xml +++ b/app/src/main/res/layout/fragment_folder.xml @@ -45,6 +45,9 @@ diff --git a/app/src/main/res/layout/fragment_library.xml b/app/src/main/res/layout/fragment_library.xml index cac8c3d5..7d5190f0 100644 --- a/app/src/main/res/layout/fragment_library.xml +++ b/app/src/main/res/layout/fragment_library.xml @@ -54,6 +54,7 @@ style="@style/BigTitleTextAppearanceToolbar" android:layout_gravity="start|center_vertical" android:paddingStart="14dp" + android:paddingEnd="8dp" android:text="@string/library" android:textColor="@color/md_white_1000" tools:ignore="MissingPrefix" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8d76c670..c906790d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -615,5 +615,6 @@ Select preset Upgrade to premium New playlist + Finish last song