Merge branch 'dev' of https://github.com/h4h13/RetroMusicPlayer into dev
Conflicts: README.md app/build.gradle app/src/main/java/code/name/monkey/retromusic/activities/PurchaseActivity.kt app/src/main/java/code/name/monkey/retromusic/activities/SupportDevelopmentActivity.kt app/src/main/java/code/name/monkey/retromusic/fragments/player/lockscreen/LockScreenPlayerControlsFragment.kt app/src/main/java/code/name/monkey/retromusic/interfaces/CabHolder.kt app/src/main/java/code/name/monkey/retromusic/interfaces/MainActivityFragmentCallbacks.kt app/src/main/java/code/name/monkey/retromusic/interfaces/MusicServiceEventListener.kt app/src/main/java/code/name/monkey/retromusic/interfaces/PaletteColorHolder.kt app/src/main/java/code/name/monkey/retromusic/util/AppRater.kt app/src/main/java/io/github/muntashirakon/music/App.kt app/src/main/java/io/github/muntashirakon/music/Constants.kt app/src/main/java/io/github/muntashirakon/music/HomeSection.kt app/src/main/java/io/github/muntashirakon/music/MainModule.kt app/src/main/java/io/github/muntashirakon/music/activities/DriveModeActivity.kt app/src/main/java/io/github/muntashirakon/music/activities/LicenseActivity.java app/src/main/java/io/github/muntashirakon/music/activities/LockScreenActivity.kt app/src/main/java/io/github/muntashirakon/music/activities/LyricsActivity.kt app/src/main/java/io/github/muntashirakon/music/activities/MainActivity.kt app/src/main/java/io/github/muntashirakon/music/activities/PermissionActivity.kt app/src/main/java/io/github/muntashirakon/music/activities/PlayingQueueActivity.kt app/src/main/java/io/github/muntashirakon/music/activities/SettingsActivity.kt app/src/main/java/io/github/muntashirakon/music/activities/ShareInstagramStory.kt app/src/main/java/io/github/muntashirakon/music/activities/UserInfoActivity.kt app/src/main/java/io/github/muntashirakon/music/activities/WhatsNewActivity.java app/src/main/java/io/github/muntashirakon/music/activities/base/AbsBaseActivity.kt app/src/main/java/io/github/muntashirakon/music/activities/base/AbsMusicServiceActivity.kt app/src/main/java/io/github/muntashirakon/music/activities/base/AbsSlidingMusicPanelActivity.kt app/src/main/java/io/github/muntashirakon/music/activities/base/AbsThemeActivity.kt app/src/main/java/io/github/muntashirakon/music/activities/bugreport/BugReportActivity.kt app/src/main/java/io/github/muntashirakon/music/activities/bugreport/model/DeviceInfo.java app/src/main/java/io/github/muntashirakon/music/activities/bugreport/model/Report.java app/src/main/java/io/github/muntashirakon/music/activities/saf/SAFGuideActivity.java app/src/main/java/io/github/muntashirakon/music/activities/tageditor/AbsTagEditorActivity.kt app/src/main/java/io/github/muntashirakon/music/activities/tageditor/AlbumTagEditorActivity.kt app/src/main/java/io/github/muntashirakon/music/activities/tageditor/SongTagEditorActivity.kt app/src/main/java/io/github/muntashirakon/music/activities/tageditor/WriteTagsAsyncTask.java app/src/main/java/io/github/muntashirakon/music/adapter/CategoryInfoAdapter.java app/src/main/java/io/github/muntashirakon/music/adapter/ContributorAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/GenreAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/HomeAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/SearchAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/SongFileAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/TranslatorsAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/album/AlbumAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/album/AlbumCoverPagerAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/album/HorizontalAlbumAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/artist/ArtistAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/base/AbsMultiSelectAdapter.java app/src/main/java/io/github/muntashirakon/music/adapter/base/MediaEntryViewHolder.java app/src/main/java/io/github/muntashirakon/music/adapter/playlist/LegacyPlaylistAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/playlist/PlaylistAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/song/AbsOffsetSongAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/song/OrderablePlaylistSongAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/song/PlayingQueueAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/song/PlaylistSongAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/song/ShuffleButtonSongAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/song/SimpleSongAdapter.kt app/src/main/java/io/github/muntashirakon/music/adapter/song/SongAdapter.kt app/src/main/java/io/github/muntashirakon/music/appshortcuts/AppShortcutIconGenerator.kt app/src/main/java/io/github/muntashirakon/music/appshortcuts/AppShortcutLauncherActivity.kt app/src/main/java/io/github/muntashirakon/music/appshortcuts/DynamicShortcutManager.kt app/src/main/java/io/github/muntashirakon/music/appshortcuts/shortcuttype/BaseShortcutType.kt app/src/main/java/io/github/muntashirakon/music/appshortcuts/shortcuttype/LastAddedShortcutType.kt app/src/main/java/io/github/muntashirakon/music/appshortcuts/shortcuttype/ShuffleAllShortcutType.kt app/src/main/java/io/github/muntashirakon/music/appshortcuts/shortcuttype/TopTracksShortcutType.kt app/src/main/java/io/github/muntashirakon/music/appwidgets/AppWidgetBig.kt app/src/main/java/io/github/muntashirakon/music/appwidgets/AppWidgetCard.kt app/src/main/java/io/github/muntashirakon/music/appwidgets/AppWidgetClassic.kt app/src/main/java/io/github/muntashirakon/music/appwidgets/AppWidgetSmall.kt app/src/main/java/io/github/muntashirakon/music/appwidgets/AppWidgetText.kt app/src/main/java/io/github/muntashirakon/music/appwidgets/BootReceiver.kt app/src/main/java/io/github/muntashirakon/music/appwidgets/base/BaseAppWidget.kt app/src/main/java/io/github/muntashirakon/music/db/BlackListStoreDao.kt app/src/main/java/io/github/muntashirakon/music/db/BlackListStoreEntity.kt app/src/main/java/io/github/muntashirakon/music/db/HistoryDao.kt app/src/main/java/io/github/muntashirakon/music/db/HistoryEntity.kt app/src/main/java/io/github/muntashirakon/music/db/LyricsDao.kt app/src/main/java/io/github/muntashirakon/music/db/LyricsEntity.kt app/src/main/java/io/github/muntashirakon/music/db/PlayCountDao.kt app/src/main/java/io/github/muntashirakon/music/db/PlayCountEntity.kt app/src/main/java/io/github/muntashirakon/music/db/PlaylistDao.kt app/src/main/java/io/github/muntashirakon/music/db/PlaylistEntity.kt app/src/main/java/io/github/muntashirakon/music/db/PlaylistWithSongs.kt app/src/main/java/io/github/muntashirakon/music/db/RetroDatabase.kt app/src/main/java/io/github/muntashirakon/music/db/SongEntity.kt app/src/main/java/io/github/muntashirakon/music/db/SongExtension.kt app/src/main/java/io/github/muntashirakon/music/dialogs/AddToPlaylistDialog.kt app/src/main/java/io/github/muntashirakon/music/dialogs/BlacklistFolderChooserDialog.java app/src/main/java/io/github/muntashirakon/music/dialogs/CreatePlaylistDialog.kt app/src/main/java/io/github/muntashirakon/music/dialogs/DeletePlaylistDialog.kt app/src/main/java/io/github/muntashirakon/music/dialogs/DeleteSongsDialog.kt app/src/main/java/io/github/muntashirakon/music/dialogs/ImportPlaylistDialog.kt app/src/main/java/io/github/muntashirakon/music/dialogs/LyricsDialog.kt app/src/main/java/io/github/muntashirakon/music/dialogs/RemoveSongFromPlaylistDialog.kt app/src/main/java/io/github/muntashirakon/music/dialogs/RenamePlaylistDialog.kt app/src/main/java/io/github/muntashirakon/music/dialogs/SavePlaylistDialog.kt app/src/main/java/io/github/muntashirakon/music/dialogs/SleepTimerDialog.kt app/src/main/java/io/github/muntashirakon/music/dialogs/SongDetailDialog.kt app/src/main/java/io/github/muntashirakon/music/dialogs/SongShareDialog.kt app/src/main/java/io/github/muntashirakon/music/extensions/ActivityEx.kt app/src/main/java/io/github/muntashirakon/music/extensions/ColorExt.kt app/src/main/java/io/github/muntashirakon/music/extensions/CursorExtensions.kt app/src/main/java/io/github/muntashirakon/music/extensions/DialogExtension.kt app/src/main/java/io/github/muntashirakon/music/extensions/DimenExtension.kt app/src/main/java/io/github/muntashirakon/music/extensions/DrawableExt.kt app/src/main/java/io/github/muntashirakon/music/extensions/FragmentExt.kt app/src/main/java/io/github/muntashirakon/music/extensions/NavigationExtensions.kt app/src/main/java/io/github/muntashirakon/music/extensions/PaletteEX.kt app/src/main/java/io/github/muntashirakon/music/extensions/Preference.kt app/src/main/java/io/github/muntashirakon/music/extensions/ViewExtensions.kt app/src/main/java/io/github/muntashirakon/music/fragments/AlbumCoverStyle.kt app/src/main/java/io/github/muntashirakon/music/fragments/CoroutineViewModel.kt app/src/main/java/io/github/muntashirakon/music/fragments/DetailListFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/LibraryViewModel.kt app/src/main/java/io/github/muntashirakon/music/fragments/MiniPlayerFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/NowPlayingScreen.kt app/src/main/java/io/github/muntashirakon/music/fragments/VolumeFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/about/AboutFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/albums/AlbumDetailsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/albums/AlbumDetailsViewModel.kt app/src/main/java/io/github/muntashirakon/music/fragments/albums/AlbumsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/artists/ArtistDetailsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/artists/ArtistDetailsViewModel.kt app/src/main/java/io/github/muntashirakon/music/fragments/artists/ArtistsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/base/AbsMainActivityFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/base/AbsMusicServiceFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/base/AbsPlayerControlsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/base/AbsPlayerFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/base/AbsRecyclerViewCustomGridSizeFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/base/AbsRecyclerViewFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/folder/FoldersFragment.java app/src/main/java/io/github/muntashirakon/music/fragments/genres/GenreDetailsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/genres/GenreDetailsViewModel.kt app/src/main/java/io/github/muntashirakon/music/fragments/genres/GenresFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/home/HomeFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/library/LibraryFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/NowPlayingPlayerFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/PlayerAlbumCoverFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/adaptive/AdaptiveFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/adaptive/AdaptivePlaybackControlsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/blur/BlurPlaybackControlsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/blur/BlurPlayerFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/card/CardFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/card/CardPlaybackControlsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/cardblur/CardBlurFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/cardblur/CardBlurPlaybackControlsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/circle/CirclePlayerFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/classic/ClassicPlayerFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/color/ColorFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/color/ColorPlaybackControlsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/fit/FitFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/fit/FitPlaybackControlsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/flat/FlatPlaybackControlsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/flat/FlatPlayerFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/full/FullPlaybackControlsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/full/FullPlayerFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/gradient/GradientPlayerFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/home/HomePlayerFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/lockscreen/LockScreenControlsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/lockscreen/LockScreenPlayerControlsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/material/MaterialControlsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/material/MaterialFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/normal/PlayerFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/normal/PlayerPlaybackControlsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/peak/PeakPlayerControlFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/peak/PeakPlayerFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/plain/PlainPlaybackControlsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/plain/PlainPlayerFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/simple/SimplePlaybackControlsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/simple/SimplePlayerFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/tiny/TinyPlaybackControlsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/player/tiny/TinyPlayerFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/playlists/PlaylistDetailsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/playlists/PlaylistDetailsViewModel.kt app/src/main/java/io/github/muntashirakon/music/fragments/playlists/PlaylistsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/search/SearchFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/search/SearchViewModel.kt app/src/main/java/io/github/muntashirakon/music/fragments/settings/AbsSettingsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/settings/AudioSettings.kt app/src/main/java/io/github/muntashirakon/music/fragments/settings/ImageSettingFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/settings/MainSettingsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/settings/NotificationSettingsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/settings/NowPlayingSettingsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/settings/OtherSettingsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/settings/PersonalizeSettingsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/settings/ThemeSettingsFragment.kt app/src/main/java/io/github/muntashirakon/music/fragments/songs/SongsFragment.kt app/src/main/java/io/github/muntashirakon/music/glide/AlbumGlideRequest.java app/src/main/java/io/github/muntashirakon/music/glide/ArtistGlideRequest.java app/src/main/java/io/github/muntashirakon/music/glide/BlurTransformation.kt app/src/main/java/io/github/muntashirakon/music/glide/ProfileBannerGlideRequest.java app/src/main/java/io/github/muntashirakon/music/glide/RetroMusicColoredTarget.kt app/src/main/java/io/github/muntashirakon/music/glide/RetroMusicGlideModule.kt app/src/main/java/io/github/muntashirakon/music/glide/SingleColorTarget.kt app/src/main/java/io/github/muntashirakon/music/glide/SongGlideRequest.java app/src/main/java/io/github/muntashirakon/music/glide/UserProfileGlideRequest.java app/src/main/java/io/github/muntashirakon/music/glide/artistimage/ArtistImageLoader.kt app/src/main/java/io/github/muntashirakon/music/glide/palette/BitmapPaletteTranscoder.java app/src/main/java/io/github/muntashirakon/music/helper/HorizontalAdapterHelper.kt app/src/main/java/io/github/muntashirakon/music/helper/MusicPlayerRemote.kt app/src/main/java/io/github/muntashirakon/music/helper/MusicProgressViewUpdateHelper.kt app/src/main/java/io/github/muntashirakon/music/helper/PlayPauseButtonOnClickHandler.kt app/src/main/java/io/github/muntashirakon/music/helper/SearchQueryHelper.kt app/src/main/java/io/github/muntashirakon/music/helper/ShuffleHelper.kt app/src/main/java/io/github/muntashirakon/music/helper/StopWatch.kt app/src/main/java/io/github/muntashirakon/music/helper/menu/GenreMenuHelper.kt app/src/main/java/io/github/muntashirakon/music/helper/menu/PlaylistMenuHelper.kt app/src/main/java/io/github/muntashirakon/music/helper/menu/SongMenuHelper.kt app/src/main/java/io/github/muntashirakon/music/helper/menu/SongsMenuHelper.kt app/src/main/java/io/github/muntashirakon/music/interfaces/CabHolder.kt app/src/main/java/io/github/muntashirakon/music/interfaces/Callbacks.kt app/src/main/java/io/github/muntashirakon/music/interfaces/ICabHolder.kt app/src/main/java/io/github/muntashirakon/music/interfaces/IMainActivityFragmentCallbacks.kt app/src/main/java/io/github/muntashirakon/music/interfaces/IMusicServiceEventListener.kt app/src/main/java/io/github/muntashirakon/music/interfaces/IPaletteColorHolder.kt app/src/main/java/io/github/muntashirakon/music/interfaces/MainActivityFragmentCallbacks.kt app/src/main/java/io/github/muntashirakon/music/interfaces/MusicServiceEventListener.kt app/src/main/java/io/github/muntashirakon/music/interfaces/PaletteColorHolder.kt app/src/main/java/io/github/muntashirakon/music/lyrics/LrcView.java app/src/main/java/io/github/muntashirakon/music/model/Artist.kt app/src/main/java/io/github/muntashirakon/music/model/lyrics/Lyrics.java app/src/main/java/io/github/muntashirakon/music/providers/BlacklistStore.java app/src/main/java/io/github/muntashirakon/music/providers/MusicPlaybackQueueStore.java app/src/main/java/io/github/muntashirakon/music/repository/GenreRepository.kt app/src/main/java/io/github/muntashirakon/music/repository/PlaylistSongsLoader.kt app/src/main/java/io/github/muntashirakon/music/repository/Repository.kt app/src/main/java/io/github/muntashirakon/music/repository/RoomRepository.kt app/src/main/java/io/github/muntashirakon/music/repository/SongRepository.kt app/src/main/java/io/github/muntashirakon/music/service/MultiPlayer.java app/src/main/java/io/github/muntashirakon/music/service/MusicService.java app/src/main/java/io/github/muntashirakon/music/service/PlaybackHandler.java app/src/main/java/io/github/muntashirakon/music/util/FileUtil.java app/src/main/java/io/github/muntashirakon/music/util/NavigationUtil.java app/src/main/java/io/github/muntashirakon/music/util/PlaylistsUtil.java app/src/main/java/io/github/muntashirakon/music/util/PreferenceUtil.kt app/src/main/java/io/github/muntashirakon/music/util/RetroUtil.java app/src/main/java/io/github/muntashirakon/music/util/SAFUtil.java app/src/main/java/io/github/muntashirakon/music/util/color/MediaNotificationProcessor.java app/src/main/java/io/github/muntashirakon/music/util/color/NotificationColorUtil.java app/src/main/java/io/github/muntashirakon/music/views/BaselineGridTextView.java app/src/main/java/io/github/muntashirakon/music/views/BreadCrumbLayout.java app/src/main/java/io/github/muntashirakon/music/views/CircularImageView.java app/src/main/java/io/github/muntashirakon/music/views/ContributorsView.java app/src/main/java/io/github/muntashirakon/music/views/NetworkImageView.java app/src/main/java/io/github/muntashirakon/music/views/SeekArc.java app/src/main/res/layout-land/fragment_home.xml app/src/main/res/layout-xlarge-land/fragment_blur.xml app/src/main/res/layout/activity_lock_screen.xml app/src/main/res/layout/activity_user_info.xml app/src/main/res/layout/fragment_banner_home.xml app/src/main/res/layout/fragment_classic_player.xml app/src/main/res/layout/fragment_folder.xml app/src/main/res/layout/fragment_home.xml app/src/main/res/layout/item_image.xml app/src/main/res/layout/sliding_music_panel_layout.xml app/src/main/res/navigation/now_playing.xml
This commit is contained in:
commit
3c0fc790d1
442 changed files with 18453 additions and 14559 deletions
|
@ -23,327 +23,300 @@ import android.net.Uri;
|
|||
import android.os.PowerManager;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import io.github.muntashirakon.music.R;
|
||||
import io.github.muntashirakon.music.service.playback.Playback;
|
||||
import io.github.muntashirakon.music.util.PreferenceUtil;
|
||||
|
||||
/**
|
||||
* @author Andrew Neal, Karim Abou Zeid (kabouzeid)
|
||||
*/
|
||||
public class MultiPlayer implements Playback, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener {
|
||||
public static final String TAG = MultiPlayer.class.getSimpleName();
|
||||
/** @author Andrew Neal, Karim Abou Zeid (kabouzeid) */
|
||||
public class MultiPlayer
|
||||
implements Playback, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener {
|
||||
public static final String TAG = MultiPlayer.class.getSimpleName();
|
||||
|
||||
private MediaPlayer mCurrentMediaPlayer = new MediaPlayer();
|
||||
private MediaPlayer mNextMediaPlayer;
|
||||
private MediaPlayer mCurrentMediaPlayer = new MediaPlayer();
|
||||
private MediaPlayer mNextMediaPlayer;
|
||||
|
||||
private Context context;
|
||||
@Nullable
|
||||
private Playback.PlaybackCallbacks callbacks;
|
||||
private Context context;
|
||||
@Nullable private Playback.PlaybackCallbacks callbacks;
|
||||
|
||||
private boolean mIsInitialized = false;
|
||||
private boolean mIsInitialized = false;
|
||||
|
||||
/**
|
||||
* Constructor of <code>MultiPlayer</code>
|
||||
*/
|
||||
MultiPlayer(final Context context) {
|
||||
this.context = context;
|
||||
mCurrentMediaPlayer.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK);
|
||||
/** Constructor of <code>MultiPlayer</code> */
|
||||
MultiPlayer(final Context context) {
|
||||
this.context = context;
|
||||
mCurrentMediaPlayer.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param path The path of the file, or the http/rtsp URL of the stream you want to play
|
||||
* @return True if the <code>player</code> has been prepared and is ready to play, false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean setDataSource(@NonNull final String path) {
|
||||
mIsInitialized = false;
|
||||
mIsInitialized = setDataSourceImpl(mCurrentMediaPlayer, path);
|
||||
if (mIsInitialized) {
|
||||
setNextDataSource(null);
|
||||
}
|
||||
return mIsInitialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param path The path of the file, or the http/rtsp URL of the stream
|
||||
* you want to play
|
||||
* @return True if the <code>player</code> has been prepared and is
|
||||
* ready to play, false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean setDataSource(@NonNull final String path) {
|
||||
mIsInitialized = false;
|
||||
mIsInitialized = setDataSourceImpl(mCurrentMediaPlayer, path);
|
||||
if (mIsInitialized) {
|
||||
setNextDataSource(null);
|
||||
}
|
||||
return mIsInitialized;
|
||||
/**
|
||||
* @param player The {@link MediaPlayer} to use
|
||||
* @param path The path of the file, or the http/rtsp URL of the stream you want to play
|
||||
* @return True if the <code>player</code> has been prepared and is ready to play, false otherwise
|
||||
*/
|
||||
private boolean setDataSourceImpl(@NonNull final MediaPlayer player, @NonNull final String path) {
|
||||
if (context == null) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
player.reset();
|
||||
player.setOnPreparedListener(null);
|
||||
if (path.startsWith("content://")) {
|
||||
player.setDataSource(context, Uri.parse(path));
|
||||
} else {
|
||||
player.setDataSource(path);
|
||||
}
|
||||
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||
player.prepare();
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
player.setOnCompletionListener(this);
|
||||
player.setOnErrorListener(this);
|
||||
final Intent intent = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
|
||||
intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, getAudioSessionId());
|
||||
intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.getPackageName());
|
||||
intent.putExtra(AudioEffect.EXTRA_CONTENT_TYPE, AudioEffect.CONTENT_TYPE_MUSIC);
|
||||
context.sendBroadcast(intent);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param player The {@link MediaPlayer} to use
|
||||
* @param path The path of the file, or the http/rtsp URL of the stream
|
||||
* you want to play
|
||||
* @return True if the <code>player</code> has been prepared and is
|
||||
* ready to play, false otherwise
|
||||
*/
|
||||
private boolean setDataSourceImpl(@NonNull final MediaPlayer player, @NonNull final String path) {
|
||||
if (context == null) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Set the MediaPlayer to start when this MediaPlayer finishes playback.
|
||||
*
|
||||
* @param path The path of the file, or the http/rtsp URL of the stream you want to play
|
||||
*/
|
||||
@Override
|
||||
public void setNextDataSource(@Nullable final String path) {
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mCurrentMediaPlayer.setNextMediaPlayer(null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.i(TAG, "Next media player is current one, continuing");
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(TAG, "Media player not initialized!");
|
||||
return;
|
||||
}
|
||||
if (mNextMediaPlayer != null) {
|
||||
mNextMediaPlayer.release();
|
||||
mNextMediaPlayer = null;
|
||||
}
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
if (PreferenceUtil.INSTANCE.isGapLessPlayback()) {
|
||||
mNextMediaPlayer = new MediaPlayer();
|
||||
mNextMediaPlayer.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK);
|
||||
mNextMediaPlayer.setAudioSessionId(getAudioSessionId());
|
||||
if (setDataSourceImpl(mNextMediaPlayer, path)) {
|
||||
try {
|
||||
player.reset();
|
||||
player.setOnPreparedListener(null);
|
||||
if (path.startsWith("content://")) {
|
||||
player.setDataSource(context, Uri.parse(path));
|
||||
} else {
|
||||
player.setDataSource(path);
|
||||
}
|
||||
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||
player.prepare();
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
player.setOnCompletionListener(this);
|
||||
player.setOnErrorListener(this);
|
||||
final Intent intent = new Intent(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION);
|
||||
intent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, getAudioSessionId());
|
||||
intent.putExtra(AudioEffect.EXTRA_PACKAGE_NAME, context.getPackageName());
|
||||
intent.putExtra(AudioEffect.EXTRA_CONTENT_TYPE, AudioEffect.CONTENT_TYPE_MUSIC);
|
||||
context.sendBroadcast(intent);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the MediaPlayer to start when this MediaPlayer finishes playback.
|
||||
*
|
||||
* @param path The path of the file, or the http/rtsp URL of the stream
|
||||
* you want to play
|
||||
*/
|
||||
@Override
|
||||
public void setNextDataSource(@Nullable final String path) {
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
mCurrentMediaPlayer.setNextMediaPlayer(null);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.i(TAG, "Next media player is current one, continuing");
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(TAG, "Media player not initialized!");
|
||||
return;
|
||||
}
|
||||
if (mNextMediaPlayer != null) {
|
||||
mNextMediaPlayer.release();
|
||||
mNextMediaPlayer = null;
|
||||
}
|
||||
if (path == null) {
|
||||
return;
|
||||
}
|
||||
if (PreferenceUtil.INSTANCE.isGapLessPlayback()) {
|
||||
mNextMediaPlayer = new MediaPlayer();
|
||||
mNextMediaPlayer.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK);
|
||||
mNextMediaPlayer.setAudioSessionId(getAudioSessionId());
|
||||
if (setDataSourceImpl(mNextMediaPlayer, path)) {
|
||||
try {
|
||||
mCurrentMediaPlayer.setNextMediaPlayer(mNextMediaPlayer);
|
||||
} catch (@NonNull IllegalArgumentException | IllegalStateException e) {
|
||||
Log.e(TAG, "setNextDataSource: setNextMediaPlayer()", e);
|
||||
if (mNextMediaPlayer != null) {
|
||||
mNextMediaPlayer.release();
|
||||
mNextMediaPlayer = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mNextMediaPlayer != null) {
|
||||
mNextMediaPlayer.release();
|
||||
mNextMediaPlayer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the callbacks
|
||||
*
|
||||
* @param callbacks The callbacks to use
|
||||
*/
|
||||
@Override
|
||||
public void setCallbacks(@Nullable final Playback.PlaybackCallbacks callbacks) {
|
||||
this.callbacks = callbacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if the player is ready to go, false otherwise
|
||||
*/
|
||||
@Override
|
||||
public boolean isInitialized() {
|
||||
return mIsInitialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts or resumes playback.
|
||||
*/
|
||||
@Override
|
||||
public boolean start() {
|
||||
try {
|
||||
mCurrentMediaPlayer.start();
|
||||
return true;
|
||||
} catch (IllegalStateException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the MediaPlayer to its uninitialized state.
|
||||
*/
|
||||
@Override
|
||||
public void stop() {
|
||||
mCurrentMediaPlayer.reset();
|
||||
mIsInitialized = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases resources associated with this MediaPlayer object.
|
||||
*/
|
||||
@Override
|
||||
public void release() {
|
||||
stop();
|
||||
mCurrentMediaPlayer.release();
|
||||
if (mNextMediaPlayer != null) {
|
||||
mNextMediaPlayer.release();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pauses playback. Call start() to resume.
|
||||
*/
|
||||
@Override
|
||||
public boolean pause() {
|
||||
try {
|
||||
mCurrentMediaPlayer.pause();
|
||||
return true;
|
||||
} catch (IllegalStateException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the MultiPlayer is playing.
|
||||
*/
|
||||
@Override
|
||||
public boolean isPlaying() {
|
||||
return mIsInitialized && mCurrentMediaPlayer.isPlaying();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the duration of the file.
|
||||
*
|
||||
* @return The duration in milliseconds
|
||||
*/
|
||||
@Override
|
||||
public int duration() {
|
||||
if (!mIsInitialized) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
return mCurrentMediaPlayer.getDuration();
|
||||
} catch (IllegalStateException e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current playback position.
|
||||
*
|
||||
* @return The current position in milliseconds
|
||||
*/
|
||||
@Override
|
||||
public int position() {
|
||||
if (!mIsInitialized) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
return mCurrentMediaPlayer.getCurrentPosition();
|
||||
} catch (IllegalStateException e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current playback position.
|
||||
*
|
||||
* @param whereto The offset in milliseconds from the start to seek to
|
||||
* @return The offset in milliseconds from the start to seek to
|
||||
*/
|
||||
@Override
|
||||
public int seek(final int whereto) {
|
||||
try {
|
||||
mCurrentMediaPlayer.seekTo(whereto);
|
||||
return whereto;
|
||||
} catch (IllegalStateException e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setVolume(final float vol) {
|
||||
try {
|
||||
mCurrentMediaPlayer.setVolume(vol, vol);
|
||||
return true;
|
||||
} catch (IllegalStateException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the audio session ID.
|
||||
*
|
||||
* @param sessionId The audio session ID
|
||||
*/
|
||||
@Override
|
||||
public boolean setAudioSessionId(final int sessionId) {
|
||||
try {
|
||||
mCurrentMediaPlayer.setAudioSessionId(sessionId);
|
||||
return true;
|
||||
mCurrentMediaPlayer.setNextMediaPlayer(mNextMediaPlayer);
|
||||
} catch (@NonNull IllegalArgumentException | IllegalStateException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the audio session ID.
|
||||
*
|
||||
* @return The current audio session ID.
|
||||
*/
|
||||
@Override
|
||||
public int getAudioSessionId() {
|
||||
return mCurrentMediaPlayer.getAudioSessionId();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean onError(final MediaPlayer mp, final int what, final int extra) {
|
||||
mIsInitialized = false;
|
||||
mCurrentMediaPlayer.release();
|
||||
mCurrentMediaPlayer = new MediaPlayer();
|
||||
mCurrentMediaPlayer.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK);
|
||||
if (context != null) {
|
||||
Toast.makeText(context, context.getResources().getString(R.string.unplayable_file), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onCompletion(final MediaPlayer mp) {
|
||||
if (mp.equals(mCurrentMediaPlayer) && mNextMediaPlayer != null) {
|
||||
mIsInitialized = false;
|
||||
mCurrentMediaPlayer.release();
|
||||
mCurrentMediaPlayer = mNextMediaPlayer;
|
||||
mIsInitialized = true;
|
||||
Log.e(TAG, "setNextDataSource: setNextMediaPlayer()", e);
|
||||
if (mNextMediaPlayer != null) {
|
||||
mNextMediaPlayer.release();
|
||||
mNextMediaPlayer = null;
|
||||
if (callbacks != null)
|
||||
callbacks.onTrackWentToNext();
|
||||
} else {
|
||||
if (callbacks != null)
|
||||
callbacks.onTrackEnded();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mNextMediaPlayer != null) {
|
||||
mNextMediaPlayer.release();
|
||||
mNextMediaPlayer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the callbacks
|
||||
*
|
||||
* @param callbacks The callbacks to use
|
||||
*/
|
||||
@Override
|
||||
public void setCallbacks(@Nullable final Playback.PlaybackCallbacks callbacks) {
|
||||
this.callbacks = callbacks;
|
||||
}
|
||||
|
||||
}
|
||||
/** @return True if the player is ready to go, false otherwise */
|
||||
@Override
|
||||
public boolean isInitialized() {
|
||||
return mIsInitialized;
|
||||
}
|
||||
|
||||
/** Starts or resumes playback. */
|
||||
@Override
|
||||
public boolean start() {
|
||||
try {
|
||||
mCurrentMediaPlayer.start();
|
||||
return true;
|
||||
} catch (IllegalStateException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Resets the MediaPlayer to its uninitialized state. */
|
||||
@Override
|
||||
public void stop() {
|
||||
mCurrentMediaPlayer.reset();
|
||||
mIsInitialized = false;
|
||||
}
|
||||
|
||||
/** Releases resources associated with this MediaPlayer object. */
|
||||
@Override
|
||||
public void release() {
|
||||
stop();
|
||||
mCurrentMediaPlayer.release();
|
||||
if (mNextMediaPlayer != null) {
|
||||
mNextMediaPlayer.release();
|
||||
}
|
||||
}
|
||||
|
||||
/** Pauses playback. Call start() to resume. */
|
||||
@Override
|
||||
public boolean pause() {
|
||||
try {
|
||||
mCurrentMediaPlayer.pause();
|
||||
return true;
|
||||
} catch (IllegalStateException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Checks whether the MultiPlayer is playing. */
|
||||
@Override
|
||||
public boolean isPlaying() {
|
||||
return mIsInitialized && mCurrentMediaPlayer.isPlaying();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the duration of the file.
|
||||
*
|
||||
* @return The duration in milliseconds
|
||||
*/
|
||||
@Override
|
||||
public int duration() {
|
||||
if (!mIsInitialized) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
return mCurrentMediaPlayer.getDuration();
|
||||
} catch (IllegalStateException e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current playback position.
|
||||
*
|
||||
* @return The current position in milliseconds
|
||||
*/
|
||||
@Override
|
||||
public int position() {
|
||||
if (!mIsInitialized) {
|
||||
return -1;
|
||||
}
|
||||
try {
|
||||
return mCurrentMediaPlayer.getCurrentPosition();
|
||||
} catch (IllegalStateException e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current playback position.
|
||||
*
|
||||
* @param whereto The offset in milliseconds from the start to seek to
|
||||
* @return The offset in milliseconds from the start to seek to
|
||||
*/
|
||||
@Override
|
||||
public int seek(final int whereto) {
|
||||
try {
|
||||
mCurrentMediaPlayer.seekTo(whereto);
|
||||
return whereto;
|
||||
} catch (IllegalStateException e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setVolume(final float vol) {
|
||||
try {
|
||||
mCurrentMediaPlayer.setVolume(vol, vol);
|
||||
return true;
|
||||
} catch (IllegalStateException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the audio session ID.
|
||||
*
|
||||
* @param sessionId The audio session ID
|
||||
*/
|
||||
@Override
|
||||
public boolean setAudioSessionId(final int sessionId) {
|
||||
try {
|
||||
mCurrentMediaPlayer.setAudioSessionId(sessionId);
|
||||
return true;
|
||||
} catch (@NonNull IllegalArgumentException | IllegalStateException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the audio session ID.
|
||||
*
|
||||
* @return The current audio session ID.
|
||||
*/
|
||||
@Override
|
||||
public int getAudioSessionId() {
|
||||
return mCurrentMediaPlayer.getAudioSessionId();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean onError(final MediaPlayer mp, final int what, final int extra) {
|
||||
mIsInitialized = false;
|
||||
mCurrentMediaPlayer.release();
|
||||
mCurrentMediaPlayer = new MediaPlayer();
|
||||
mCurrentMediaPlayer.setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK);
|
||||
if (context != null) {
|
||||
Toast.makeText(
|
||||
context,
|
||||
context.getResources().getString(R.string.unplayable_file),
|
||||
Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onCompletion(final MediaPlayer mp) {
|
||||
if (mp.equals(mCurrentMediaPlayer) && mNextMediaPlayer != null) {
|
||||
mIsInitialized = false;
|
||||
mCurrentMediaPlayer.release();
|
||||
mCurrentMediaPlayer = mNextMediaPlayer;
|
||||
mIsInitialized = true;
|
||||
mNextMediaPlayer = null;
|
||||
if (callbacks != null) callbacks.onTrackWentToNext();
|
||||
} else {
|
||||
if (callbacks != null) callbacks.onTrackEnded();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ import java.util.Objects;
|
|||
import java.util.Random;
|
||||
|
||||
import io.github.muntashirakon.music.R;
|
||||
import io.github.muntashirakon.music.activities.LockScreenActivity;
|
||||
import io.github.muntashirakon.music.appwidgets.AppWidgetBig;
|
||||
import io.github.muntashirakon.music.appwidgets.AppWidgetCard;
|
||||
import io.github.muntashirakon.music.appwidgets.AppWidgetClassic;
|
||||
|
@ -71,8 +72,10 @@ import io.github.muntashirakon.music.appwidgets.AppWidgetText;
|
|||
import io.github.muntashirakon.music.glide.BlurTransformation;
|
||||
import io.github.muntashirakon.music.glide.SongGlideRequest;
|
||||
import io.github.muntashirakon.music.helper.ShuffleHelper;
|
||||
import io.github.muntashirakon.music.model.AbsCustomPlaylist;
|
||||
import io.github.muntashirakon.music.model.Playlist;
|
||||
import io.github.muntashirakon.music.model.Song;
|
||||
import io.github.muntashirakon.music.model.smartplaylist.AbsSmartPlaylist;
|
||||
import io.github.muntashirakon.music.providers.HistoryStore;
|
||||
import io.github.muntashirakon.music.providers.MusicPlaybackQueueStore;
|
||||
import io.github.muntashirakon.music.providers.SongPlayCountStore;
|
||||
|
@ -94,8 +97,8 @@ import static io.github.muntashirakon.music.ConstantsKt.TOGGLE_HEADSET;
|
|||
/**
|
||||
* @author Karim Abou Zeid (kabouzeid), Andrew Neal
|
||||
*/
|
||||
public class MusicService extends Service implements
|
||||
SharedPreferences.OnSharedPreferenceChangeListener, Playback.PlaybackCallbacks {
|
||||
public class MusicService extends Service
|
||||
implements SharedPreferences.OnSharedPreferenceChangeListener, Playback.PlaybackCallbacks {
|
||||
|
||||
public static final String TAG = MusicService.class.getSimpleName();
|
||||
public static final String RETRO_MUSIC_PACKAGE_NAME = "io.github.muntashirakon.music";
|
||||
|
@ -109,17 +112,22 @@ public class MusicService extends Service implements
|
|||
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 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)
|
||||
// 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 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 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";
|
||||
|
@ -144,13 +152,14 @@ public class MusicService extends Service implements
|
|||
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
|
||||
| PlaybackStateCompat.ACTION_SKIP_TO_NEXT
|
||||
| PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
|
||||
| PlaybackStateCompat.ACTION_STOP
|
||||
| PlaybackStateCompat.ACTION_SEEK_TO;
|
||||
private static final long MEDIA_SESSION_ACTIONS =
|
||||
PlaybackStateCompat.ACTION_PLAY
|
||||
| PlaybackStateCompat.ACTION_PAUSE
|
||||
| PlaybackStateCompat.ACTION_PLAY_PAUSE
|
||||
| PlaybackStateCompat.ACTION_SKIP_TO_NEXT
|
||||
| PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
|
||||
| PlaybackStateCompat.ACTION_STOP
|
||||
| PlaybackStateCompat.ACTION_SEEK_TO;
|
||||
private final IBinder musicBind = new MusicBinder();
|
||||
public int nextPosition = -1;
|
||||
|
||||
|
@ -171,43 +180,44 @@ public class MusicService extends Service implements
|
|||
|
||||
private AppWidgetText appWidgetText = AppWidgetText.Companion.getInstance();
|
||||
|
||||
private final BroadcastReceiver widgetIntentReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String command = intent.getStringExtra(EXTRA_APP_WIDGET_NAME);
|
||||
final int[] ids = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
|
||||
if (command != null) {
|
||||
switch (command) {
|
||||
case AppWidgetClassic.NAME: {
|
||||
appWidgetClassic.performUpdate(MusicService.this, ids);
|
||||
break;
|
||||
}
|
||||
case AppWidgetSmall.NAME: {
|
||||
appWidgetSmall.performUpdate(MusicService.this, ids);
|
||||
break;
|
||||
}
|
||||
case AppWidgetBig.NAME: {
|
||||
appWidgetBig.performUpdate(MusicService.this, ids);
|
||||
break;
|
||||
}
|
||||
case AppWidgetCard.NAME: {
|
||||
appWidgetCard.performUpdate(MusicService.this, ids);
|
||||
break;
|
||||
}
|
||||
case AppWidgetText.NAME: {
|
||||
appWidgetText.performUpdate(MusicService.this, ids);
|
||||
break;
|
||||
private final BroadcastReceiver widgetIntentReceiver =
|
||||
new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
final String command = intent.getStringExtra(EXTRA_APP_WIDGET_NAME);
|
||||
final int[] ids = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
|
||||
if (command != null) {
|
||||
switch (command) {
|
||||
case AppWidgetClassic.NAME: {
|
||||
appWidgetClassic.performUpdate(MusicService.this, ids);
|
||||
break;
|
||||
}
|
||||
case AppWidgetSmall.NAME: {
|
||||
appWidgetSmall.performUpdate(MusicService.this, ids);
|
||||
break;
|
||||
}
|
||||
case AppWidgetBig.NAME: {
|
||||
appWidgetBig.performUpdate(MusicService.this, ids);
|
||||
break;
|
||||
}
|
||||
case AppWidgetCard.NAME: {
|
||||
appWidgetCard.performUpdate(MusicService.this, ids);
|
||||
break;
|
||||
}
|
||||
case AppWidgetText.NAME: {
|
||||
appWidgetText.performUpdate(MusicService.this, ids);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
};
|
||||
private AudioManager audioManager;
|
||||
private IntentFilter becomingNoisyReceiverIntentFilter = new IntentFilter(
|
||||
AudioManager.ACTION_AUDIO_BECOMING_NOISY);
|
||||
private IntentFilter becomingNoisyReceiverIntentFilter =
|
||||
new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
|
||||
private boolean becomingNoisyReceiverRegistered;
|
||||
private IntentFilter bluetoothConnectedIntentFilter = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);
|
||||
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;
|
||||
|
@ -219,96 +229,112 @@ public class MusicService extends Service implements
|
|||
private List<Song> playingQueue = 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 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 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 final BroadcastReceiver updateFavoriteReceiver =
|
||||
new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(final Context context, final Intent intent) {
|
||||
updateNotification();
|
||||
}
|
||||
};
|
||||
private final BroadcastReceiver lockScreenReceiver =
|
||||
new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (PreferenceUtil.INSTANCE.isLockScreen() && isPlaying()) {
|
||||
Intent lockIntent = new Intent(context, LockScreenActivity.class);
|
||||
lockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
startActivity(lockIntent);
|
||||
}
|
||||
}
|
||||
};
|
||||
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.INSTANCE.isBluetoothSpeaker()) {
|
||||
if (VERSION.SDK_INT >= VERSION_CODES.M) {
|
||||
if (getAudioManager().getDevices(AudioManager.GET_DEVICES_OUTPUTS).length > 0) {
|
||||
play();
|
||||
}
|
||||
} else {
|
||||
if (getAudioManager().isBluetoothA2dpOn()) {
|
||||
play();
|
||||
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.INSTANCE.isBluetoothSpeaker()) {
|
||||
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);
|
||||
};
|
||||
private PhoneStateListener phoneStateListener =
|
||||
new PhoneStateListener() {
|
||||
@Override
|
||||
public void onCallStateChanged(int state, String incomingNumber) {
|
||||
switch (state) {
|
||||
case 0:
|
||||
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;
|
||||
case 1:
|
||||
play();
|
||||
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;
|
||||
|
@ -333,7 +359,8 @@ public class MusicService extends Service implements
|
|||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
final TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
|
||||
final TelephonyManager telephonyManager =
|
||||
(TelephonyManager) getSystemService(TELEPHONY_SERVICE);
|
||||
if (telephonyManager != null) {
|
||||
telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
|
||||
}
|
||||
|
@ -353,8 +380,10 @@ public class MusicService extends Service implements
|
|||
|
||||
setupMediaSession();
|
||||
|
||||
// queue saving needs to run on a separate thread so that it doesn't block the playback handler events
|
||||
queueSaveHandlerThread = new HandlerThread("QueueSaveHandler", Process.THREAD_PRIORITY_BACKGROUND);
|
||||
// queue saving needs to run on a separate thread so that it doesn't block the playback handler
|
||||
// events
|
||||
queueSaveHandlerThread =
|
||||
new HandlerThread("QueueSaveHandler", Process.THREAD_PRIORITY_BACKGROUND);
|
||||
queueSaveHandlerThread.start();
|
||||
queueSaveHandler = new QueueSaveHandler(this, queueSaveHandlerThread.getLooper());
|
||||
|
||||
|
@ -362,38 +391,49 @@ public class MusicService extends Service implements
|
|||
|
||||
registerReceiver(widgetIntentReceiver, new IntentFilter(APP_WIDGET_UPDATE));
|
||||
registerReceiver(updateFavoriteReceiver, new IntentFilter(FAVORITE_STATE_CHANGED));
|
||||
registerReceiver(lockScreenReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
|
||||
|
||||
initNotification();
|
||||
|
||||
mediaStoreObserver = new MediaStoreObserver(this, playerHandler);
|
||||
throttledSeekHandler = new ThrottledSeekHandler(this, playerHandler);
|
||||
getContentResolver()
|
||||
.registerContentObserver(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
.registerContentObserver(
|
||||
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
getContentResolver()
|
||||
.registerContentObserver(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
.registerContentObserver(
|
||||
MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
getContentResolver()
|
||||
.registerContentObserver(MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
.registerContentObserver(
|
||||
MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
getContentResolver()
|
||||
.registerContentObserver(MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
.registerContentObserver(
|
||||
MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
getContentResolver()
|
||||
.registerContentObserver(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
.registerContentObserver(
|
||||
MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
|
||||
getContentResolver()
|
||||
.registerContentObserver(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
.registerContentObserver(
|
||||
MediaStore.Audio.Media.INTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
getContentResolver()
|
||||
.registerContentObserver(MediaStore.Audio.Albums.INTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
.registerContentObserver(
|
||||
MediaStore.Audio.Albums.INTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
getContentResolver()
|
||||
.registerContentObserver(MediaStore.Audio.Artists.INTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
.registerContentObserver(
|
||||
MediaStore.Audio.Artists.INTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
getContentResolver()
|
||||
.registerContentObserver(MediaStore.Audio.Genres.INTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
.registerContentObserver(
|
||||
MediaStore.Audio.Genres.INTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
getContentResolver()
|
||||
.registerContentObserver(MediaStore.Audio.Playlists.INTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
.registerContentObserver(
|
||||
MediaStore.Audio.Playlists.INTERNAL_CONTENT_URI, true, mediaStoreObserver);
|
||||
|
||||
PreferenceUtil.INSTANCE.registerOnSharedPreferenceChangedListener(this);
|
||||
|
||||
restoreState();
|
||||
|
||||
sendBroadcast(new Intent(RETRO_MUSIC_PACKAGE_NAME + ".RETRO_MUSIC_SERVICE_CREATED"));
|
||||
sendBroadcast(new Intent("io.github.muntashirakon.music.RETRO_MUSIC_SERVICE_CREATED"));
|
||||
|
||||
registerHeadsetEvents();
|
||||
registerBluetoothConnected();
|
||||
|
@ -403,6 +443,7 @@ public class MusicService extends Service implements
|
|||
public void onDestroy() {
|
||||
unregisterReceiver(widgetIntentReceiver);
|
||||
unregisterReceiver(updateFavoriteReceiver);
|
||||
unregisterReceiver(lockScreenReceiver);
|
||||
if (becomingNoisyReceiverRegistered) {
|
||||
unregisterReceiver(becomingNoisyReceiver);
|
||||
becomingNoisyReceiverRegistered = false;
|
||||
|
@ -422,7 +463,7 @@ public class MusicService extends Service implements
|
|||
PreferenceUtil.INSTANCE.unregisterOnSharedPreferenceChangedListener(this);
|
||||
wakeLock.release();
|
||||
|
||||
sendBroadcast(new Intent(RETRO_MUSIC_PACKAGE_NAME + ".RETRO_MUSIC_SERVICE_DESTROYED"));
|
||||
sendBroadcast(new Intent("io.github.muntashirakon.music.RETRO_MUSIC_SERVICE_DESTROYED"));
|
||||
}
|
||||
|
||||
public void acquireWakeLock(long milli) {
|
||||
|
@ -591,7 +632,8 @@ public class MusicService extends Service implements
|
|||
case REPEAT_MODE_ALL:
|
||||
case REPEAT_MODE_THIS:
|
||||
this.repeatMode = repeatMode;
|
||||
PreferenceManager.getDefaultSharedPreferences(this).edit()
|
||||
PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.edit()
|
||||
.putInt(SAVED_REPEAT_MODE, repeatMode)
|
||||
.apply();
|
||||
prepareNext();
|
||||
|
@ -605,7 +647,8 @@ public class MusicService extends Service implements
|
|||
}
|
||||
|
||||
public void setShuffleMode(final int shuffleMode) {
|
||||
PreferenceManager.getDefaultSharedPreferences(this).edit()
|
||||
PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.edit()
|
||||
.putInt(SAVED_SHUFFLE_MODE, shuffleMode)
|
||||
.apply();
|
||||
switch (shuffleMode) {
|
||||
|
@ -664,8 +707,8 @@ public class MusicService extends Service implements
|
|||
}
|
||||
|
||||
public void initNotification() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N &&
|
||||
!PreferenceUtil.INSTANCE.isClassicNotification()) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
|
||||
&& !PreferenceUtil.INSTANCE.isClassicNotification()) {
|
||||
playingNotification = new PlayingNotificationImpl();
|
||||
} else {
|
||||
playingNotification = new PlayingNotificationOreo();
|
||||
|
@ -725,7 +768,8 @@ public class MusicService extends Service implements
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(@NonNull SharedPreferences sharedPreferences, @NonNull String key) {
|
||||
public void onSharedPreferenceChanged(
|
||||
@NonNull SharedPreferences sharedPreferences, @NonNull String key) {
|
||||
switch (key) {
|
||||
case GAP_LESS_PLAYBACK:
|
||||
if (sharedPreferences.getBoolean(key, false)) {
|
||||
|
@ -817,10 +861,14 @@ public class MusicService extends Service implements
|
|||
return true;
|
||||
}
|
||||
|
||||
public void openQueue(@Nullable final List<Song> playingQueue, final int startPosition,
|
||||
final boolean startPlaying) {
|
||||
if (playingQueue != null && !playingQueue.isEmpty() && startPosition >= 0 && startPosition < playingQueue
|
||||
.size()) {
|
||||
public void openQueue(
|
||||
@Nullable final List<Song> playingQueue,
|
||||
final int startPosition,
|
||||
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
|
||||
originalPlayingQueue = new ArrayList<>(playingQueue);
|
||||
this.playingQueue = new ArrayList<>(originalPlayingQueue);
|
||||
|
@ -878,13 +926,15 @@ public class MusicService extends Service implements
|
|||
}
|
||||
notifyChange(PLAY_STATE_CHANGED);
|
||||
|
||||
// fixes a bug where the volume would stay ducked because the AudioManager.AUDIOFOCUS_GAIN event is not sent
|
||||
// fixes a bug where the volume would stay ducked because the
|
||||
// AudioManager.AUDIOFOCUS_GAIN event is not sent
|
||||
playerHandler.removeMessages(DUCK);
|
||||
playerHandler.sendEmptyMessage(UNDUCK);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(this, getResources().getString(R.string.audio_focus_denied), Toast.LENGTH_SHORT)
|
||||
Toast.makeText(
|
||||
this, getResources().getString(R.string.audio_focus_denied), Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
@ -908,7 +958,8 @@ public class MusicService extends Service implements
|
|||
if (openTrackAndPrepareNextAt(position)) {
|
||||
play();
|
||||
} else {
|
||||
Toast.makeText(this, getResources().getString(R.string.unplayable_file), Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(this, getResources().getString(R.string.unplayable_file), Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -988,12 +1039,15 @@ public class MusicService extends Service implements
|
|||
public synchronized void restoreQueuesAndPositionIfNecessary() {
|
||||
if (!queuesRestored && playingQueue.isEmpty()) {
|
||||
List<Song> restoredQueue = MusicPlaybackQueueStore.getInstance(this).getSavedPlayingQueue();
|
||||
List<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);
|
||||
List<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);
|
||||
|
||||
if (restoredQueue.size() > 0 && restoredQueue.size() == restoredOriginalQueue.size()
|
||||
if (restoredQueue.size() > 0
|
||||
&& restoredQueue.size() == restoredOriginalQueue.size()
|
||||
&& restoredPosition != -1) {
|
||||
this.originalPlayingQueue = restoredOriginalQueue;
|
||||
this.playingQueue = restoredQueue;
|
||||
|
@ -1019,8 +1073,10 @@ public class MusicService extends Service implements
|
|||
}
|
||||
|
||||
public void savePositionInTrack() {
|
||||
PreferenceManager.getDefaultSharedPreferences(this).edit()
|
||||
.putInt(SAVED_POSITION_IN_TRACK, getSongProgressMillis()).apply();
|
||||
PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.edit()
|
||||
.putInt(SAVED_POSITION_IN_TRACK, getSongProgressMillis())
|
||||
.apply();
|
||||
}
|
||||
|
||||
public void saveQueuesImpl() {
|
||||
|
@ -1076,10 +1132,13 @@ public class MusicService extends Service implements
|
|||
}
|
||||
|
||||
public void updateMediaSessionPlaybackState() {
|
||||
PlaybackStateCompat.Builder stateBuilder = new PlaybackStateCompat.Builder()
|
||||
.setActions(MEDIA_SESSION_ACTIONS)
|
||||
.setState(isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,
|
||||
getSongProgressMillis(), 1);
|
||||
PlaybackStateCompat.Builder stateBuilder =
|
||||
new PlaybackStateCompat.Builder()
|
||||
.setActions(MEDIA_SESSION_ACTIONS)
|
||||
.setState(
|
||||
isPlaying() ? PlaybackStateCompat.STATE_PLAYING : PlaybackStateCompat.STATE_PAUSED,
|
||||
getSongProgressMillis(),
|
||||
1);
|
||||
|
||||
setCustomAction(stateBuilder);
|
||||
|
||||
|
@ -1092,7 +1151,8 @@ public class MusicService extends Service implements
|
|||
}
|
||||
}
|
||||
|
||||
void updateMediaSessionMetaData() {
|
||||
public void updateMediaSessionMetaData() {
|
||||
Log.i(TAG, "onResourceReady: ");
|
||||
final Song song = getCurrentSong();
|
||||
|
||||
if (song.getId() == -1) {
|
||||
|
@ -1108,13 +1168,15 @@ public class MusicService extends Service implements
|
|||
.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, song.getDuration())
|
||||
.putLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER, getPosition() + 1)
|
||||
.putLong(MediaMetadataCompat.METADATA_KEY_YEAR, song.getYear())
|
||||
.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, null)
|
||||
.putLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS, getPlayingQueue().size());
|
||||
.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, null);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
metaData.putLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS, getPlayingQueue().size());
|
||||
}
|
||||
|
||||
if (PreferenceUtil.INSTANCE.isAlbumArtOnLockScreen()) {
|
||||
final Point screenSize = RetroUtil.getScreenSize(MusicService.this);
|
||||
final BitmapRequestBuilder<?, Bitmap> request = SongGlideRequest.Builder
|
||||
.from(Glide.with(MusicService.this), song)
|
||||
final BitmapRequestBuilder<?, Bitmap> request = SongGlideRequest.Builder.from(Glide.with(MusicService.this), song)
|
||||
.checkIgnoreMediaStore(MusicService.this)
|
||||
.asBitmap().build();
|
||||
if (PreferenceUtil.INSTANCE.isBlurredAlbumArt()) {
|
||||
|
@ -1132,6 +1194,7 @@ public class MusicService extends Service implements
|
|||
|
||||
@Override
|
||||
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
|
||||
|
||||
metaData.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, copy(resource));
|
||||
mediaSession.setMetadata(metaData.build());
|
||||
}
|
||||
|
@ -1144,7 +1207,8 @@ public class MusicService extends Service implements
|
|||
}
|
||||
|
||||
private void closeAudioEffectSession() {
|
||||
final Intent audioEffectsIntent = new Intent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
|
||||
final Intent audioEffectsIntent =
|
||||
new Intent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION);
|
||||
if (playback != null) {
|
||||
audioEffectsIntent.putExtra(AudioEffect.EXTRA_AUDIO_SESSION, playback.getAudioSessionId());
|
||||
}
|
||||
|
@ -1177,15 +1241,11 @@ public class MusicService extends Service implements
|
|||
savePosition();
|
||||
savePositionInTrack();
|
||||
final Song currentSong = getCurrentSong();
|
||||
if (currentSong != null) {
|
||||
HistoryStore.getInstance(this).addSongId(currentSong.getId());
|
||||
}
|
||||
HistoryStore.getInstance(this).addSongId(currentSong.getId());
|
||||
if (songPlayCountHelper.shouldBumpPlayCount()) {
|
||||
SongPlayCountStore.getInstance(this).bumpPlayCount(songPlayCountHelper.getSong().getId());
|
||||
}
|
||||
if (currentSong != null) {
|
||||
songPlayCountHelper.notifySongChanged(currentSong);
|
||||
}
|
||||
songPlayCountHelper.notifySongChanged(currentSong);
|
||||
break;
|
||||
case QUEUE_CHANGED:
|
||||
updateMediaSessionMetaData(); // because playing queue size might have changed
|
||||
|
@ -1213,10 +1273,10 @@ public class MusicService extends Service implements
|
|||
}
|
||||
|
||||
private void playFromPlaylist(Intent intent) {
|
||||
Playlist playlist = intent.getParcelableExtra(INTENT_EXTRA_PLAYLIST);
|
||||
AbsSmartPlaylist playlist = intent.getParcelableExtra(INTENT_EXTRA_PLAYLIST);
|
||||
int shuffleMode = intent.getIntExtra(INTENT_EXTRA_SHUFFLE_MODE, getShuffleMode());
|
||||
if (playlist != null) {
|
||||
List<Song> playlistSongs = playlist.getSongs();
|
||||
List<Song> playlistSongs = playlist.songs();
|
||||
if (!playlistSongs.isEmpty()) {
|
||||
if (shuffleMode == SHUFFLE_MODE_SHUFFLE) {
|
||||
int startPosition = new Random().nextInt(playlistSongs.size());
|
||||
|
@ -1226,7 +1286,8 @@ public class MusicService extends Service implements
|
|||
openQueue(playlistSongs, 0, true);
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(getApplicationContext(), R.string.playlist_is_empty, Toast.LENGTH_LONG).show();
|
||||
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();
|
||||
|
@ -1280,7 +1341,8 @@ public class MusicService extends Service implements
|
|||
|
||||
private boolean requestFocus() {
|
||||
return (getAudioManager()
|
||||
.requestAudioFocus(audioFocusListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN)
|
||||
.requestAudioFocus(
|
||||
audioFocusListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN)
|
||||
== AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
|
||||
}
|
||||
|
||||
|
@ -1295,7 +1357,10 @@ public class MusicService extends Service implements
|
|||
}
|
||||
|
||||
private void savePosition() {
|
||||
PreferenceManager.getDefaultSharedPreferences(this).edit().putInt(SAVED_POSITION, getPosition()).apply();
|
||||
PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.edit()
|
||||
.putInt(SAVED_POSITION, getPosition())
|
||||
.apply();
|
||||
}
|
||||
|
||||
private void saveQueues() {
|
||||
|
@ -1313,56 +1378,60 @@ public class MusicService extends Service implements
|
|||
}
|
||||
|
||||
private void setCustomAction(PlaybackStateCompat.Builder stateBuilder) {
|
||||
int repeatIcon = R.drawable.ic_repeat; // REPEAT_MODE_NONE
|
||||
int repeatIcon = R.drawable.ic_repeat; // REPEAT_MODE_NONE
|
||||
if (getRepeatMode() == REPEAT_MODE_THIS) {
|
||||
repeatIcon = R.drawable.ic_repeat_one;
|
||||
} else if (getRepeatMode() == REPEAT_MODE_ALL) {
|
||||
repeatIcon = R.drawable.ic_repeat_white_circle;
|
||||
}
|
||||
stateBuilder.addCustomAction(new PlaybackStateCompat.CustomAction.Builder(
|
||||
CYCLE_REPEAT, getString(R.string.action_cycle_repeat), repeatIcon)
|
||||
.build());
|
||||
stateBuilder.addCustomAction(
|
||||
new PlaybackStateCompat.CustomAction.Builder(
|
||||
CYCLE_REPEAT, getString(R.string.action_cycle_repeat), repeatIcon)
|
||||
.build());
|
||||
|
||||
final int shuffleIcon = getShuffleMode() == SHUFFLE_MODE_NONE ? R.drawable.ic_shuffle_off_circled
|
||||
: R.drawable.ic_shuffle_on_circled;
|
||||
stateBuilder.addCustomAction(new PlaybackStateCompat.CustomAction.Builder(
|
||||
TOGGLE_SHUFFLE, getString(R.string.action_toggle_shuffle), shuffleIcon)
|
||||
.build());
|
||||
final int shuffleIcon =
|
||||
getShuffleMode() == SHUFFLE_MODE_NONE
|
||||
? R.drawable.ic_shuffle_off_circled
|
||||
: R.drawable.ic_shuffle_on_circled;
|
||||
stateBuilder.addCustomAction(
|
||||
new PlaybackStateCompat.CustomAction.Builder(
|
||||
TOGGLE_SHUFFLE, getString(R.string.action_toggle_shuffle), shuffleIcon)
|
||||
.build());
|
||||
|
||||
final int favoriteIcon = MusicUtil.INSTANCE.isFavorite(getApplicationContext(), getCurrentSong())
|
||||
? R.drawable.ic_favorite : R.drawable.ic_favorite_border;
|
||||
stateBuilder.addCustomAction(new PlaybackStateCompat.CustomAction.Builder(
|
||||
TOGGLE_FAVORITE, getString(R.string.action_toggle_favorite), favoriteIcon)
|
||||
.build());
|
||||
final int favoriteIcon =
|
||||
MusicUtil.INSTANCE.isFavorite(getApplicationContext(), getCurrentSong())
|
||||
? R.drawable.ic_favorite
|
||||
: R.drawable.ic_favorite_border;
|
||||
stateBuilder.addCustomAction(
|
||||
new PlaybackStateCompat.CustomAction.Builder(
|
||||
TOGGLE_FAVORITE, getString(R.string.action_toggle_favorite), favoriteIcon)
|
||||
.build());
|
||||
}
|
||||
|
||||
private void setupMediaSession() {
|
||||
ComponentName mediaButtonReceiverComponentName = new ComponentName(
|
||||
getApplicationContext(),
|
||||
MediaButtonIntentReceiver.class);
|
||||
ComponentName mediaButtonReceiverComponentName =
|
||||
new ComponentName(getApplicationContext(), MediaButtonIntentReceiver.class);
|
||||
|
||||
Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
|
||||
mediaButtonIntent.setComponent(mediaButtonReceiverComponentName);
|
||||
|
||||
PendingIntent mediaButtonReceiverPendingIntent = PendingIntent.getBroadcast(
|
||||
getApplicationContext(),
|
||||
0,
|
||||
mediaButtonIntent,
|
||||
0);
|
||||
PendingIntent mediaButtonReceiverPendingIntent =
|
||||
PendingIntent.getBroadcast(getApplicationContext(), 0, mediaButtonIntent, 0);
|
||||
|
||||
mediaSession = new MediaSessionCompat(this,
|
||||
"Metro",
|
||||
mediaButtonReceiverComponentName,
|
||||
mediaButtonReceiverPendingIntent);
|
||||
MediaSessionCallback mediasessionCallback = new MediaSessionCallback(
|
||||
getApplicationContext(), this);
|
||||
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS
|
||||
| MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS
|
||||
);
|
||||
mediaSession =
|
||||
new MediaSessionCompat(
|
||||
this,
|
||||
"RetroMusicPlayer",
|
||||
mediaButtonReceiverComponentName,
|
||||
mediaButtonReceiverPendingIntent);
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
public class MusicBinder extends Binder {
|
||||
|
@ -1372,4 +1441,4 @@ public class MusicService extends Service implements
|
|||
return MusicService.this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,17 +14,6 @@
|
|||
|
||||
package io.github.muntashirakon.music.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 io.github.muntashirakon.music.util.PreferenceUtil;
|
||||
|
||||
import static io.github.muntashirakon.music.service.MusicService.DUCK;
|
||||
import static io.github.muntashirakon.music.service.MusicService.META_CHANGED;
|
||||
import static io.github.muntashirakon.music.service.MusicService.PLAY_STATE_CHANGED;
|
||||
|
@ -32,140 +21,148 @@ import static io.github.muntashirakon.music.service.MusicService.REPEAT_MODE_NON
|
|||
import static io.github.muntashirakon.music.service.MusicService.TRACK_ENDED;
|
||||
import static io.github.muntashirakon.music.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 io.github.muntashirakon.music.util.PreferenceUtil;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
class PlaybackHandler extends Handler {
|
||||
|
||||
@NonNull
|
||||
private final WeakReference<MusicService> mService;
|
||||
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);
|
||||
mService = new WeakReference<>(service);
|
||||
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;
|
||||
}
|
||||
|
||||
@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.INSTANCE.isAudioDucking()) {
|
||||
currentDuckVolume -= .05f;
|
||||
if (currentDuckVolume > .2f) {
|
||||
sendEmptyMessageDelayed(DUCK, 10);
|
||||
} else {
|
||||
currentDuckVolume = .2f;
|
||||
}
|
||||
} else {
|
||||
currentDuckVolume = 1f;
|
||||
}
|
||||
service.playback.setVolume(currentDuckVolume);
|
||||
break;
|
||||
|
||||
switch (msg.what) {
|
||||
case MusicService.DUCK:
|
||||
if (PreferenceUtil.INSTANCE.isAudioDucking()) {
|
||||
currentDuckVolume -= .05f;
|
||||
if (currentDuckVolume > .2f) {
|
||||
sendEmptyMessageDelayed(DUCK, 10);
|
||||
} else {
|
||||
currentDuckVolume = .2f;
|
||||
}
|
||||
} else {
|
||||
currentDuckVolume = 1f;
|
||||
}
|
||||
service.playback.setVolume(currentDuckVolume);
|
||||
break;
|
||||
|
||||
case MusicService.UNDUCK:
|
||||
if (PreferenceUtil.INSTANCE.isAudioDucking()) {
|
||||
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.pendingQuit || service.getRepeatMode() == REPEAT_MODE_NONE && service.isLastTrack()) {
|
||||
service.pause();
|
||||
service.seek(0);
|
||||
if (service.pendingQuit) {
|
||||
service.pendingQuit = false;
|
||||
service.quit();
|
||||
break;
|
||||
}
|
||||
} 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;
|
||||
case MusicService.UNDUCK:
|
||||
if (PreferenceUtil.INSTANCE.isAudioDucking()) {
|
||||
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.pendingQuit
|
||||
|| service.getRepeatMode() == REPEAT_MODE_NONE && service.isLastTrack()) {
|
||||
service.pause();
|
||||
service.seek(0);
|
||||
if (service.pendingQuit) {
|
||||
service.pendingQuit = false;
|
||||
service.quit();
|
||||
break;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ class PlayingNotificationImpl : PlayingNotification() {
|
|||
if (isFavorite) R.drawable.ic_favorite else R.drawable.ic_favorite_border
|
||||
|
||||
val action = Intent(service, MainActivity::class.java)
|
||||
action.putExtra(MainActivity.EXPAND_PANEL, true)
|
||||
action.putExtra(MainActivity.EXPAND_PANEL, PreferenceUtil.isExpandPanel)
|
||||
action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
val clickIntent =
|
||||
PendingIntent.getActivity(service, 0, action, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
|
|
|
@ -73,7 +73,7 @@ class PlayingNotificationOreo : PlayingNotification() {
|
|||
val notificationLayoutBig = getCombinedRemoteViews(false, song)
|
||||
|
||||
val action = Intent(service, MainActivity::class.java)
|
||||
action.putExtra(MainActivity.EXPAND_PANEL, true)
|
||||
action.putExtra(MainActivity.EXPAND_PANEL, PreferenceUtil.isExpandPanel)
|
||||
action.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
|
||||
val clickIntent = PendingIntent
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue