diff options
18 files changed, 237 insertions, 183 deletions
diff --git a/ServerProxy b/ServerProxy -Subproject 5b318194f533e4dc121572ccc71261fe99d060d +Subproject 08f66ee2da9aa39ae569c8ed2a2ad02f141e971 diff --git a/app/build.gradle b/app/build.gradle index e9bd19e5..a87ba2b1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,14 +2,13 @@ apply plugin: 'com.android.application' android { compileSdkVersion 27 - buildToolsVersion '25.0.0' defaultConfig { applicationId "github.daneren2005.dsub" minSdkVersion 14 targetSdkVersion 26 - versionCode 200 - versionName '5.4.3' + versionCode 202 + versionName '5.4.4' setProperty("archivesBaseName", "DSub $versionName") resConfigs "de", "es", "fr", "hu", "nl", "pt-rPT", "ru", "sv" } @@ -27,14 +26,16 @@ android { zipAlignEnabled true } } - + flavorDimensions "version" productFlavors { floss { // FLOSS build (no proprietary libraries) + dimension "version" } google { // FLOSS build + Google libraries // Adds ChromeCast support + dimension "version" } } @@ -54,20 +55,20 @@ android { } dependencies { - compile project(':Server Proxy') - compile fileTree(include: ['*.jar'], dir: 'libs') - compile 'com.android.support:support-v4:27.1.+' - compile 'com.android.support:appcompat-v7:27.1.+' - compile 'com.android.support:mediarouter-v7:27.1.+' - compile 'com.android.support:recyclerview-v7:27.1.+' - compile 'com.android.support:design:27.1.+' - googleCompile 'com.google.android.gms:play-services-cast:8.1.0' - compile 'com.sothree.slidinguppanel:library:3.0.0' - compile 'de.hdodenhof:circleimageview:1.2.1' - compile 'com.shehabic.droppy:Droppy:0.5.1@aar' - compile group: 'org.fourthline.cling', name: 'cling-core', version:'2.1.1' - compile group: 'org.fourthline.cling', name: 'cling-support', version:'2.1.1' - compile group: 'org.eclipse.jetty', name: 'jetty-server', version:'8.1.16.v20140903' - compile group: 'org.eclipse.jetty', name: 'jetty-servlet', version:'8.1.16.v20140903' - compile group: 'org.eclipse.jetty', name: 'jetty-client', version:'8.1.16.v20140903' + implementation project(path: ':ServerProxy') + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation 'com.android.support:support-v4:27.1.+' + implementation 'com.android.support:appcompat-v7:27.1.+' + implementation 'com.android.support:mediarouter-v7:27.1.+' + implementation 'com.android.support:recyclerview-v7:27.1.+' + implementation 'com.android.support:design:27.1.+' + googleImplementation 'com.google.android.gms:play-services-cast:8.1.0' + implementation 'com.sothree.slidinguppanel:library:3.0.0' + implementation 'de.hdodenhof:circleimageview:1.2.1' + implementation 'com.shehabic.droppy:Droppy:0.5.1@aar' + implementation group: 'org.fourthline.cling', name: 'cling-core', version:'2.1.1' + implementation group: 'org.fourthline.cling', name: 'cling-support', version:'2.1.1' + implementation group: 'org.eclipse.jetty', name: 'jetty-server', version:'8.1.16.v20140903' + implementation group: 'org.eclipse.jetty', name: 'jetty-servlet', version:'8.1.16.v20140903' + implementation group: 'org.eclipse.jetty', name: 'jetty-client', version:'8.1.16.v20140903' } diff --git a/app/src/androidTest/java/github/daneren2005/dsub/domain/GenreComparatorTest.java b/app/src/androidTest/java/github/daneren2005/dsub/domain/GenreComparatorTest.java index 9ffa518e..16d189fa 100644 --- a/app/src/androidTest/java/github/daneren2005/dsub/domain/GenreComparatorTest.java +++ b/app/src/androidTest/java/github/daneren2005/dsub/domain/GenreComparatorTest.java @@ -16,7 +16,7 @@ public class GenreComparatorTest extends TestCase { Genre g2 = new Genre(); - List<Genre> genres = new ArrayList<Genre>(); + List<Genre> genres = new ArrayList<>(); genres.add(g1); genres.add(g2); @@ -34,7 +34,7 @@ public class GenreComparatorTest extends TestCase { Genre g2 = new Genre(); g2.setName("genre"); - List<Genre> genres = new ArrayList<Genre>(); + List<Genre> genres = new ArrayList<>(); genres.add(g1); genres.add(g2); @@ -53,9 +53,9 @@ public class GenreComparatorTest extends TestCase { g2.setName("Pop"); Genre g3 = new Genre(); - g2.setName("Rap"); + g3.setName("Rap"); - List<Genre> genres = new ArrayList<Genre>(); + List<Genre> genres = new ArrayList<>(); genres.add(g1); genres.add(g2); genres.add(g3); diff --git a/app/src/androidTest/java/github/daneren2005/dsub/service/DownloadServiceTest.java b/app/src/androidTest/java/github/daneren2005/dsub/service/DownloadServiceTest.java index 44b77b84..2e10b977 100644 --- a/app/src/androidTest/java/github/daneren2005/dsub/service/DownloadServiceTest.java +++ b/app/src/androidTest/java/github/daneren2005/dsub/service/DownloadServiceTest.java @@ -49,6 +49,20 @@ public class DownloadServiceTest extends assertEquals(0, position); } + public void testGetRecentDownloadsWithoutPlaylist() { + int output_length = downloadService.getRecentDownloads().size(); + assertEquals(0, output_length); + } + + public void testGetRecentDownloadsWithPlaylist() { + downloadService.getDownloads().clear(); + downloadService.download(this.createMusicSongs(2), false, false, false, + false, 0, 0); + + int output_length = downloadService.getRecentDownloads().size(); + assertEquals(1, output_length); + } + public void testGetCurrentPlayingIndexWithoutPlayList() { int currentPlayingIndex = activity.getDownloadService() .getCurrentPlayingIndex(); @@ -118,6 +132,7 @@ public class DownloadServiceTest extends // Do a next before the previous downloadService.next(); + downloadService.setPlayerState(STARTED); // Do the previous downloadService.previous(); diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index cfc70a55..52756534 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -166,12 +166,6 @@ </intent-filter> </receiver> - <receiver android:name="github.daneren2005.dsub.receiver.AudioNoisyReceiver"> - <intent-filter android:priority="999"> - <action android:name="android.media.AUDIO_BECOMING_NOISY" /> - </intent-filter> - </receiver> - <receiver android:name="github.daneren2005.dsub.receiver.A2dpIntentReceiver"> <intent-filter> <action android:name="android.music.playstatusrequest"/> diff --git a/app/src/main/java/github/daneren2005/dsub/domain/Genre.java b/app/src/main/java/github/daneren2005/dsub/domain/Genre.java index 4b6ac344..dcf12a1d 100644 --- a/app/src/main/java/github/daneren2005/dsub/domain/Genre.java +++ b/app/src/main/java/github/daneren2005/dsub/domain/Genre.java @@ -1,16 +1,10 @@ package github.daneren2005.dsub.domain; -import android.content.Context; -import android.content.SharedPreferences; - import java.io.Serializable; import java.util.Collections; import java.util.Comparator; import java.util.List; -import github.daneren2005.dsub.util.Constants; -import github.daneren2005.dsub.util.Util; - public class Genre implements Serializable { private String name; private String index; @@ -57,7 +51,10 @@ public class Genre implements Serializable { public static class GenreComparator implements Comparator<Genre> { @Override public int compare(Genre genre1, Genre genre2) { - return genre1.getName().compareToIgnoreCase(genre2.getName()); + String genre1Name = genre1.getName() != null ? genre1.getName() : ""; + String genre2Name = genre2.getName() != null ? genre2.getName() : ""; + + return genre1Name.compareToIgnoreCase(genre2Name); } public static List<Genre> sort(List<Genre> genres) { diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SettingsFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SettingsFragment.java index 94c9b7fc..f7031146 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SettingsFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SettingsFragment.java @@ -24,6 +24,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.EditTextPreference; @@ -109,6 +110,14 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared public void onCreate(Bundle bundle) { super.onCreate(bundle); + if(Build.VERSION.SDK_INT >= 21) { + CheckBoxPreference mediaButtons = (CheckBoxPreference) findPreference("mediaButtons"); + if (mediaButtons != null) { + PreferenceCategory otherCategory = (PreferenceCategory) findPreference("otherSettings"); + otherCategory.removePreference(mediaButtons); + } + } + int instance = this.getArguments().getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, -1); if (instance != -1) { PreferenceScreen preferenceScreen = expandServer(instance); diff --git a/app/src/main/java/github/daneren2005/dsub/service/AutoMediaBrowserService.java b/app/src/main/java/github/daneren2005/dsub/service/AutoMediaBrowserService.java index e4edabc4..b0f0f399 100644 --- a/app/src/main/java/github/daneren2005/dsub/service/AutoMediaBrowserService.java +++ b/app/src/main/java/github/daneren2005/dsub/service/AutoMediaBrowserService.java @@ -19,15 +19,13 @@ package github.daneren2005.dsub.service; import android.annotation.TargetApi; -import android.content.Intent; -import android.media.MediaDescription; -import android.media.MediaMetadata; -import android.media.browse.MediaBrowser; import android.os.Build; import android.os.Bundle; import android.os.Handler; -import android.service.media.MediaBrowserService; import android.support.annotation.Nullable; +import android.support.v4.media.MediaBrowserCompat; +import android.support.v4.media.MediaBrowserServiceCompat; +import android.support.v4.media.MediaDescriptionCompat; import android.util.Log; import java.io.IOException; @@ -43,15 +41,13 @@ import github.daneren2005.dsub.domain.MusicFolder; import github.daneren2005.dsub.domain.Playlist; import github.daneren2005.dsub.domain.PodcastChannel; import github.daneren2005.dsub.domain.PodcastEpisode; -import github.daneren2005.dsub.domain.ServerInfo; import github.daneren2005.dsub.util.Constants; -import github.daneren2005.dsub.util.SilentBackgroundTask; import github.daneren2005.dsub.util.SilentServiceTask; import github.daneren2005.dsub.util.Util; import github.daneren2005.dsub.util.compat.RemoteControlClientLP; @TargetApi(Build.VERSION_CODES.LOLLIPOP) -public class AutoMediaBrowserService extends MediaBrowserService { +public class AutoMediaBrowserService extends MediaBrowserServiceCompat { private static final String TAG = AutoMediaBrowserService.class.getSimpleName(); private static final String BROWSER_ROOT = "root"; private static final String BROWSER_ALBUM_LISTS = "albumLists"; @@ -83,7 +79,7 @@ public class AutoMediaBrowserService extends MediaBrowserService { } @Override - public void onLoadChildren(String parentId, Result<List<MediaBrowser.MediaItem>> result) { + public void onLoadChildren(String parentId, Result<List<MediaBrowserCompat.MediaItem>> result) { if(BROWSER_ROOT.equals(parentId)) { getRootFolders(result); } else if(BROWSER_ALBUM_LISTS.equals(parentId)) { @@ -116,46 +112,46 @@ public class AutoMediaBrowserService extends MediaBrowserService { getBookmarks(result); } else { // No idea what it is, send empty result - result.sendResult(new ArrayList<MediaBrowser.MediaItem>()); + result.sendResult(new ArrayList<MediaBrowserCompat.MediaItem>()); } } - private void getRootFolders(Result<List<MediaBrowser.MediaItem>> result) { - List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>(); + private void getRootFolders(Result<List<MediaBrowserCompat.MediaItem>> result) { + List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>(); - MediaDescription.Builder albumLists = new MediaDescription.Builder(); + MediaDescriptionCompat.Builder albumLists = new MediaDescriptionCompat.Builder(); albumLists.setTitle(downloadService.getString(R.string.main_albums_title)) .setMediaId(BROWSER_ALBUM_LISTS); - mediaItems.add(new MediaBrowser.MediaItem(albumLists.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(albumLists.build(), MediaBrowserCompat.MediaItem.FLAG_BROWSABLE)); - MediaDescription.Builder library = new MediaDescription.Builder(); + MediaDescriptionCompat.Builder library = new MediaDescriptionCompat.Builder(); library.setTitle(downloadService.getString(R.string.button_bar_browse)) .setMediaId(BROWSER_LIBRARY); - mediaItems.add(new MediaBrowser.MediaItem(library.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(library.build(), MediaBrowserCompat.MediaItem.FLAG_BROWSABLE)); - MediaDescription.Builder playlists = new MediaDescription.Builder(); + MediaDescriptionCompat.Builder playlists = new MediaDescriptionCompat.Builder(); playlists.setTitle(downloadService.getString(R.string.button_bar_playlists)) .setMediaId(BROWSER_PLAYLISTS); - mediaItems.add(new MediaBrowser.MediaItem(playlists.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(playlists.build(), MediaBrowserCompat.MediaItem.FLAG_BROWSABLE)); if(Util.getPreferences(downloadService).getBoolean(Constants.PREFERENCES_KEY_PODCASTS_ENABLED, true)) { - MediaDescription.Builder podcasts = new MediaDescription.Builder(); + MediaDescriptionCompat.Builder podcasts = new MediaDescriptionCompat.Builder(); podcasts.setTitle(downloadService.getString(R.string.button_bar_podcasts)) .setMediaId(BROWSER_PODCASTS); - mediaItems.add(new MediaBrowser.MediaItem(podcasts.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(podcasts.build(), MediaBrowserCompat.MediaItem.FLAG_BROWSABLE)); } if(Util.getPreferences(downloadService).getBoolean(Constants.PREFERENCES_KEY_BOOKMARKS_ENABLED, true)) { - MediaDescription.Builder podcasts = new MediaDescription.Builder(); + MediaDescriptionCompat.Builder podcasts = new MediaDescriptionCompat.Builder(); podcasts.setTitle(downloadService.getString(R.string.button_bar_bookmarks)) .setMediaId(BROWSER_BOOKMARKS); - mediaItems.add(new MediaBrowser.MediaItem(podcasts.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(podcasts.build(), MediaBrowserCompat.MediaItem.FLAG_BROWSABLE)); } result.sendResult(mediaItems); } - private void getAlbumLists(Result<List<MediaBrowser.MediaItem>> result) { + private void getAlbumLists(Result<List<MediaBrowserCompat.MediaItem>> result) { List<Integer> albums = new ArrayList<>(); albums.add(R.string.main_albums_newest); albums.add(R.string.main_albums_random); @@ -166,20 +162,20 @@ public class AutoMediaBrowserService extends MediaBrowserService { albums.add(R.string.main_albums_recent); albums.add(R.string.main_albums_frequent); - List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>(); + List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>(); for(Integer id: albums) { - MediaDescription description = new MediaDescription.Builder() + MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setTitle(downloadService.getResources().getString(id)) .setMediaId(ALBUM_TYPE_PREFIX + id) .build(); - mediaItems.add(new MediaBrowser.MediaItem(description, MediaBrowser.MediaItem.FLAG_BROWSABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(description, MediaBrowserCompat.MediaItem.FLAG_BROWSABLE)); } result.sendResult(mediaItems); } - private void getAlbumList(final Result<List<MediaBrowser.MediaItem>> result, final int id) { + private void getAlbumList(final Result<List<MediaBrowserCompat.MediaItem>> result, final int id) { new SilentServiceTask<MusicDirectory>(downloadService) { @Override protected MusicDirectory doInBackground(MusicService musicService) throws Throwable { @@ -212,16 +208,16 @@ public class AutoMediaBrowserService extends MediaBrowserService { @Override protected void done(MusicDirectory albumSet) { - List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>(); + List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>(); for(Entry album: albumSet.getChildren(true, false)) { - MediaDescription description = new MediaDescription.Builder() + MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setTitle(album.getAlbumDisplay()) .setSubtitle(album.getArtist()) .setMediaId(MUSIC_DIRECTORY_PREFIX + album.getId()) .build(); - mediaItems.add(new MediaBrowser.MediaItem(description, MediaBrowser.MediaItem.FLAG_BROWSABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(description, MediaBrowserCompat.MediaItem.FLAG_BROWSABLE)); } result.sendResult(mediaItems); @@ -231,7 +227,7 @@ public class AutoMediaBrowserService extends MediaBrowserService { result.detach(); } - private void getLibrary(final Result<List<MediaBrowser.MediaItem>> result) { + private void getLibrary(final Result<List<MediaBrowserCompat.MediaItem>> result) { new SilentServiceTask<List<MusicFolder>>(downloadService) { @Override protected List<MusicFolder> doInBackground(MusicService musicService) throws Throwable { @@ -240,15 +236,15 @@ public class AutoMediaBrowserService extends MediaBrowserService { @Override protected void done(List<MusicFolder> folders) { - List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>(); + List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>(); for(MusicFolder folder: folders) { - MediaDescription description = new MediaDescription.Builder() + MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setTitle(folder.getName()) .setMediaId(MUSIC_FOLDER_PREFIX + folder.getId()) .build(); - mediaItems.add(new MediaBrowser.MediaItem(description, MediaBrowser.MediaItem.FLAG_BROWSABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(description, MediaBrowserCompat.MediaItem.FLAG_BROWSABLE)); } result.sendResult(mediaItems); @@ -257,7 +253,7 @@ public class AutoMediaBrowserService extends MediaBrowserService { result.detach(); } - private void getIndexes(final Result<List<MediaBrowser.MediaItem>> result, final String musicFolderId) { + private void getIndexes(final Result<List<MediaBrowserCompat.MediaItem>> result, final String musicFolderId) { new SilentServiceTask<Indexes>(downloadService) { @Override protected Indexes doInBackground(MusicService musicService) throws Throwable { @@ -266,16 +262,16 @@ public class AutoMediaBrowserService extends MediaBrowserService { @Override protected void done(Indexes indexes) { - List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>(); + List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>(); // music directories for(Artist artist : indexes.getArtists()) { - MediaDescription description = new MediaDescription.Builder() + MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setTitle(artist.getName()) .setMediaId(MUSIC_DIRECTORY_CONTENTS_PREFIX + artist.getId()) .build(); - mediaItems.add(new MediaBrowser.MediaItem(description, MediaBrowser.MediaItem.FLAG_BROWSABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(description, MediaBrowserCompat.MediaItem.FLAG_BROWSABLE)); } // music files @@ -286,13 +282,13 @@ public class AutoMediaBrowserService extends MediaBrowserService { extras.putByteArray(Constants.INTENT_EXTRA_ENTRY_BYTES, entry.toByteArray()); extras.putString(Constants.INTENT_EXTRA_NAME_CHILD_ID, entry.getId()); - MediaDescription description = new MediaDescription.Builder() + MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setTitle(entry.getTitle()) .setMediaId(entry.getId()) .setExtras(extras) .build(); - mediaItems.add(new MediaBrowser.MediaItem(description, MediaBrowser.MediaItem.FLAG_PLAYABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(description, MediaBrowserCompat.MediaItem.FLAG_PLAYABLE)); } catch(IOException e) { Log.e(TAG, "Failed to add entry", e); } @@ -305,7 +301,7 @@ public class AutoMediaBrowserService extends MediaBrowserService { result.detach(); } - private void getMusicDirectory(final Result<List<MediaBrowser.MediaItem>> result, final String musicDirectoryId) { + private void getMusicDirectory(final Result<List<MediaBrowserCompat.MediaItem>> result, final String musicDirectoryId) { new SilentServiceTask<MusicDirectory>(downloadService) { @Override protected MusicDirectory doInBackground(MusicService musicService) throws Throwable { @@ -314,20 +310,20 @@ public class AutoMediaBrowserService extends MediaBrowserService { @Override protected void done(MusicDirectory directory) { - List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>(); + List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>(); addPlayOptions(mediaItems, musicDirectoryId, Constants.INTENT_EXTRA_NAME_ID); for(Entry entry : directory.getChildren()) { - MediaDescription description; + MediaDescriptionCompat description; if (entry.isDirectory()) { // browse deeper - description = new MediaDescription.Builder() + description = new MediaDescriptionCompat.Builder() .setTitle(entry.getTitle()) .setMediaId(MUSIC_DIRECTORY_CONTENTS_PREFIX + entry.getId()) .build(); - mediaItems.add(new MediaBrowser.MediaItem(description, MediaBrowser.MediaItem.FLAG_BROWSABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(description, MediaBrowserCompat.MediaItem.FLAG_BROWSABLE)); } else { try { // mark individual songs as directly playable @@ -336,13 +332,13 @@ public class AutoMediaBrowserService extends MediaBrowserService { extras.putByteArray(Constants.INTENT_EXTRA_ENTRY_BYTES, entry.toByteArray()); extras.putString(Constants.INTENT_EXTRA_NAME_CHILD_ID, entry.getId()); - description = new MediaDescription.Builder() + description = new MediaDescriptionCompat.Builder() .setTitle(entry.getTitle()) .setMediaId(entry.getId()) .setExtras(extras) .build(); - mediaItems.add(new MediaBrowser.MediaItem(description, MediaBrowser.MediaItem.FLAG_PLAYABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(description, MediaBrowserCompat.MediaItem.FLAG_PLAYABLE)); } catch (IOException e) { Log.e(TAG, "Failed to add entry", e); } @@ -355,7 +351,7 @@ public class AutoMediaBrowserService extends MediaBrowserService { result.detach(); } - private void getPlaylists(final Result<List<MediaBrowser.MediaItem>> result) { + private void getPlaylists(final Result<List<MediaBrowserCompat.MediaItem>> result) { new SilentServiceTask<List<Playlist>>(downloadService) { @Override protected List<Playlist> doInBackground(MusicService musicService) throws Throwable { @@ -364,15 +360,15 @@ public class AutoMediaBrowserService extends MediaBrowserService { @Override protected void done(List<Playlist> playlists) { - List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>(); + List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>(); for(Playlist playlist: playlists) { - MediaDescription description = new MediaDescription.Builder() + MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setTitle(playlist.getName()) .setMediaId(PLAYLIST_PREFIX + playlist.getId()) .build(); - mediaItems.add(new MediaBrowser.MediaItem(description, MediaBrowser.MediaItem.FLAG_BROWSABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(description, MediaBrowserCompat.MediaItem.FLAG_BROWSABLE)); } result.sendResult(mediaItems); @@ -382,7 +378,7 @@ public class AutoMediaBrowserService extends MediaBrowserService { result.detach(); } - private void getPodcasts(final Result<List<MediaBrowser.MediaItem>> result) { + private void getPodcasts(final Result<List<MediaBrowserCompat.MediaItem>> result) { new SilentServiceTask<List<PodcastChannel>>(downloadService) { @Override protected List<PodcastChannel> doInBackground(MusicService musicService) throws Throwable { @@ -391,15 +387,15 @@ public class AutoMediaBrowserService extends MediaBrowserService { @Override protected void done(List<PodcastChannel> podcasts) { - List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>(); + List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>(); for(PodcastChannel podcast: podcasts) { - MediaDescription description = new MediaDescription.Builder() + MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setTitle(podcast.getName()) .setMediaId(PODCAST_PREFIX + podcast.getId()) .build(); - mediaItems.add(new MediaBrowser.MediaItem(description, MediaBrowser.MediaItem.FLAG_BROWSABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(description, MediaBrowserCompat.MediaItem.FLAG_BROWSABLE)); } result.sendResult(mediaItems); @@ -408,7 +404,7 @@ public class AutoMediaBrowserService extends MediaBrowserService { result.detach(); } - private void getPodcastEpisodes(final Result<List<MediaBrowser.MediaItem>> result, final String podcastId) { + private void getPodcastEpisodes(final Result<List<MediaBrowserCompat.MediaItem>> result, final String podcastId) { new SilentServiceTask<MusicDirectory>(downloadService) { @Override protected MusicDirectory doInBackground(MusicService musicService) throws Throwable { @@ -417,7 +413,7 @@ public class AutoMediaBrowserService extends MediaBrowserService { @Override protected void done(MusicDirectory podcasts) { - List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>(); + List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>(); for(Entry entry: podcasts.getChildren(false, true)) { try { @@ -426,14 +422,14 @@ public class AutoMediaBrowserService extends MediaBrowserService { podcastExtras.putByteArray(Constants.INTENT_EXTRA_ENTRY_BYTES, podcast.toByteArray()); podcastExtras.putString(Constants.INTENT_EXTRA_NAME_PODCAST_ID, podcast.getId()); - MediaDescription description = new MediaDescription.Builder() + MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setTitle(podcast.getTitle()) .setSubtitle(Util.formatDate(downloadService, podcast.getDate(), false)) .setMediaId(PODCAST_PREFIX + podcast.getId()) .setExtras(podcastExtras) .build(); - mediaItems.add(new MediaBrowser.MediaItem(description, MediaBrowser.MediaItem.FLAG_PLAYABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(description, MediaBrowserCompat.MediaItem.FLAG_PLAYABLE)); } catch(IOException e) { Log.e(TAG, "Failed to add podcast", e); } @@ -446,7 +442,7 @@ public class AutoMediaBrowserService extends MediaBrowserService { result.detach(); } - private void getBookmarks(final Result<List<MediaBrowser.MediaItem>> result) { + private void getBookmarks(final Result<List<MediaBrowserCompat.MediaItem>> result) { new SilentServiceTask<MusicDirectory>(downloadService) { @Override protected MusicDirectory doInBackground(MusicService musicService) throws Throwable { @@ -455,7 +451,7 @@ public class AutoMediaBrowserService extends MediaBrowserService { @Override protected void done(MusicDirectory bookmarkList) { - List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>(); + List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>(); for(Entry entry: bookmarkList.getChildren(false, true)) { try { @@ -463,14 +459,14 @@ public class AutoMediaBrowserService extends MediaBrowserService { extras.putByteArray(Constants.INTENT_EXTRA_ENTRY_BYTES, entry.toByteArray()); extras.putString(Constants.INTENT_EXTRA_NAME_CHILD_ID, entry.getId()); - MediaDescription description = new MediaDescription.Builder() + MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setTitle(entry.getTitle()) .setSubtitle(Util.formatDuration(entry.getBookmark().getPosition() / 1000)) .setMediaId(entry.getId()) .setExtras(extras) .build(); - mediaItems.add(new MediaBrowser.MediaItem(description, MediaBrowser.MediaItem.FLAG_PLAYABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(description, MediaBrowserCompat.MediaItem.FLAG_PLAYABLE)); } catch(IOException e) { Log.e(TAG, "Failed to add entry", e); } @@ -483,39 +479,39 @@ public class AutoMediaBrowserService extends MediaBrowserService { result.detach(); } - private void addPlayOptions(List<MediaBrowser.MediaItem> mediaItems, String id, String idConstant) { + private void addPlayOptions(List<MediaBrowserCompat.MediaItem> mediaItems, String id, String idConstant) { Bundle playAllExtras = new Bundle(); playAllExtras.putString(idConstant, id); - MediaDescription.Builder playAll = new MediaDescription.Builder(); + MediaDescriptionCompat.Builder playAll = new MediaDescriptionCompat.Builder(); playAll.setTitle(downloadService.getString(R.string.menu_play)) .setMediaId("play-" + id) .setExtras(playAllExtras); - mediaItems.add(new MediaBrowser.MediaItem(playAll.build(), MediaBrowser.MediaItem.FLAG_PLAYABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(playAll.build(), MediaBrowserCompat.MediaItem.FLAG_PLAYABLE)); Bundle shuffleExtras = new Bundle(); shuffleExtras.putString(idConstant, id); shuffleExtras.putBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE, true); - MediaDescription.Builder shuffle = new MediaDescription.Builder(); + MediaDescriptionCompat.Builder shuffle = new MediaDescriptionCompat.Builder(); shuffle.setTitle(downloadService.getString(R.string.menu_shuffle)) .setMediaId("shuffle-" + id) .setExtras(shuffleExtras); - mediaItems.add(new MediaBrowser.MediaItem(shuffle.build(), MediaBrowser.MediaItem.FLAG_PLAYABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(shuffle.build(), MediaBrowserCompat.MediaItem.FLAG_PLAYABLE)); Bundle playLastExtras = new Bundle(); playLastExtras.putString(idConstant, id); playLastExtras.putBoolean(Constants.INTENT_EXTRA_PLAY_LAST, true); - MediaDescription.Builder playLast = new MediaDescription.Builder(); + MediaDescriptionCompat.Builder playLast = new MediaDescriptionCompat.Builder(); playLast.setTitle(downloadService.getString(R.string.menu_play_last)) .setMediaId("playLast-" + id) .setExtras(playLastExtras); - mediaItems.add(new MediaBrowser.MediaItem(playLast.build(), MediaBrowser.MediaItem.FLAG_PLAYABLE)); + mediaItems.add(new MediaBrowserCompat.MediaItem(playLast.build(), MediaBrowserCompat.MediaItem.FLAG_PLAYABLE)); } - private void getPlayOptions(Result<List<MediaBrowser.MediaItem>> result, String id, String idConstant) { - List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>(); + private void getPlayOptions(Result<List<MediaBrowserCompat.MediaItem>> result, String id, String idConstant) { + List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>(); addPlayOptions(mediaItems, id, idConstant); diff --git a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java index 6c3cfbd7..e9096900 100644 --- a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java +++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java @@ -42,6 +42,7 @@ import github.daneren2005.dsub.domain.PodcastEpisode; import github.daneren2005.dsub.domain.RemoteControlState; import github.daneren2005.dsub.domain.RepeatMode; import github.daneren2005.dsub.domain.ServerInfo; +import github.daneren2005.dsub.receiver.AudioNoisyReceiver; import github.daneren2005.dsub.receiver.MediaButtonIntentReceiver; import github.daneren2005.dsub.util.ArtistRadioBuffer; import github.daneren2005.dsub.util.ImageLoader; @@ -77,6 +78,7 @@ import android.content.ComponentCallbacks2; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.SharedPreferences; import android.media.AudioManager; import android.media.MediaPlayer; @@ -168,6 +170,7 @@ public class DownloadService extends Service { private boolean downloadOngoing = false; private float volume = 1.0f; private long delayUpdateProgress = DEFAULT_DELAY_UPDATE_PROGRESS; + private boolean foregroundService = false; private AudioEffectsController effectsController; private RemoteControlState remoteState = LOCAL; @@ -180,6 +183,9 @@ public class DownloadService extends Service { private boolean autoPlayStart = false; private boolean runListenersOnInit = false; + private IntentFilter audioNoisyIntent = new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY); + private AudioNoisyReceiver audioNoisyReceiver = null; + private MediaRouteManager mediaRouter; // Variables to manage getCurrentPosition sometimes starting from an arbitrary non-zero number @@ -262,6 +268,8 @@ public class DownloadService extends Service { }, "DownloadService").start(); Util.registerMediaButtonEventReceiver(this); + audioNoisyReceiver = new AudioNoisyReceiver(); + registerReceiver(audioNoisyReceiver, audioNoisyIntent); if (mRemoteControl == null) { // Use the remote control APIs (if available) to set the playback state @@ -302,6 +310,9 @@ public class DownloadService extends Service { public int onStartCommand(Intent intent, int flags, int startId) { super.onStartCommand(intent, flags, startId); lifecycleSupport.onStart(intent); + if(Build.VERSION.SDK_INT >= 26 && !this.isForeground()) { + Notifications.shutGoogleUpNotification(this); + } return START_NOT_STICKY; } @@ -375,6 +386,9 @@ public class DownloadService extends Service { proxy.stop(); proxy = null; } + if (audioNoisyReceiver != null) { + unregisterReceiver(audioNoisyReceiver); + } mediaRouter.destroy(); Notifications.hidePlayingNotification(this, this, handler); Notifications.hideDownloadingNotification(this, this, handler); @@ -1050,6 +1064,14 @@ public class DownloadService extends Service { return size() == 1 || (currentPlaying != null && !currentPlaying.isSong()); } + public synchronized boolean isForeground() { + return this.foregroundService; + } + + public synchronized void setIsForeground(boolean foreground) { + this.foregroundService = foreground; + } + public synchronized List<DownloadFile> getDownloads() { List<DownloadFile> temp = new ArrayList<DownloadFile>(); temp.addAll(downloadList); @@ -1060,7 +1082,7 @@ public class DownloadService extends Service { public synchronized List<DownloadFile> getRecentDownloads() { int from = Math.max(currentPlayingIndex - 10, 0); int songsToKeep = Math.max(Util.getPreloadCount(this), 20); - int to = Math.min(currentPlayingIndex + songsToKeep, downloadList.size() - 1); + int to = Math.min(currentPlayingIndex + songsToKeep, Math.max(downloadList.size() - 1, 0)); List<DownloadFile> temp = downloadList.subList(from, to); temp.addAll(backgroundDownloadList); return temp; @@ -1493,7 +1515,8 @@ public class DownloadService extends Service { this.playerState = playerState; if(playerState == STARTED) { - Util.requestAudioFocus(this); + AudioManager audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE); + Util.requestAudioFocus(this, audioManager); } if (show) { @@ -2783,14 +2806,16 @@ public class DownloadService extends Service { } public void setRating(int rating) { final DownloadFile currentPlaying = this.currentPlaying; - if(currentPlaying == null) { + if (currentPlaying == null) { return; } MusicDirectory.Entry entry = currentPlaying.getSong(); // Immediately skip to the next song if down thumbed - if(rating == 1) { + if (rating == 1 && size() > 1) { next(true); + } else if (rating == 1 && size() == 1) { + stop(); } UpdateHelper.setRating(this, entry, rating, new UpdateHelper.OnRatingChange() { diff --git a/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java b/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java index 2321e69e..23f48e02 100644 --- a/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java +++ b/app/src/main/java/github/daneren2005/dsub/util/ImageLoader.java @@ -640,7 +640,7 @@ public class ImageLoader { private final ImageView mView; private Drawable mDrawable; - public AvatarTask(Context context, ImageView view, String username) { + private AvatarTask(Context context, ImageView view, String username) { super(context); mContext = context; mView = view; @@ -659,8 +659,10 @@ public class ImageLoader { mDrawable = Util.createDrawableFromBitmap(mContext, bitmap); } + } catch (java.io.FileNotFoundException x) { + Log.i(TAG, "Avatar not available for download."); } catch (Throwable x) { - Log.e(TAG, "Failed to download album art.", x); + Log.e(TAG, "Failed to download avatar.", x); } return null; diff --git a/app/src/main/java/github/daneren2005/dsub/util/Notifications.java b/app/src/main/java/github/daneren2005/dsub/util/Notifications.java index 59341ebf..a8f7add0 100644 --- a/app/src/main/java/github/daneren2005/dsub/util/Notifications.java +++ b/app/src/main/java/github/daneren2005/dsub/util/Notifications.java @@ -114,11 +114,11 @@ public final class Notifications { handler.post(new Runnable() { @Override public void run() { - downloadService.stopForeground(true); + stopForeground(downloadService, true); showDownloadingNotification(context, downloadService, handler, downloadService.getCurrentDownloading(), downloadService.getBackgroundDownloads().size()); try { - downloadService.startForeground(NOTIFICATION_ID_PLAYING, notification); + startForeground(downloadService, NOTIFICATION_ID_PLAYING, notification); } catch(Exception e) { Log.e(TAG, "Failed to start notifications after stopping foreground download"); } @@ -130,7 +130,7 @@ public final class Notifications { public void run() { if (playing) { try { - downloadService.startForeground(NOTIFICATION_ID_PLAYING, notification); + startForeground(downloadService, NOTIFICATION_ID_PLAYING, notification); } catch(Exception e) { Log.e(TAG, "Failed to start notifications while playing"); } @@ -138,7 +138,7 @@ public final class Notifications { playShowing = false; persistentPlayingShowing = true; NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - downloadService.stopForeground(false); + stopForeground(downloadService, false); try { notificationManager.notify(NOTIFICATION_ID_PLAYING, notification); @@ -334,7 +334,7 @@ public final class Notifications { handler.post(new Runnable() { @Override public void run() { - downloadService.stopForeground(true); + stopForeground(downloadService, true); if(persistentPlayingShowing) { NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); @@ -413,7 +413,7 @@ public final class Notifications { handler.post(new Runnable() { @Override public void run() { - downloadService.startForeground(NOTIFICATION_ID_DOWNLOADING, notification); + startForeground(downloadService, NOTIFICATION_ID_DOWNLOADING, notification); } }); } @@ -429,7 +429,7 @@ public final class Notifications { handler.post(new Runnable() { @Override public void run() { - downloadService.stopForeground(true); + stopForeground(downloadService, true); } }); } @@ -461,8 +461,8 @@ public final class Notifications { .setChannelId("downloading-channel"); final Notification notification = builder.build(); - downloadService.startForeground(NOTIFICATION_ID_SHUT_GOOGLE_UP, notification); - downloadService.stopForeground(true); + startForeground(downloadService, NOTIFICATION_ID_SHUT_GOOGLE_UP, notification); + stopForeground(downloadService, true); } public static void showSyncNotification(final Context context, int stringId, String extra) { @@ -537,4 +537,14 @@ public final class Notifications { return syncChannel; } + + private static void startForeground(DownloadService downloadService, int notificationId, Notification notification) { + downloadService.startForeground(notificationId, notification); + downloadService.setIsForeground(true); + } + + private static void stopForeground(DownloadService downloadService, boolean removeNotification) { + downloadService.stopForeground(removeNotification); + downloadService.setIsForeground(false); + } } diff --git a/app/src/main/java/github/daneren2005/dsub/util/Util.java b/app/src/main/java/github/daneren2005/dsub/util/Util.java index 5699cdf9..78f3e2d6 100644 --- a/app/src/main/java/github/daneren2005/dsub/util/Util.java +++ b/app/src/main/java/github/daneren2005/dsub/util/Util.java @@ -1294,11 +1294,11 @@ public final class Util { public static void registerMediaButtonEventReceiver(Context context) { - // Only do it if enabled in the settings. + // Only do it if enabled in the settings and api < 21 SharedPreferences prefs = getPreferences(context); boolean enabled = prefs.getBoolean(Constants.PREFERENCES_KEY_MEDIA_BUTTONS, true); - if (enabled) { + if (enabled && Build.VERSION.SDK_INT < 21) { // AudioManager.registerMediaButtonEventReceiver() was introduced in Android 2.2. // Use reflection to maintain compatibility with 1.5. @@ -1327,11 +1327,9 @@ public final class Util { } @TargetApi(8) - public static void requestAudioFocus(final Context context) { + public static void requestAudioFocus(final Context context, final AudioManager audioManager) { if(Build.VERSION.SDK_INT >= 26) { if(audioFocusRequest == null) { - final AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - AudioAttributes playbackAttributes = new AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_MEDIA) .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) @@ -1344,7 +1342,6 @@ public final class Util { audioManager.requestAudioFocus(audioFocusRequest); } } else if (Build.VERSION.SDK_INT >= 8 && focusListener == null) { - final AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); audioManager.requestAudioFocus(focusListener = getAudioFocusChangeListener(context, audioManager), AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); } } diff --git a/app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java b/app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java index 1229d024..b27a9850 100644 --- a/app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java +++ b/app/src/main/java/github/daneren2005/dsub/util/compat/RemoteControlClientLP.java @@ -25,21 +25,20 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Bitmap; -import android.media.AudioAttributes; -import android.media.MediaDescription; -import android.media.MediaMetadata; +import android.media.AudioManager; import android.media.RemoteControlClient; -import android.media.session.MediaSession; -import android.media.session.PlaybackState; import android.os.Build; import android.os.Bundle; import android.provider.MediaStore; import android.support.annotation.NonNull; +import android.support.v4.media.MediaDescriptionCompat; +import android.support.v4.media.MediaMetadataCompat; +import android.support.v4.media.session.MediaSessionCompat; +import android.support.v4.media.session.PlaybackStateCompat; import android.support.v7.media.MediaRouter; import android.util.Log; import android.view.KeyEvent; -import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -75,7 +74,7 @@ public class RemoteControlClientLP extends RemoteControlClientBase { private static final String AUTO_RESERVE_SKIP_TO_NEXT = "com.google.android.gms.car.media.ALWAYS_RESERVE_SPACE_FOR.ACTION_SKIP_TO_NEXT"; private static final String AUTO_RESERVE_SKIP_TO_PREVIOUS = "com.google.android.gms.car.media.ALWAYS_RESERVE_SPACE_FOR.ACTION_SKIP_TO_PREVIOUS"; - protected MediaSession mediaSession; + protected MediaSessionCompat mediaSession; protected DownloadService downloadService; protected ImageLoader imageLoader; protected List<DownloadFile> currentQueue; @@ -84,7 +83,7 @@ public class RemoteControlClientLP extends RemoteControlClientBase { @Override public void register(Context context, ComponentName mediaButtonReceiverComponent) { downloadService = (DownloadService) context; - mediaSession = new MediaSession(downloadService, "DSub MediaSession"); + mediaSession = new MediaSessionCompat(downloadService, "DSub MediaSession"); Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); mediaButtonIntent.setComponent(mediaButtonReceiverComponent); @@ -97,13 +96,10 @@ public class RemoteControlClientLP extends RemoteControlClientBase { PendingIntent activityPendingIntent = PendingIntent.getActivity(context, 0, activityIntent, 0); mediaSession.setSessionActivity(activityPendingIntent); - mediaSession.setFlags(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS | MediaSession.FLAG_HANDLES_MEDIA_BUTTONS); + mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS | MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS); mediaSession.setCallback(new EventCallback()); - AudioAttributes.Builder audioAttributesBuilder = new AudioAttributes.Builder(); - audioAttributesBuilder.setUsage(AudioAttributes.USAGE_MEDIA) - .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC); - mediaSession.setPlaybackToLocal(audioAttributesBuilder.build()); + mediaSession.setPlaybackToLocal(AudioManager.STREAM_MUSIC); mediaSession.setActive(true); Bundle sessionExtras = new Bundle(); @@ -128,21 +124,21 @@ public class RemoteControlClientLP extends RemoteControlClientBase { @Override public void setPlaybackState(int state, int index, int queueSize) { - PlaybackState.Builder builder = new PlaybackState.Builder(); + PlaybackStateCompat.Builder builder = new PlaybackStateCompat.Builder(); - int newState = PlaybackState.STATE_NONE; + int newState = PlaybackStateCompat.STATE_NONE; switch(state) { case RemoteControlClient.PLAYSTATE_PLAYING: - newState = PlaybackState.STATE_PLAYING; + newState = PlaybackStateCompat.STATE_PLAYING; break; case RemoteControlClient.PLAYSTATE_STOPPED: - newState = PlaybackState.STATE_STOPPED; + newState = PlaybackStateCompat.STATE_STOPPED; break; case RemoteControlClient.PLAYSTATE_PAUSED: - newState = PlaybackState.STATE_PAUSED; + newState = PlaybackStateCompat.STATE_PAUSED; break; case RemoteControlClient.PLAYSTATE_BUFFERING: - newState = PlaybackState.STATE_BUFFERING; + newState = PlaybackStateCompat.STATE_BUFFERING; break; } @@ -166,7 +162,7 @@ public class RemoteControlClientLP extends RemoteControlClientBase { builder.setActiveQueueItemId(entry.getId().hashCode()); } - PlaybackState playbackState = builder.build(); + PlaybackStateCompat playbackState = builder.build(); mediaSession.setPlaybackState(playbackState); previousState = state; } @@ -186,19 +182,19 @@ public class RemoteControlClientLP extends RemoteControlClientBase { } public void setMetadata(Entry currentSong, Bitmap bitmap) { - MediaMetadata.Builder builder = new MediaMetadata.Builder(); - builder.putString(MediaMetadata.METADATA_KEY_ARTIST, (currentSong == null) ? null : currentSong.getArtist()) - .putString(MediaMetadata.METADATA_KEY_ALBUM, (currentSong == null) ? null : currentSong.getAlbum()) - .putString(MediaMetadata.METADATA_KEY_ALBUM_ARTIST, (currentSong == null) ? null : currentSong.getArtist()) - .putString(MediaMetadata.METADATA_KEY_TITLE, (currentSong) == null ? null : currentSong.getTitle()) - .putString(MediaMetadata.METADATA_KEY_GENRE, (currentSong) == null ? null : currentSong.getGenre()) - .putLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER, (currentSong == null) ? + MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder(); + builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, (currentSong == null) ? null : currentSong.getArtist()) + .putString(MediaMetadataCompat.METADATA_KEY_ALBUM, (currentSong == null) ? null : currentSong.getAlbum()) + .putString(MediaMetadataCompat.METADATA_KEY_ALBUM_ARTIST, (currentSong == null) ? null : currentSong.getArtist()) + .putString(MediaMetadataCompat.METADATA_KEY_TITLE, (currentSong) == null ? null : currentSong.getTitle()) + .putString(MediaMetadataCompat.METADATA_KEY_GENRE, (currentSong) == null ? null : currentSong.getGenre()) + .putLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER, (currentSong == null) ? 0 : ((currentSong.getTrack() == null) ? 0 : currentSong.getTrack())) - .putLong(MediaMetadata.METADATA_KEY_DURATION, (currentSong == null) ? + .putLong(MediaMetadataCompat.METADATA_KEY_DURATION, (currentSong == null) ? 0 : ((currentSong.getDuration() == null) ? 0 : (currentSong.getDuration() * 1000))); if(bitmap != null) { - builder.putBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART, bitmap); + builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, bitmap); } mediaSession.setMetadata(builder.build()); @@ -221,17 +217,22 @@ public class RemoteControlClientLP extends RemoteControlClientBase { @Override public void updatePlaylist(List<DownloadFile> playlist) { - List<MediaSession.QueueItem> queue = new ArrayList<>(); + List<MediaSessionCompat.QueueItem> queue = new ArrayList<>(); for(DownloadFile file: playlist) { Entry entry = file.getSong(); + Bundle extras = new Bundle(); + extras.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, + ((entry.getDuration() == null) ? 0 : (entry.getDuration() * 1000))); - MediaDescription description = new MediaDescription.Builder() + MediaDescriptionCompat description = new MediaDescriptionCompat.Builder() .setMediaId(entry.getId()) .setTitle(entry.getTitle()) - .setSubtitle(entry.getAlbumDisplay()) + .setSubtitle(entry.getArtist()) + .setDescription(entry.getAlbum()) + .setExtras(extras) .build(); - MediaSession.QueueItem item = new MediaSession.QueueItem(description, entry.getId().hashCode()); + MediaSessionCompat.QueueItem item = new MediaSessionCompat.QueueItem(description, entry.getId().hashCode()); queue.add(item); } @@ -239,46 +240,46 @@ public class RemoteControlClientLP extends RemoteControlClientBase { currentQueue = playlist; } - public MediaSession getMediaSession() { + public MediaSessionCompat getMediaSession() { return mediaSession; } protected long getPlaybackActions(boolean isSong, int currentIndex, int size) { - long actions = PlaybackState.ACTION_PLAY | - PlaybackState.ACTION_PAUSE | - PlaybackState.ACTION_SEEK_TO | - PlaybackState.ACTION_SKIP_TO_QUEUE_ITEM; + long actions = PlaybackStateCompat.ACTION_PLAY | + PlaybackStateCompat.ACTION_PAUSE | + PlaybackStateCompat.ACTION_SEEK_TO | + PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM; if(isSong) { if (currentIndex > 0) { - actions |= PlaybackState.ACTION_SKIP_TO_PREVIOUS; + actions |= PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS; } if (currentIndex < size - 1) { - actions |= PlaybackState.ACTION_SKIP_TO_NEXT; + actions |= PlaybackStateCompat.ACTION_SKIP_TO_NEXT; } } else { - actions |= PlaybackState.ACTION_SKIP_TO_PREVIOUS; - actions |= PlaybackState.ACTION_SKIP_TO_NEXT; + actions |= PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS; + actions |= PlaybackStateCompat.ACTION_SKIP_TO_NEXT; } return actions; } - protected void addCustomActions(Entry currentSong, PlaybackState.Builder builder) { + protected void addCustomActions(Entry currentSong, PlaybackStateCompat.Builder builder) { Bundle showOnWearExtras = new Bundle(); showOnWearExtras.putBoolean(SHOW_ON_WEAR, true); int rating = currentSong.getRating(); - PlaybackState.CustomAction thumbsUp = new PlaybackState.CustomAction.Builder(CUSTOM_ACTION_THUMBS_UP, + PlaybackStateCompat.CustomAction thumbsUp = new PlaybackStateCompat.CustomAction.Builder(CUSTOM_ACTION_THUMBS_UP, downloadService.getString(R.string.download_thumbs_up), rating == 5 ? R.drawable.ic_action_rating_good_selected : R.drawable.ic_action_rating_good) .setExtras(showOnWearExtras).build(); - PlaybackState.CustomAction thumbsDown = new PlaybackState.CustomAction.Builder(CUSTOM_ACTION_THUMBS_DOWN, + PlaybackStateCompat.CustomAction thumbsDown = new PlaybackStateCompat.CustomAction.Builder(CUSTOM_ACTION_THUMBS_DOWN, downloadService.getString(R.string.download_thumbs_down), rating == 1 ? R.drawable.ic_action_rating_bad_selected : R.drawable.ic_action_rating_bad) .setExtras(showOnWearExtras).build(); - PlaybackState.CustomAction star = new PlaybackState.CustomAction.Builder(CUSTOM_ACTION_STAR, + PlaybackStateCompat.CustomAction star = new PlaybackStateCompat.CustomAction.Builder(CUSTOM_ACTION_STAR, downloadService.getString(R.string.common_star), currentSong.isStarred() ? R.drawable.ic_toggle_star : R.drawable.ic_toggle_star_outline) .setExtras(showOnWearExtras).build(); @@ -476,7 +477,7 @@ public class RemoteControlClientLP extends RemoteControlClientBase { downloadService.setShufflePlayEnabled(true); } - private class EventCallback extends MediaSession.Callback { + private class EventCallback extends MediaSessionCompat.Callback { @Override public void onPlay() { downloadService.start(); diff --git a/app/src/main/res/xml/changelog.xml b/app/src/main/res/xml/changelog.xml index 42e62e1d..80e26cc8 100644 --- a/app/src/main/res/xml/changelog.xml +++ b/app/src/main/res/xml/changelog.xml @@ -1,5 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <changelog> + <release version="5.4.4" versioncode="201" releasedate="09/27/2018"> + <change>Reverted back to target SDK 23 to fix service crashes</change> + </release> <release version="5.4.3" versioncode="200" releasedate="09/11/2018"> <change>Fix more issues from targeting Android O</change> </release> diff --git a/app/src/main/res/xml/settings_playback.xml b/app/src/main/res/xml/settings_playback.xml index edaf3013..fb3501f0 100644 --- a/app/src/main/res/xml/settings_playback.xml +++ b/app/src/main/res/xml/settings_playback.xml @@ -117,7 +117,8 @@ </PreferenceCategory> <PreferenceCategory - android:title="@string/settings.other_title"> + android:title="@string/settings.other_title" + android:key="otherSettings"> <CheckBoxPreference android:title="@string/settings.shuffle_by_album" diff --git a/build.gradle b/build.gradle index d5dfdd4f..3fc890c1 100644 --- a/build.gradle +++ b/build.gradle @@ -7,9 +7,10 @@ buildscript { url 'https://maven.google.com/' name 'Google' } + google() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.2.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 325e6709..90a0ff73 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Nov 09 08:50:56 PST 2017 +#Sun Nov 18 21:50:34 GMT 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip diff --git a/settings.gradle b/settings.gradle index 430c7754..73938efa 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,4 @@ -include ':app', ':Server Proxy' -project(':Server Proxy').projectDir = new File('ServerProxy') +include ':app' + +include ':ServerProxy' +project(':ServerProxy').projectDir = new File('ServerProxy') |