From c7a49ee88e82a97bd1340bb83513a5a984d19938 Mon Sep 17 00:00:00 2001 From: Andrew Rabert Date: Sat, 24 Mar 2018 21:28:28 -0400 Subject: [PATCH] IDE-fueled mega refactor --- .gitignore | 6 +- .idea/misc.xml | 4 - .idea/modules.xml | 9 - .idea/runConfigurations.xml | 12 - .idea/vcs.xml | 6 - app/src/main/AndroidManifest.xml | 165 ++- .../activity/EditPlayActionActivity.java | 95 +- .../activity/QueryReceiverActivity.java | 14 +- .../audinaut/activity/SettingsActivity.java | 7 +- .../audinaut/activity/SubsonicActivity.java | 479 +++---- .../activity/SubsonicFragmentActivity.java | 343 ++--- .../activity/VoiceQueryReceiverActivity.java | 8 +- .../adapter/AlphabeticalAlbumAdapter.java | 8 +- .../audinaut/adapter/ArtistAdapter.java | 88 +- .../audinaut/adapter/BasicListAdapter.java | 9 +- .../audinaut/adapter/DetailsAdapter.java | 24 +- .../audinaut/adapter/DownloadFileAdapter.java | 14 +- .../audinaut/adapter/EntryGridAdapter.java | 65 +- .../adapter/EntryInfiniteGridAdapter.java | 36 +- .../adapter/ExpandableSectionAdapter.java | 91 +- .../audinaut/adapter/GenreAdapter.java | 8 +- .../nullsum/audinaut/adapter/MainAdapter.java | 19 +- .../audinaut/adapter/PlaylistAdapter.java | 23 +- .../audinaut/adapter/SearchAdapter.java | 42 +- .../audinaut/adapter/SectionAdapter.java | 270 ++-- .../audinaut/adapter/SettingsAdapter.java | 121 -- .../audiofx/AudioEffectsController.java | 8 +- .../audinaut/audiofx/EqualizerController.java | 36 +- .../audiofx/LoudnessEnhancerController.java | 13 +- .../audinaut/domain/MusicDirectory.java | 182 +-- .../nullsum/audinaut/domain/MusicFolder.java | 27 +- .../nullsum/audinaut/domain/PlayerQueue.java | 6 +- .../net/nullsum/audinaut/domain/Playlist.java | 43 +- .../audinaut/domain/SearchCritera.java | 18 +- .../nullsum/audinaut/domain/SearchResult.java | 9 - .../net/nullsum/audinaut/domain/User.java | 75 +- .../audinaut/fragments/DownloadFragment.java | 62 +- .../audinaut/fragments/EqualizerFragment.java | 103 +- .../audinaut/fragments/MainFragment.java | 110 +- .../fragments/NowPlayingFragment.java | 542 +++----- .../fragments/PreferenceCompatFragment.java | 88 +- .../audinaut/fragments/SearchFragment.java | 82 +- .../fragments/SelectArtistFragment.java | 40 +- .../fragments/SelectDirectoryFragment.java | 455 ++---- .../fragments/SelectGenreFragment.java | 6 +- .../fragments/SelectPlaylistFragment.java | 210 ++- .../fragments/SelectRecyclerFragment.java | 89 +- .../fragments/SelectYearFragment.java | 11 +- .../audinaut/fragments/SettingsFragment.java | 404 +++--- .../audinaut/fragments/SubsonicFragment.java | 767 +++++----- .../provider/AudinautSearchProvider.java | 92 +- .../provider/AudinautWidgetProvider.java | 333 +++-- .../audinaut/receiver/A2dpIntentReceiver.java | 7 +- .../audinaut/receiver/AudioNoisyReceiver.java | 18 +- .../audinaut/receiver/BootReceiver.java | 4 +- .../receiver/HeadphonePlugReceiver.java | 6 +- .../receiver/MediaButtonIntentReceiver.java | 4 +- .../audinaut/receiver/PlayActionReceiver.java | 4 +- .../audinaut/service/CachedMusicService.java | 455 ++---- .../audinaut/service/DownloadFile.java | 181 +-- .../audinaut/service/DownloadService.java | 1235 +++++++---------- .../DownloadServiceLifecycleSupport.java | 293 ++-- .../service/HeadphoneListenerService.java | 6 +- .../audinaut/service/MediaStoreService.java | 8 +- .../audinaut/service/MusicService.java | 18 +- .../audinaut/service/OfflineException.java | 4 +- .../audinaut/service/OfflineMusicService.java | 261 ++-- .../audinaut/service/RESTMusicService.java | 439 +++--- .../service/parser/AbstractParser.java | 73 +- .../service/parser/EntryListParser.java | 8 +- .../audinaut/service/parser/ErrorParser.java | 1 + .../audinaut/service/parser/GenreParser.java | 18 +- .../service/parser/IndexesParser.java | 39 +- .../parser/MusicDirectoryEntryParser.java | 25 +- .../service/parser/MusicDirectoryParser.java | 26 +- .../service/parser/MusicFoldersParser.java | 17 +- .../service/parser/PlayQueueParser.java | 83 -- .../service/parser/PlaylistParser.java | 6 +- .../service/parser/PlaylistsParser.java | 6 +- .../service/parser/RandomSongsParser.java | 6 +- .../service/parser/SearchResult2Parser.java | 16 +- .../service/parser/SubsonicRESTException.java | 10 +- .../audinaut/service/parser/UserParser.java | 42 +- .../net/nullsum/audinaut/updates/Updater.java | 41 +- .../audinaut/updates/UpdaterSongPress.java | 4 +- .../nullsum/audinaut/util/BackgroundTask.java | 189 +-- .../net/nullsum/audinaut/util/BufferFile.java | 6 + .../nullsum/audinaut/util/BufferProxy.java | 16 +- .../nullsum/audinaut/util/CacheCleaner.java | 78 +- .../net/nullsum/audinaut/util/Constants.java | 24 +- .../util/DownloadFileItemHelperCallback.java | 38 +- .../nullsum/audinaut/util/DrawableTint.java | 47 +- .../audinaut/util/EnvironmentVariables.java | 20 - .../net/nullsum/audinaut/util/FileProxy.java | 48 +- .../net/nullsum/audinaut/util/FileUtil.java | 326 ++--- .../nullsum/audinaut/util/ImageLoader.java | 200 +-- .../nullsum/audinaut/util/LoadingTask.java | 23 +- .../net/nullsum/audinaut/util/MenuUtil.java | 29 +- .../nullsum/audinaut/util/Notifications.java | 113 +- .../java/net/nullsum/audinaut/util/Pair.java | 14 +- .../audinaut/util/ProgressListener.java | 2 +- .../nullsum/audinaut/util/ServerProxy.java | 74 +- .../audinaut/util/SettingsBackupAgent.java | 7 +- .../audinaut/util/ShufflePlayBuffer.java | 70 +- .../audinaut/util/SilentBackgroundTask.java | 4 - .../audinaut/util/SilentServiceTask.java | 41 - .../audinaut/util/SimpleServiceBinder.java | 8 +- .../nullsum/audinaut/util/SongDBHandler.java | 163 +-- .../net/nullsum/audinaut/util/SyncUtil.java | 91 +- .../audinaut/util/TabBackgroundTask.java | 7 +- .../net/nullsum/audinaut/util/ThemeUtil.java | 29 +- .../audinaut/util/TimeLimitedCache.java | 14 +- .../nullsum/audinaut/util/UpdateHelper.java | 39 +- .../net/nullsum/audinaut/util/UserUtil.java | 53 +- .../java/net/nullsum/audinaut/util/Util.java | 461 ++---- .../net/nullsum/audinaut/util/tags/Bastp.java | 29 +- .../nullsum/audinaut/util/tags/BastpUtil.java | 37 +- .../nullsum/audinaut/util/tags/Common.java | 60 +- .../nullsum/audinaut/util/tags/FlacFile.java | 27 +- .../nullsum/audinaut/util/tags/ID3v2File.java | 94 +- .../audinaut/util/tags/LameHeader.java | 23 +- .../nullsum/audinaut/util/tags/OggFile.java | 46 +- .../net/nullsum/audinaut/view/AlbumView.java | 29 +- .../audinaut/view/ArtistEntryView.java | 19 +- .../net/nullsum/audinaut/view/ArtistView.java | 18 +- .../audinaut/view/AutoRepeatButton.java | 81 +- .../audinaut/view/BasicHeaderView.java | 5 +- .../nullsum/audinaut/view/BasicListView.java | 8 +- .../view/CacheLocationPreference.java | 67 +- .../net/nullsum/audinaut/view/CardView.java | 9 +- .../nullsum/audinaut/view/ErrorDialog.java | 27 +- .../audinaut/view/FadeOutAnimation.java | 36 +- .../nullsum/audinaut/view/FastScroller.java | 114 +- .../net/nullsum/audinaut/view/GenreView.java | 16 +- .../audinaut/view/GridSpacingDecoration.java | 33 +- .../audinaut/view/MyLeadingMarginSpan2.java | 34 - .../audinaut/view/PlaylistSongView.java | 29 +- .../nullsum/audinaut/view/PlaylistView.java | 18 +- .../audinaut/view/RecyclingImageView.java | 34 +- .../audinaut/view/SeekBarPreference.java | 55 +- .../nullsum/audinaut/view/SettingView.java | 23 +- .../net/nullsum/audinaut/view/SongView.java | 96 +- .../audinaut/view/SquareImageView.java | 1 - .../net/nullsum/audinaut/view/UpdateView.java | 221 ++- .../nullsum/audinaut/view/UpdateView2.java | 29 +- .../net/nullsum/audinuat/domain/Artist.kt | 8 - .../net/nullsum/audinuat/domain/Indexes.kt | 13 +- .../nullsum/audinuat/domain/PlayerState.kt | 25 +- .../audinuat/service/MusicServiceFactory.kt | 7 +- app/src/main/res/anim/enter_from_left.xml | 11 +- app/src/main/res/anim/enter_from_right.xml | 11 +- app/src/main/res/anim/exit_to_left.xml | 11 +- app/src/main/res/anim/exit_to_right.xml | 11 +- app/src/main/res/anim/fade_in.xml | 6 +- app/src/main/res/anim/fade_out.xml | 6 +- app/src/main/res/anim/push_down_in.xml | 15 +- app/src/main/res/anim/push_down_out.xml | 15 +- app/src/main/res/anim/push_up_in.xml | 15 +- app/src/main/res/anim/push_up_out.xml | 15 +- .../drawable-v21/notification_backward.xml | 5 +- .../res/drawable-v21/notification_close.xml | 5 +- .../res/drawable-v21/notification_forward.xml | 5 +- .../res/drawable-v21/notification_pause.xml | 5 +- .../res/drawable-v21/notification_start.xml | 5 +- .../drawable/card_rounded_corners_black.xml | 10 +- .../drawable/card_rounded_corners_dark.xml | 10 +- .../drawable/card_rounded_corners_light.xml | 10 +- .../res/drawable/fast_scroller_bubble.xml | 12 +- .../res/drawable/fast_scroller_handle.xml | 16 +- .../res/drawable/notification_backward.xml | 5 +- .../main/res/drawable/notification_close.xml | 5 +- .../res/drawable/notification_forward.xml | 5 +- .../main/res/drawable/notification_pause.xml | 5 +- .../main/res/drawable/notification_start.xml | 5 +- app/src/main/res/layout-land/download.xml | 80 +- .../abstract_fragment_container.xml | 9 +- .../main/res/layout-large-land/download.xml | 47 +- app/src/main/res/layout-port/download.xml | 43 +- app/src/main/res/layout/abstract_activity.xml | 8 +- .../res/layout/abstract_fragment_activity.xml | 111 +- .../layout/abstract_fragment_container.xml | 2 +- .../res/layout/abstract_recycler_fragment.xml | 11 +- app/src/main/res/layout/actionbar_spinner.xml | 7 +- app/src/main/res/layout/album_cell_item.xml | 30 +- app/src/main/res/layout/album_list_header.xml | 16 +- app/src/main/res/layout/album_list_item.xml | 30 +- app/src/main/res/layout/appwidget4x1.xml | 48 +- app/src/main/res/layout/appwidget4x2.xml | 62 +- app/src/main/res/layout/appwidget4x3.xml | 58 +- app/src/main/res/layout/appwidget4x4.xml | 64 +- app/src/main/res/layout/basic_art_item.xml | 18 +- app/src/main/res/layout/basic_cell_item.xml | 22 +- app/src/main/res/layout/basic_choice_item.xml | 14 +- app/src/main/res/layout/basic_count_item.xml | 18 +- app/src/main/res/layout/basic_header.xml | 8 +- app/src/main/res/layout/basic_list_item.xml | 16 +- .../res/layout/cache_location_buttons.xml | 8 +- app/src/main/res/layout/details_item.xml | 14 +- .../res/layout/download_media_buttons.xml | 119 +- app/src/main/res/layout/download_playlist.xml | 18 +- app/src/main/res/layout/download_slider.xml | 68 +- app/src/main/res/layout/drawer_header.xml | 28 +- app/src/main/res/layout/edit_play_action.xml | 70 +- app/src/main/res/layout/equalizer.xml | 59 +- app/src/main/res/layout/equalizer_bar.xml | 20 +- app/src/main/res/layout/expandable_header.xml | 28 +- app/src/main/res/layout/fast_scroller.xml | 23 +- app/src/main/res/layout/genre_list_item.xml | 26 +- app/src/main/res/layout/notification.xml | 27 +- .../main/res/layout/notification_expanded.xml | 30 +- app/src/main/res/layout/preferences.xml | 6 +- app/src/main/res/layout/save_playlist.xml | 33 +- .../main/res/layout/seekbar_preference.xml | 13 +- .../main/res/layout/select_album_header.xml | 95 +- .../main/res/layout/select_artist_header.xml | 64 +- app/src/main/res/layout/settings_activity.xml | 8 +- app/src/main/res/layout/shuffle_dialog.xml | 62 +- app/src/main/res/layout/song_list_item.xml | 100 +- app/src/main/res/layout/tab_progress.xml | 22 +- app/src/main/res/layout/update_playlist.xml | 56 +- app/src/main/res/menu/abstract_top_menu.xml | 6 +- app/src/main/res/menu/downloading.xml | 4 +- app/src/main/res/menu/drawer_navigation.xml | 17 +- app/src/main/res/menu/empty.xml | 4 +- app/src/main/res/menu/main.xml | 6 +- app/src/main/res/menu/multiselect_media.xml | 24 +- .../res/menu/multiselect_media_offline.xml | 16 +- .../main/res/menu/multiselect_nowplaying.xml | 14 +- .../menu/multiselect_nowplaying_offline.xml | 6 +- app/src/main/res/menu/nowplaying.xml | 22 +- app/src/main/res/menu/nowplaying_context.xml | 16 +- .../res/menu/nowplaying_context_offline.xml | 12 +- app/src/main/res/menu/nowplaying_offline.xml | 18 +- app/src/main/res/menu/search.xml | 4 +- app/src/main/res/menu/select_album.xml | 14 +- .../main/res/menu/select_album_context.xml | 24 +- .../res/menu/select_album_context_offline.xml | 20 +- app/src/main/res/menu/select_album_list.xml | 8 +- app/src/main/res/menu/select_artist.xml | 12 +- .../main/res/menu/select_artist_context.xml | 20 +- .../menu/select_artist_context_offline.xml | 16 +- .../main/res/menu/select_playlist_context.xml | 17 +- .../menu/select_playlist_context_offline.xml | 8 +- app/src/main/res/menu/select_song.xml | 18 +- app/src/main/res/menu/select_song_context.xml | 30 +- .../res/menu/select_song_context_offline.xml | 18 +- app/src/main/res/menu/select_song_offline.xml | 12 +- .../main/res/menu/tasker_configuration.xml | 6 +- app/src/main/res/values-v21/styles.xml | 8 +- app/src/main/res/values-v21/themes.xml | 4 + app/src/main/res/values/attrs.xml | 108 +- app/src/main/res/values/ids.xml | 2 +- app/src/main/res/values/strings.xml | 17 +- app/src/main/res/values/styles.xml | 31 +- app/src/main/res/values/themes.xml | 82 +- app/src/main/res/xml/appwidget4x1.xml | 8 +- app/src/main/res/xml/appwidget4x2.xml | 8 +- app/src/main/res/xml/appwidget4x3.xml | 8 +- app/src/main/res/xml/appwidget4x4.xml | 12 +- app/src/main/res/xml/authenticator.xml | 7 +- app/src/main/res/xml/searchable.xml | 15 +- app/src/main/res/xml/settings.xml | 20 +- app/src/main/res/xml/settings_appearance.xml | 49 +- app/src/main/res/xml/settings_cache.xml | 76 +- app/src/main/res/xml/settings_playback.xml | 107 +- app/src/main/res/xml/settings_servers.xml | 2 +- audinaut.svg | 25 +- 267 files changed, 6271 insertions(+), 9399 deletions(-) delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/runConfigurations.xml delete mode 100644 .idea/vcs.xml delete mode 100644 app/src/main/java/net/nullsum/audinaut/adapter/SettingsAdapter.java delete mode 100644 app/src/main/java/net/nullsum/audinaut/service/parser/PlayQueueParser.java delete mode 100644 app/src/main/java/net/nullsum/audinaut/util/EnvironmentVariables.java delete mode 100644 app/src/main/java/net/nullsum/audinaut/util/SilentServiceTask.java delete mode 100644 app/src/main/java/net/nullsum/audinaut/view/MyLeadingMarginSpan2.java diff --git a/.gitignore b/.gitignore index 7a75b49..1a00d2b 100644 --- a/.gitignore +++ b/.gitignore @@ -37,11 +37,7 @@ captures/ # Intellij *.iml -.idea/workspace.xml -.idea/tasks.xml -.idea/gradle.xml -.idea/dictionaries -.idea/libraries +.idea # External native build folder generated in Android Studio 2.2 and later .externalNativeBuild diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index f5c6d9e..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 5017480..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 7f68460..0000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ce7118c..a3d3e40 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,100 +1,120 @@ + package="net.nullsum.audinaut" + android:installLocation="internalOnly"> - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + - - - - + - - - - + - - + + - + - + - + - + - + + android:icon="@drawable/launch" + android:label="@string/tasker.start_playing"> - + - + - - - + + + - + @@ -106,7 +126,7 @@ - + @@ -114,48 +134,59 @@ android:name="net.nullsum.audinaut.provider.AudinautWidget4x1" android:label="@string/widget.4x1"> - + - + - + - + - + - + - + - + + android:name="net.nullsum.audinaut.receiver.PlayActionReceiver" + android:permission=""> - + - + diff --git a/app/src/main/java/net/nullsum/audinaut/activity/EditPlayActionActivity.java b/app/src/main/java/net/nullsum/audinaut/activity/EditPlayActionActivity.java index 5cf4cc8..f6bb4c7 100644 --- a/app/src/main/java/net/nullsum/audinaut/activity/EditPlayActionActivity.java +++ b/app/src/main/java/net/nullsum/audinaut/activity/EditPlayActionActivity.java @@ -16,12 +16,10 @@ package net.nullsum.audinaut.activity; import android.app.Activity; -import android.support.v7.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.support.v4.widget.DrawerLayout; +import android.support.v7.app.AlertDialog; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -29,13 +27,9 @@ import android.view.View; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; -import android.widget.CompoundButton; import android.widget.EditText; import android.widget.Spinner; -import java.util.ArrayList; -import java.util.List; - import net.nullsum.audinaut.R; import net.nullsum.audinaut.domain.Genre; import net.nullsum.audinaut.service.MusicService; @@ -45,6 +39,9 @@ import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.LoadingTask; import net.nullsum.audinaut.util.Util; +import java.util.ArrayList; +import java.util.List; + public class EditPlayActionActivity extends SubsonicActivity { private CheckBox shuffleCheckbox; private CheckBox startYearCheckbox; @@ -64,36 +61,23 @@ public class EditPlayActionActivity extends SubsonicActivity { final Activity context = this; doNothing = context.getResources().getString(R.string.tasker_edit_do_nothing); - shuffleCheckbox = (CheckBox) findViewById(R.id.edit_shuffle_checkbox); - shuffleCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton view, boolean isChecked) { - startYearCheckbox.setEnabled(isChecked); - endYearCheckbox.setEnabled(isChecked); - genreButton.setEnabled(isChecked); - } + shuffleCheckbox = findViewById(R.id.edit_shuffle_checkbox); + shuffleCheckbox.setOnCheckedChangeListener((view, isChecked) -> { + startYearCheckbox.setEnabled(isChecked); + endYearCheckbox.setEnabled(isChecked); + genreButton.setEnabled(isChecked); }); - startYearCheckbox = (CheckBox) findViewById(R.id.edit_start_year_checkbox); - startYearBox = (EditText) findViewById(R.id.edit_start_year); + startYearCheckbox = findViewById(R.id.edit_start_year_checkbox); + startYearBox = findViewById(R.id.edit_start_year); // Disable/enable number box if checked - startYearCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton view, boolean isChecked) { - startYearBox.setEnabled(isChecked); - } - }); + startYearCheckbox.setOnCheckedChangeListener((view, isChecked) -> startYearBox.setEnabled(isChecked)); - endYearCheckbox = (CheckBox) findViewById(R.id.edit_end_year_checkbox); - endYearBox = (EditText) findViewById(R.id.edit_end_year); - endYearCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton view, boolean isChecked) { - endYearBox.setEnabled(isChecked); - } - }); + endYearCheckbox = findViewById(R.id.edit_end_year_checkbox); + endYearBox = findViewById(R.id.edit_end_year); + endYearCheckbox.setOnCheckedChangeListener((view, isChecked) -> endYearBox.setEnabled(isChecked)); - genreButton = (Button) findViewById(R.id.edit_genre_spinner); + genreButton = findViewById(R.id.edit_genre_spinner); genreButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { new LoadingTask>(context, true) { @@ -105,24 +89,22 @@ public class EditPlayActionActivity extends SubsonicActivity { @Override protected void done(final List genres) { - List names = new ArrayList(); + List names = new ArrayList<>(); String blank = context.getResources().getString(R.string.select_genre_blank); names.add(doNothing); names.add(blank); - for(Genre genre: genres) { + for (Genre genre : genres) { names.add(genre.getName()); } final List finalNames = names; AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.shuffle_pick_genre) - .setItems(names.toArray(new CharSequence[names.size()]), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - if(which == 1) { - genreButton.setText(""); - } else { - genreButton.setText(finalNames.get(which)); - } + .setItems(names.toArray(new CharSequence[names.size()]), (dialog, which) -> { + if (which == 1) { + genreButton.setText(""); + } else { + genreButton.setText(finalNames.get(which)); } }); AlertDialog dialog = builder.create(); @@ -145,36 +127,36 @@ public class EditPlayActionActivity extends SubsonicActivity { }); genreButton.setText(doNothing); - offlineSpinner = (Spinner) findViewById(R.id.edit_offline_spinner); + offlineSpinner = findViewById(R.id.edit_offline_spinner); ArrayAdapter offlineAdapter = ArrayAdapter.createFromResource(this, R.array.editServerOptions, android.R.layout.simple_spinner_item); offlineAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); offlineSpinner.setAdapter(offlineAdapter); // Setup default for everything Bundle extras = getIntent().getBundleExtra(Constants.TASKER_EXTRA_BUNDLE); - if(extras != null) { - if(extras.getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE)) { + if (extras != null) { + if (extras.getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE)) { shuffleCheckbox.setChecked(true); } String startYear = extras.getString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, null); - if(startYear != null) { + if (startYear != null) { startYearCheckbox.setEnabled(true); startYearBox.setText(startYear); } String endYear = extras.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, null); - if(endYear != null) { + if (endYear != null) { endYearCheckbox.setEnabled(true); endYearBox.setText(endYear); } String genre = extras.getString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, doNothing); - if(genre != null) { + if (genre != null) { genreButton.setText(genre); } int offline = extras.getInt(Constants.PREFERENCES_KEY_OFFLINE, 0); - if(offline != 0) { + if (offline != 0) { offlineSpinner.setSelection(offline); } } @@ -191,13 +173,13 @@ public class EditPlayActionActivity extends SubsonicActivity { @Override public boolean onOptionsItemSelected(MenuItem item) { - if(item.getItemId() == android.R.id.home) { + if (item.getItemId() == android.R.id.home) { cancel(); return true; - } else if(item.getItemId() == R.id.menu_accept) { + } else if (item.getItemId() == R.id.menu_accept) { accept(); return true; - } else if(item.getItemId() == R.id.menu_cancel) { + } else if (item.getItemId() == R.id.menu_cancel) { cancel(); return true; } @@ -215,21 +197,21 @@ public class EditPlayActionActivity extends SubsonicActivity { Bundle data = new Bundle(); boolean shuffle = shuffleCheckbox.isChecked(); data.putBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE, shuffle); - if(shuffle) { - if(startYearCheckbox.isChecked()) { + if (shuffle) { + if (startYearCheckbox.isChecked()) { data.putString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, startYearBox.getText().toString()); } - if(endYearCheckbox.isChecked()) { + if (endYearCheckbox.isChecked()) { data.putString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, endYearBox.getText().toString()); } String genre = genreButton.getText().toString(); - if(!genre.equals(doNothing)) { + if (!genre.equals(doNothing)) { data.putString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, genre); } } int offline = offlineSpinner.getSelectedItemPosition(); - if(offline != 0) { + if (offline != 0) { data.putInt(Constants.PREFERENCES_KEY_OFFLINE, offline); } @@ -238,6 +220,7 @@ public class EditPlayActionActivity extends SubsonicActivity { setResult(Activity.RESULT_OK, intent); finish(); } + private void cancel() { setResult(Activity.RESULT_CANCELED); finish(); diff --git a/app/src/main/java/net/nullsum/audinaut/activity/QueryReceiverActivity.java b/app/src/main/java/net/nullsum/audinaut/activity/QueryReceiverActivity.java index e4107e9..dc2135c 100644 --- a/app/src/main/java/net/nullsum/audinaut/activity/QueryReceiverActivity.java +++ b/app/src/main/java/net/nullsum/audinaut/activity/QueryReceiverActivity.java @@ -23,13 +23,9 @@ import android.app.Activity; import android.app.SearchManager; import android.content.Intent; import android.os.Bundle; -import android.provider.SearchRecentSuggestions; -import android.util.Log; -import net.nullsum.audinaut.fragments.SubsonicFragment; import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.Util; -import net.nullsum.audinaut.provider.AudinautSearchProvider; /** * Receives search queries and forwards to the SearchFragment. @@ -38,8 +34,6 @@ import net.nullsum.audinaut.provider.AudinautSearchProvider; */ public class QueryReceiverActivity extends Activity { - private static final String TAG = QueryReceiverActivity.class.getSimpleName(); - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -47,11 +41,10 @@ public class QueryReceiverActivity extends Activity { Intent intent = getIntent(); if (Intent.ACTION_SEARCH.equals(intent.getAction())) { doSearch(); - } else if(Intent.ACTION_VIEW.equals(intent.getAction())) { + } else if (Intent.ACTION_VIEW.equals(intent.getAction())) { showResult(intent.getDataString(), intent.getStringExtra(SearchManager.EXTRA_DATA_KEY)); } finish(); - Util.disablePendingTransition(this); } private void doSearch() { @@ -63,15 +56,16 @@ public class QueryReceiverActivity extends Activity { Util.startActivityWithoutTransition(QueryReceiverActivity.this, intent); } } + private void showResult(String albumId, String name) { if (albumId != null) { Intent intent = new Intent(this, SubsonicFragmentActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); intent.putExtra(Constants.INTENT_EXTRA_VIEW_ALBUM, true); - if(albumId.indexOf("ar-") == 0) { + if (albumId.indexOf("ar-") == 0) { intent.putExtra(Constants.INTENT_EXTRA_NAME_ARTIST, true); albumId = albumId.replace("ar-", ""); - } else if(albumId.indexOf("so-") == 0) { + } else if (albumId.indexOf("so-") == 0) { intent.putExtra(Constants.INTENT_EXTRA_SEARCH_SONG, name); albumId = albumId.replace("so-", ""); } diff --git a/app/src/main/java/net/nullsum/audinaut/activity/SettingsActivity.java b/app/src/main/java/net/nullsum/audinaut/activity/SettingsActivity.java index 399e80c..8b0bc1b 100644 --- a/app/src/main/java/net/nullsum/audinaut/activity/SettingsActivity.java +++ b/app/src/main/java/net/nullsum/audinaut/activity/SettingsActivity.java @@ -18,7 +18,6 @@ */ package net.nullsum.audinaut.activity; -import android.os.Build; import android.os.Bundle; import android.support.v7.widget.Toolbar; @@ -28,8 +27,6 @@ import net.nullsum.audinaut.fragments.SettingsFragment; import net.nullsum.audinaut.util.Constants; public class SettingsActivity extends SubsonicActivity { - private static final String TAG = SettingsActivity.class.getSimpleName(); - private PreferenceCompatFragment fragment; @Override public void onCreate(Bundle savedInstanceState) { @@ -38,7 +35,7 @@ public class SettingsActivity extends SubsonicActivity { setContentView(R.layout.settings_activity); if (savedInstanceState == null) { - fragment = new SettingsFragment(); + PreferenceCompatFragment fragment = new SettingsFragment(); Bundle args = new Bundle(); args.putInt(Constants.INTENT_EXTRA_FRAGMENT_TYPE, R.xml.settings); @@ -50,7 +47,7 @@ public class SettingsActivity extends SubsonicActivity { getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "").commit(); } - Toolbar mainToolbar = (Toolbar) findViewById(R.id.main_toolbar); + Toolbar mainToolbar = findViewById(R.id.main_toolbar); setSupportActionBar(mainToolbar); } } diff --git a/app/src/main/java/net/nullsum/audinaut/activity/SubsonicActivity.java b/app/src/main/java/net/nullsum/audinaut/activity/SubsonicActivity.java index 672c595..505cd2f 100644 --- a/app/src/main/java/net/nullsum/audinaut/activity/SubsonicActivity.java +++ b/app/src/main/java/net/nullsum/audinaut/activity/SubsonicActivity.java @@ -18,116 +18,108 @@ */ package net.nullsum.audinaut.activity; -import android.app.UiModeManager; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.content.res.Configuration; import android.media.AudioManager; -import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.support.design.widget.NavigationView; import android.support.v4.app.ActivityCompat; -import android.support.v4.content.ContextCompat; -import android.support.v7.app.ActionBarDrawerToggle; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; +import android.support.v4.content.ContextCompat; import android.support.v4.widget.DrawerLayout; -import android.support.v7.app.AlertDialog; +import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatDelegate; import android.support.v7.widget.Toolbar; import android.util.Log; -import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; -import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.Window; import android.view.WindowManager; import android.view.animation.AnimationUtils; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.ArrayAdapter; -import android.widget.CheckBox; import android.widget.ImageView; import android.widget.Spinner; import android.widget.TextView; +import net.nullsum.audinaut.R; +import net.nullsum.audinaut.fragments.SubsonicFragment; +import net.nullsum.audinaut.service.DownloadService; +import net.nullsum.audinaut.service.HeadphoneListenerService; +import net.nullsum.audinaut.util.Constants; +import net.nullsum.audinaut.util.DrawableTint; +import net.nullsum.audinaut.util.ImageLoader; +import net.nullsum.audinaut.util.SilentBackgroundTask; +import net.nullsum.audinaut.util.ThemeUtil; +import net.nullsum.audinaut.util.UserUtil; +import net.nullsum.audinaut.util.Util; +import net.nullsum.audinaut.view.UpdateView; + import java.io.File; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; -import net.nullsum.audinaut.R; -import net.nullsum.audinaut.fragments.SubsonicFragment; -import net.nullsum.audinaut.service.DownloadService; -import net.nullsum.audinaut.service.HeadphoneListenerService; -import net.nullsum.audinaut.service.MusicService; -import net.nullsum.audinaut.service.MusicServiceFactory; -import net.nullsum.audinaut.util.Constants; -import net.nullsum.audinaut.util.DrawableTint; -import net.nullsum.audinaut.util.ImageLoader; -import net.nullsum.audinaut.util.SilentBackgroundTask; -import net.nullsum.audinaut.util.ThemeUtil; -import net.nullsum.audinaut.util.Util; -import net.nullsum.audinaut.view.UpdateView; -import net.nullsum.audinaut.util.UserUtil; - -import static android.Manifest.*; +import static android.Manifest.permission; public class SubsonicActivity extends AppCompatActivity implements OnItemSelectedListener { private static final String TAG = SubsonicActivity.class.getSimpleName(); - private static ImageLoader IMAGE_LOADER; - protected static String theme; - protected static boolean fullScreen; - protected static boolean actionbarColored; private static final int MENU_GROUP_SERVER = 10; private static final int MENU_ITEM_SERVER_BASE = 100; private static final int PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 1; - - private final List afterServiceAvailable = new ArrayList<>(); - private boolean drawerIdle = true; - private boolean destroyed = false; - private boolean finished = false; - protected List backStack = new ArrayList(); - protected SubsonicFragment currentFragment; - protected View primaryContainer; - protected View secondaryContainer; - protected boolean touchscreen = true; - protected Handler handler = new Handler(); - Spinner actionBarSpinner; - ArrayAdapter spinnerAdapter; - ViewGroup rootView; - DrawerLayout drawer; - ActionBarDrawerToggle drawerToggle; - NavigationView drawerList; - View drawerHeader; - ImageView drawerHeaderToggle; - TextView drawerServerName; - TextView drawerUserName; - int lastSelectedPosition = 0; - boolean showingTabs = true; - boolean drawerOpen = false; - SharedPreferences.OnSharedPreferenceChangeListener preferencesListener; + private static String theme; + private static boolean fullScreen; + private static boolean actionbarColored; + private static ImageLoader IMAGE_LOADER; static { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO); } + final List backStack = new ArrayList<>(); + final Handler handler = new Handler(); + private final List afterServiceAvailable = new ArrayList<>(); + SubsonicFragment currentFragment; + View secondaryContainer; + DrawerLayout drawer; + ActionBarDrawerToggle drawerToggle; + NavigationView drawerList; + int lastSelectedPosition = 0; + private boolean touchscreen = true; + private Spinner actionBarSpinner; + private ArrayAdapter spinnerAdapter; + private View drawerHeader; + private ImageView drawerHeaderToggle; + private TextView drawerServerName; + private TextView drawerUserName; + private boolean showingTabs = true; + private boolean drawerOpen = false; + private SharedPreferences.OnSharedPreferenceChangeListener preferencesListener; + private boolean drawerIdle = true; + private boolean destroyed = false; + + public synchronized static ImageLoader getStaticImageLoader(Context context) { + if (IMAGE_LOADER == null) { + IMAGE_LOADER = new ImageLoader(context); + } + return IMAGE_LOADER; + } + @Override protected void onCreate(Bundle bundle) { - UiModeManager uiModeManager = (UiModeManager) getSystemService(UI_MODE_SERVICE); PackageManager pm = getPackageManager(); - if(!pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) { + if (!pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) { touchscreen = false; } @@ -138,16 +130,16 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte startService(new Intent(this, DownloadService.class)); setVolumeControlStream(AudioManager.STREAM_MUSIC); - if(getIntent().hasExtra(Constants.FRAGMENT_POSITION)) { + if (getIntent().hasExtra(Constants.FRAGMENT_POSITION)) { lastSelectedPosition = getIntent().getIntExtra(Constants.FRAGMENT_POSITION, 0); } - if(preferencesListener == null) { + if (preferencesListener == null) { Util.getPreferences(this).registerOnSharedPreferenceChangeListener(preferencesListener); } if (ContextCompat.checkSelfPermission(this, permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions(this, new String[]{ permission.WRITE_EXTERNAL_STORAGE }, PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE); + ActivityCompat.requestPermissions(this, new String[]{permission.WRITE_EXTERNAL_STORAGE}, PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE); } } @@ -156,9 +148,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte switch (requestCode) { case PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE: { // If request is cancelled, the result arrays are empty. - if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { - - } else { + if (!(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)) { Util.toast(this, R.string.permission_external_storage_failed); finish(); } @@ -170,23 +160,23 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); - if(spinnerAdapter == null) { + if (spinnerAdapter == null) { createCustomActionBarView(); } getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setHomeButtonEnabled(true); - if(Util.shouldStartOnHeadphones(this)) { + if (Util.shouldStartOnHeadphones(this)) { Intent serviceIntent = new Intent(); serviceIntent.setClassName(this.getPackageName(), HeadphoneListenerService.class.getName()); this.startService(serviceIntent); } } - protected void createCustomActionBarView() { + private void createCustomActionBarView() { actionBarSpinner = (Spinner) getLayoutInflater().inflate(R.layout.actionbar_spinner, null); - if((this instanceof SubsonicFragmentActivity || this instanceof SettingsActivity) && (Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_COLOR_ACTION_BAR, true) || ThemeUtil.getThemeRes(this) != R.style.Theme_Audinaut_Light_No_Color)) { - actionBarSpinner.setBackgroundDrawable(DrawableTint.getTintedDrawableFromColor(this, R.drawable.abc_spinner_mtrl_am_alpha, android.R.color.white)); + if ((this instanceof SubsonicFragmentActivity || this instanceof SettingsActivity) && (Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_COLOR_ACTION_BAR, true) || ThemeUtil.getThemeRes(this) != R.style.Theme_Audinaut_Light_No_Color)) { + actionBarSpinner.setBackground(DrawableTint.getTintedDrawableFromColor(this)); } spinnerAdapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item); spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); @@ -228,91 +218,79 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte Util.getPreferences(this).unregisterOnSharedPreferenceChangeListener(preferencesListener); } - @Override - public void finish() { - super.finish(); - Util.disablePendingTransition(this); - } - @Override public void setContentView(int viewId) { super.setContentView(R.layout.abstract_activity); - rootView = (ViewGroup) findViewById(R.id.content_frame); + ViewGroup rootView = findViewById(R.id.content_frame); - if(viewId != 0) { + if (viewId != 0) { LayoutInflater layoutInflater = getLayoutInflater(); layoutInflater.inflate(viewId, rootView); } - drawerList = (NavigationView) findViewById(R.id.left_drawer); - drawerList.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { - @Override - public boolean onNavigationItemSelected(final MenuItem menuItem) { - if(showingTabs) { - // Settings are on a different selectable track - if (menuItem.getItemId() != R.id.drawer_settings && menuItem.getItemId() != R.id.drawer_offline) { - menuItem.setChecked(true); - lastSelectedPosition = menuItem.getItemId(); - } - - switch (menuItem.getItemId()) { - case R.id.drawer_library: - drawerItemSelected("Artist"); - return true; - case R.id.drawer_playlists: - drawerItemSelected("Playlist"); - return true; - case R.id.drawer_downloading: - drawerItemSelected("Download"); - return true; - case R.id.drawer_offline: - toggleOffline(); - return true; - case R.id.drawer_settings: - startActivity(new Intent(SubsonicActivity.this, SettingsActivity.class)); - drawer.closeDrawers(); - return true; - } - } else { - int activeServer = menuItem.getItemId() - MENU_ITEM_SERVER_BASE; - SubsonicActivity.this.setActiveServer(activeServer); - populateTabs(); - return true; + drawerList = findViewById(R.id.left_drawer); + drawerList.setNavigationItemSelectedListener(menuItem -> { + if (showingTabs) { + // Settings are on a different selectable track + if (menuItem.getItemId() != R.id.drawer_settings && menuItem.getItemId() != R.id.drawer_offline) { + menuItem.setChecked(true); + lastSelectedPosition = menuItem.getItemId(); } - return false; + switch (menuItem.getItemId()) { + case R.id.drawer_library: + drawerItemSelected("Artist"); + return true; + case R.id.drawer_playlists: + drawerItemSelected("Playlist"); + return true; + case R.id.drawer_downloading: + drawerItemSelected("Download"); + return true; + case R.id.drawer_offline: + toggleOffline(); + return true; + case R.id.drawer_settings: + startActivity(new Intent(SubsonicActivity.this, SettingsActivity.class)); + drawer.closeDrawers(); + return true; + } + } else { + int activeServer = menuItem.getItemId() - MENU_ITEM_SERVER_BASE; + SubsonicActivity.this.setActiveServer(activeServer); + populateTabs(); + return true; } + + return false; }); drawerHeader = drawerList.inflateHeaderView(R.layout.drawer_header); - drawerHeader.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if(showingTabs) { - populateServers(); - } else { - populateTabs(); - } + drawerHeader.setOnClickListener(v -> { + if (showingTabs) { + populateServers(); + } else { + populateTabs(); } }); - drawerHeaderToggle = (ImageView) drawerHeader.findViewById(R.id.header_select_image); - drawerServerName = (TextView) drawerHeader.findViewById(R.id.header_server_name); - drawerUserName = (TextView) drawerHeader.findViewById(R.id.header_user_name); + drawerHeaderToggle = drawerHeader.findViewById(R.id.header_select_image); + drawerServerName = drawerHeader.findViewById(R.id.header_server_name); + drawerUserName = drawerHeader.findViewById(R.id.header_user_name); updateDrawerHeader(); - drawer = (DrawerLayout) findViewById(R.id.drawer_layout); + drawer = findViewById(R.id.drawer_layout); // Pass in toolbar if it exists - Toolbar toolbar = (Toolbar) findViewById(R.id.main_toolbar); + Toolbar toolbar = findViewById(R.id.main_toolbar); drawerToggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.common_appname, R.string.common_appname) { @Override public void onDrawerClosed(View view) { drawerIdle = true; drawerOpen = false; - if(!showingTabs) { + if (!showingTabs) { populateTabs(); } } @@ -321,10 +299,10 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte public void onDrawerOpened(View view) { DownloadService downloadService = getDownloadService(); boolean downloadingVisible = downloadService != null && !downloadService.getBackgroundDownloads().isEmpty(); - if(lastSelectedPosition == R.id.drawer_downloading) { + if (lastSelectedPosition == R.id.drawer_downloading) { downloadingVisible = true; } - setDrawerItemVisible(R.id.drawer_downloading, downloadingVisible); + setDrawerItemVisible(downloadingVisible); drawerIdle = true; drawerOpen = true; @@ -336,24 +314,13 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte drawerIdle = false; } }; - drawer.setDrawerListener(drawerToggle); + drawer.addDrawerListener(drawerToggle); drawerToggle.setDrawerIndicatorEnabled(true); - drawer.setOnTouchListener(new View.OnTouchListener() { - public boolean onTouch(View v, MotionEvent event) { - if (drawerIdle && currentFragment != null && currentFragment.getGestureDetector() != null) { - return currentFragment.getGestureDetector().onTouchEvent(event); - } else { - return false; - } - } - }); + drawer.setOnTouchListener((v, event) -> drawerIdle && currentFragment != null && currentFragment.getGestureDetector() != null && currentFragment.getGestureDetector().onTouchEvent(event)); // Check whether this is a tablet or not secondaryContainer = findViewById(R.id.fragment_second_container); - if(secondaryContainer != null) { - primaryContainer = findViewById(R.id.fragment_container); - } } @Override @@ -362,7 +329,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte String[] ids = new String[backStack.size() + 1]; ids[0] = currentFragment.getTag(); int i = 1; - for(SubsonicFragment frag: backStack) { + for (SubsonicFragment frag : backStack) { ids[i] = frag.getTag(); i++; } @@ -370,21 +337,22 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte savedInstanceState.putInt(Constants.MAIN_BACK_STACK_SIZE, backStack.size() + 1); savedInstanceState.putInt(Constants.FRAGMENT_POSITION, lastSelectedPosition); } + @Override public void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); int size = savedInstanceState.getInt(Constants.MAIN_BACK_STACK_SIZE); String[] ids = savedInstanceState.getStringArray(Constants.MAIN_BACK_STACK); FragmentManager fm = getSupportFragmentManager(); - currentFragment = (SubsonicFragment)fm.findFragmentByTag(ids[0]); + currentFragment = (SubsonicFragment) fm.findFragmentByTag(ids[0]); currentFragment.setPrimaryFragment(true); currentFragment.setSupportTag(ids[0]); supportInvalidateOptionsMenu(); FragmentTransaction trans = getSupportFragmentManager().beginTransaction(); - for(int i = 1; i < size; i++) { - SubsonicFragment frag = (SubsonicFragment)fm.findFragmentByTag(ids[i]); + for (int i = 1; i < size; i++) { + SubsonicFragment frag = (SubsonicFragment) fm.findFragmentByTag(ids[i]); frag.setSupportTag(ids[i]); - if(secondaryContainer != null) { + if (secondaryContainer != null) { frag.setPrimaryFragment(false, true); } trans.hide(frag); @@ -393,7 +361,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte trans.commit(); // Current fragment is hidden in secondaryContainer - if(secondaryContainer == null && !currentFragment.isVisible()) { + if (secondaryContainer == null && !currentFragment.isVisible()) { trans = getSupportFragmentManager().beginTransaction(); trans.remove(currentFragment); trans.commit(); @@ -404,7 +372,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte trans.commit(); } // Current fragment needs to be moved over to secondaryContainer - else if(secondaryContainer != null && secondaryContainer.findViewById(currentFragment.getRootId()) == null && backStack.size() > 0) { + else if (secondaryContainer != null && secondaryContainer.findViewById(currentFragment.getRootId()) == null && backStack.size() > 0) { trans = getSupportFragmentManager().beginTransaction(); trans.remove(currentFragment); trans.show(backStack.get(backStack.size() - 1)); @@ -419,9 +387,9 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte } lastSelectedPosition = savedInstanceState.getInt(Constants.FRAGMENT_POSITION); - if(lastSelectedPosition != 0) { + if (lastSelectedPosition != 0) { MenuItem item = drawerList.getMenu().findItem(lastSelectedPosition); - if(item != null) { + if (item != null) { item.setChecked(true); } } @@ -437,26 +405,27 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte public boolean onCreateOptionsMenu(Menu menu) { MenuInflater menuInflater = getMenuInflater(); SubsonicFragment currentFragment = getCurrentFragment(); - if(currentFragment != null) { + if (currentFragment != null) { try { SubsonicFragment fragment = getCurrentFragment(); fragment.setContext(this); fragment.onCreateOptionsMenu(menu, menuInflater); - if(isTouchscreen()) { + if (isTouchscreen()) { menu.setGroupVisible(R.id.not_touchscreen, false); } - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Error on creating options menu", e); } } return true; } + @Override public boolean onOptionsItemSelected(MenuItem item) { - if(drawerToggle != null && drawerToggle.onOptionsItemSelected(item)) { + if (drawerToggle != null && drawerToggle.onOptionsItemSelected(item)) { return true; - } else if(item.getItemId() == android.R.id.home) { + } else if (item.getItemId() == android.R.id.home) { onBackPressed(); return true; } @@ -464,22 +433,14 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte return getCurrentFragment().onOptionsItemSelected(item); } - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - boolean isVolumeDown = keyCode == KeyEvent.KEYCODE_VOLUME_DOWN; - boolean isVolumeUp = keyCode == KeyEvent.KEYCODE_VOLUME_UP; - boolean isVolumeAdjust = isVolumeDown || isVolumeUp; - - return super.onKeyDown(keyCode, event); - } - @Override public void setTitle(CharSequence title) { - if(title != null && getSupportActionBar() != null && !title.equals(getSupportActionBar().getTitle())) { + if (title != null && getSupportActionBar() != null && !title.equals(getSupportActionBar().getTitle())) { getSupportActionBar().setTitle(title); recreateSpinner(); } } + public void setSubtitle(CharSequence title) { getSupportActionBar().setSubtitle(title); } @@ -487,8 +448,8 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { int top = spinnerAdapter.getCount() - 1; - if(position < top) { - for(int i = top; i > position && i >= 0; i--) { + if (position < top) { + for (int i = top; i > position && i >= 0; i--) { removeCurrent(); } } @@ -503,17 +464,10 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte drawerList.getMenu().clear(); drawerList.inflateMenu(R.menu.drawer_navigation); - SharedPreferences prefs = Util.getPreferences(this); - boolean sharedEnabled = prefs.getBoolean(Constants.PREFERENCES_KEY_SHARED_ENABLED, true) && !Util.isOffline(this); - MenuItem offlineMenuItem = drawerList.getMenu().findItem(R.id.drawer_offline); - if(Util.isOffline(this)) { - if(lastSelectedPosition == 0 || lastSelectedPosition == R.id.drawer_library) { - String newFragment = Util.openToTab(this); - if(newFragment == null || "Library".equals(newFragment)) { - newFragment = "Artist"; - } - + if (Util.isOffline(this)) { + if (lastSelectedPosition == 0 || lastSelectedPosition == R.id.drawer_library) { + String newFragment = "Artist"; lastSelectedPosition = getDrawerItemId(newFragment); drawerItemSelected(newFragment); } @@ -523,9 +477,9 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte offlineMenuItem.setTitle(R.string.main_offline); } - if(lastSelectedPosition != 0) { + if (lastSelectedPosition != 0) { MenuItem item = drawerList.getMenu().findItem(lastSelectedPosition); - if(item != null) { + if (item != null) { item.setChecked(true); } } @@ -533,14 +487,15 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte showingTabs = true; } + private void populateServers() { drawerList.getMenu().clear(); int serverCount = Util.getServerCount(this); int activeServer = Util.getActiveServer(this); - for(int i = 1; i <= serverCount; i++) { + for (int i = 1; i <= serverCount; i++) { MenuItem item = drawerList.getMenu().add(MENU_GROUP_SERVER, MENU_ITEM_SERVER_BASE + i, MENU_ITEM_SERVER_BASE + i, Util.getServerName(this, i)); - if(activeServer == i) { + if (activeServer == i) { item.setChecked(true); } } @@ -549,52 +504,40 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte showingTabs = false; } - private void setDrawerItemVisible(int id, boolean visible) { - MenuItem item = drawerList.getMenu().findItem(id); - if(item != null) { + + private void setDrawerItemVisible(boolean visible) { + MenuItem item = drawerList.getMenu().findItem(R.id.drawer_downloading); + if (item != null) { item.setVisible(visible); } } - protected void drawerItemSelected(String fragmentType) { - if(currentFragment != null) { + void drawerItemSelected(String fragmentType) { + if (currentFragment != null) { currentFragment.stopActionMode(); } startFragmentActivity(fragmentType); } - public void startFragmentActivity(String fragmentType) { + void startFragmentActivity(String fragmentType) { Intent intent = new Intent(); intent.setClass(SubsonicActivity.this, SubsonicFragmentActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - if(!"".equals(fragmentType)) { + if (!"".equals(fragmentType)) { intent.putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, fragmentType); } - if(lastSelectedPosition != 0) { + if (lastSelectedPosition != 0) { intent.putExtra(Constants.FRAGMENT_POSITION, lastSelectedPosition); } startActivity(intent); finish(); } - protected void exit() { - if(((Object) this).getClass() != SubsonicFragmentActivity.class) { - Intent intent = new Intent(this, SubsonicFragmentActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); - intent.putExtra(Constants.INTENT_EXTRA_NAME_EXIT, true); - Util.startActivityWithoutTransition(this, intent); - } else { - finished = true; - this.stopService(new Intent(this, DownloadService.class)); - this.finish(); - } - } - - public boolean onBackPressedSupport() { - if(drawerOpen) { + boolean onBackPressedSupport() { + if (drawerOpen) { drawer.closeDrawers(); return false; - } else if(backStack.size() > 0) { + } else if (backStack.size() > 0) { removeCurrent(); return false; } else { @@ -604,7 +547,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte @Override public void onBackPressed() { - if(onBackPressedSupport()) { + if (onBackPressedSupport()) { super.onBackPressed(); } } @@ -613,12 +556,13 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte return this.currentFragment; } - public void replaceFragment(SubsonicFragment fragment, int tag) { + void replaceFragment(SubsonicFragment fragment, int tag) { replaceFragment(fragment, tag, false); } + public void replaceFragment(SubsonicFragment fragment, int tag, boolean replaceCurrent) { SubsonicFragment oldFragment = currentFragment; - if(currentFragment != null) { + if (currentFragment != null) { currentFragment.setPrimaryFragment(false, secondaryContainer != null); } backStack.add(currentFragment); @@ -627,7 +571,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte currentFragment.setPrimaryFragment(true); supportInvalidateOptionsMenu(); - if(secondaryContainer == null || oldFragment.isAlwaysFullscreen() || currentFragment.isAlwaysStartFullscreen()) { + if (secondaryContainer == null || oldFragment.isAlwaysFullscreen() || currentFragment.isAlwaysStartFullscreen()) { FragmentTransaction trans = getSupportFragmentManager().beginTransaction(); trans.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right); trans.hide(oldFragment); @@ -640,16 +584,13 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte FragmentTransaction trans = getSupportFragmentManager().beginTransaction(); // Check to see if you need to put on top of old left or not - if(backStack.size() > 1) { + if (backStack.size() > 1) { // Move old right to left if there is a backstack already SubsonicFragment newLeftFragment = backStack.get(backStack.size() - 1); - if(replaceCurrent) { - // trans.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right); - } trans.remove(newLeftFragment); // Only move right to left if replaceCurrent is false - if(!replaceCurrent) { + if (!replaceCurrent) { SubsonicFragment oldLeftFragment = backStack.get(backStack.size() - 2); oldLeftFragment.setSecondaryFragment(false); // trans.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right); @@ -679,13 +620,14 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte } recreateSpinner(); } + public void removeCurrent() { // Don't try to remove current if there is no backstack to remove from - if(backStack.isEmpty()) { + if (backStack.isEmpty()) { return; } - if(currentFragment != null) { + if (currentFragment != null) { currentFragment.setPrimaryFragment(false); } SubsonicFragment oldFragment = currentFragment; @@ -694,7 +636,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte currentFragment.setPrimaryFragment(true, false); supportInvalidateOptionsMenu(); - if(secondaryContainer == null || currentFragment.isAlwaysFullscreen() || oldFragment.isAlwaysStartFullscreen()) { + if (secondaryContainer == null || currentFragment.isAlwaysFullscreen() || oldFragment.isAlwaysStartFullscreen()) { FragmentTransaction trans = getSupportFragmentManager().beginTransaction(); trans.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_left); trans.remove(oldFragment); @@ -708,7 +650,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte trans.remove(oldFragment); // Only switch places if there is a backstack, otherwise primary container is correct - if(backStack.size() > 0 && !backStack.get(backStack.size() - 1).isAlwaysFullscreen() && !currentFragment.isAlwaysStartFullscreen()) { + if (backStack.size() > 0 && !backStack.get(backStack.size() - 1).isAlwaysFullscreen() && !currentFragment.isAlwaysStartFullscreen()) { trans.setCustomAnimations(0, 0, 0, 0); // Add current left fragment to right side trans.remove(currentFragment); @@ -735,20 +677,10 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte } recreateSpinner(); } - public void replaceExistingFragment(SubsonicFragment fragment, int tag) { - FragmentTransaction trans = getSupportFragmentManager().beginTransaction(); - trans.remove(currentFragment); - trans.add(R.id.fragment_container, fragment, tag + ""); - trans.commit(); - - currentFragment = fragment; - currentFragment.setPrimaryFragment(true); - supportInvalidateOptionsMenu(); - } public void invalidate() { - if(currentFragment != null) { - while(backStack.size() > 0) { + if (currentFragment != null) { + while (backStack.size() > 0) { removeCurrent(); } @@ -759,26 +691,26 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte supportInvalidateOptionsMenu(); } - protected void recreateSpinner() { - if(currentFragment == null || currentFragment.getTitle() == null) { + void recreateSpinner() { + if (currentFragment == null || currentFragment.getTitle() == null) { return; } - if(spinnerAdapter == null || getSupportActionBar().getCustomView() == null) { + if (spinnerAdapter == null || getSupportActionBar().getCustomView() == null) { createCustomActionBarView(); } - if(backStack.size() > 0) { + if (backStack.size() > 0) { createCustomActionBarView(); spinnerAdapter.clear(); - for(int i = 0; i < backStack.size(); i++) { + for (int i = 0; i < backStack.size(); i++) { CharSequence title = backStack.get(i).getTitle(); - if(title != null) { + if (title != null) { spinnerAdapter.add(title); } else { spinnerAdapter.add("null"); } } - if(currentFragment.getTitle() != null) { + if (currentFragment.getTitle() != null) { spinnerAdapter.add(currentFragment.getTitle()); } else { spinnerAdapter.add("null"); @@ -788,7 +720,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte getSupportActionBar().setDisplayShowTitleEnabled(false); getSupportActionBar().setDisplayShowCustomEnabled(true); - if(drawerToggle.isDrawerIndicatorEnabled()) { + if (drawerToggle.isDrawerIndicatorEnabled()) { getSupportActionBar().setDisplayHomeAsUpEnabled(false); drawerToggle.setDrawerIndicatorEnabled(false); getSupportActionBar().setDisplayHomeAsUpEnabled(true); @@ -801,19 +733,10 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte } } - protected void restart() { - restart(true); - } - protected void restart(boolean resumePosition) { + private void restart() { Intent intent = new Intent(this, this.getClass()); intent.putExtras(getIntent()); - if(resumePosition) { - intent.putExtra(Constants.FRAGMENT_POSITION, lastSelectedPosition); - } else { - String fragmentType = Util.openToTab(this); - intent.putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, fragmentType); - intent.putExtra(Constants.FRAGMENT_POSITION, getDrawerItemId(fragmentType)); - } + intent.putExtra(Constants.FRAGMENT_POSITION, lastSelectedPosition); finish(); Util.startActivityWithoutTransition(this, intent); } @@ -821,7 +744,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte private void applyTheme() { theme = ThemeUtil.getTheme(this); - if(theme != null && theme.indexOf("fullscreen") != -1) { + if (theme != null && theme.contains("fullscreen")) { theme = theme.substring(0, theme.indexOf("_fullscreen")); ThemeUtil.setTheme(this, theme); } @@ -829,9 +752,10 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte ThemeUtil.applyTheme(this, theme); actionbarColored = Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_COLOR_ACTION_BAR, true); } + private void applyFullscreen() { fullScreen = Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_FULL_SCREEN, false); - if(fullScreen ) { + if (fullScreen) { int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; @@ -851,15 +775,10 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte } return IMAGE_LOADER; } - public synchronized static ImageLoader getStaticImageLoader(Context context) { - if (IMAGE_LOADER == null) { - IMAGE_LOADER = new ImageLoader(context); - } - return IMAGE_LOADER; - } public DownloadService getDownloadService() { - if(finished) { + boolean finished = false; + if (finished) { return null; } @@ -875,42 +794,35 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte } final DownloadService downloadService = DownloadService.getInstance(); - if(downloadService != null && afterServiceAvailable.size() > 0) { - for(Runnable runnable: afterServiceAvailable) { + if (downloadService != null && afterServiceAvailable.size() > 0) { + for (Runnable runnable : afterServiceAvailable) { handler.post(runnable); } afterServiceAvailable.clear(); } return downloadService; } + public void runWhenServiceAvailable(Runnable runnable) { - if(getDownloadService() != null) { + if (getDownloadService() != null) { runnable.run(); } else { afterServiceAvailable.add(runnable); checkIfServiceAvailable(); } } + private void checkIfServiceAvailable() { - if(getDownloadService() == null) { - handler.postDelayed(new Runnable() { - @Override - public void run() { - checkIfServiceAvailable(); - } - }, 50); - } else if(afterServiceAvailable.size() > 0) { - for(Runnable runnable: afterServiceAvailable) { + if (getDownloadService() == null) { + handler.postDelayed(this::checkIfServiceAvailable, 50); + } else if (afterServiceAvailable.size() > 0) { + for (Runnable runnable : afterServiceAvailable) { handler.post(runnable); } afterServiceAvailable.clear(); } } - public static String getThemeName() { - return theme; - } - public boolean isTouchscreen() { return touchscreen; } @@ -918,11 +830,12 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte public void openNowPlaying() { } + public void closeNowPlaying() { } - public void setActiveServer(int instance) { + private void setActiveServer(int instance) { if (Util.getActiveServer(this) != instance) { final DownloadService service = getDownloadService(); if (service != null) { @@ -937,12 +850,13 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte } Util.setActiveServer(this, instance); invalidate(); - UserUtil.refreshCurrentUser(this, false, true); + UserUtil.refreshCurrentUser(this); updateDrawerHeader(); } } - public void updateDrawerHeader() { - if(Util.isOffline(this)) { + + private void updateDrawerHeader() { + if (Util.isOffline(this)) { drawerServerName.setText(R.string.select_album_offline); drawerUserName.setText(""); drawerHeader.setClickable(false); @@ -955,7 +869,7 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte } } - public void toggleOffline() { + private void toggleOffline() { boolean isOffline = Util.isOffline(this); Util.setOffline(this, !isOffline); invalidate(); @@ -969,12 +883,12 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte drawer.closeDrawers(); } - public int getDrawerItemId(String fragmentType) { - if(fragmentType == null) { + int getDrawerItemId(String fragmentType) { + if (fragmentType == null) { return R.id.drawer_library; } - switch(fragmentType) { + switch (fragmentType) { case "Artist": return R.id.drawer_library; case "Playlist": @@ -1013,7 +927,6 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte PackageInfo packageInfo = context.getPackageManager().getPackageInfo("net.nullsum.audinaut", 0); file = new File(Environment.getExternalStorageDirectory(), "audinaut-stacktrace.txt"); printWriter = new PrintWriter(file); - printWriter.println("Android API level: " + Build.VERSION.SDK); printWriter.println("Subsonic version name: " + packageInfo.versionName); printWriter.println("Subsonic version code: " + packageInfo.versionCode); printWriter.println(); diff --git a/app/src/main/java/net/nullsum/audinaut/activity/SubsonicFragmentActivity.java b/app/src/main/java/net/nullsum/audinaut/activity/SubsonicFragmentActivity.java index c1839dc..7ad2700 100644 --- a/app/src/main/java/net/nullsum/audinaut/activity/SubsonicFragmentActivity.java +++ b/app/src/main/java/net/nullsum/audinaut/activity/SubsonicFragmentActivity.java @@ -20,42 +20,28 @@ package net.nullsum.audinaut.activity; import android.accounts.Account; import android.accounts.AccountManager; -import android.app.Dialog; import android.content.ContentResolver; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.TypedArray; import android.os.Bundle; -import android.os.Handler; import android.preference.PreferenceManager; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; -import android.support.v7.app.AlertDialog; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; -import android.widget.CheckBox; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; -import com.sothree.slidinguppanel.SlidingUpPanelLayout.PanelState; import com.sothree.slidinguppanel.SlidingUpPanelLayout; - -import java.io.File; -import java.util.Date; -import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; +import com.sothree.slidinguppanel.SlidingUpPanelLayout.PanelState; import net.nullsum.audinaut.R; import net.nullsum.audinaut.domain.MusicDirectory; -import net.nullsum.audinaut.domain.PlayerQueue; import net.nullsum.audinaut.domain.PlayerState; import net.nullsum.audinaut.fragments.DownloadFragment; import net.nullsum.audinaut.fragments.NowPlayingFragment; @@ -66,8 +52,6 @@ import net.nullsum.audinaut.fragments.SelectPlaylistFragment; import net.nullsum.audinaut.fragments.SubsonicFragment; import net.nullsum.audinaut.service.DownloadFile; import net.nullsum.audinaut.service.DownloadService; -import net.nullsum.audinaut.service.MusicService; -import net.nullsum.audinaut.service.MusicServiceFactory; import net.nullsum.audinaut.updates.Updater; import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.FileUtil; @@ -75,15 +59,16 @@ import net.nullsum.audinaut.util.SilentBackgroundTask; import net.nullsum.audinaut.util.UserUtil; import net.nullsum.audinaut.util.Util; +import java.io.File; +import java.util.List; + /** * Created by Scott on 10/14/13. */ public class SubsonicFragmentActivity extends SubsonicActivity implements DownloadService.OnSongChangedListener { - private static String TAG = SubsonicFragmentActivity.class.getSimpleName(); + private static final String TAG = SubsonicFragmentActivity.class.getSimpleName(); private static boolean infoDialogDisplayed; private static boolean sessionInitialized = false; - private static long ALLOWED_SKEW = 30000L; - private SlidingUpPanelLayout slideUpPanel; private SlidingUpPanelLayout.PanelSlideListener panelSlideListener; private boolean isPanelClosing = false; @@ -97,9 +82,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo private TextView trackView; private TextView artistView; private ImageButton startButton; - private long lastBackPressTime = 0; private DownloadFile currentPlaying; - private PlayerState currentState; private ImageButton previousButton; private ImageButton nextButton; private ImageButton rewindButton; @@ -107,14 +90,12 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo @Override public void onCreate(Bundle savedInstanceState) { - if(savedInstanceState == null) { + if (savedInstanceState == null) { String fragmentType = getIntent().getStringExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE); boolean firstRun = false; if (fragmentType == null) { - fragmentType = Util.openToTab(this); - if (fragmentType != null) { - firstRun = true; - } + fragmentType = "Library"; + firstRun = true; } if ("".equals(fragmentType) || fragmentType == null || firstRun) { @@ -130,7 +111,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo stopService(new Intent(this, DownloadService.class)); finish(); getImageLoader().clearCache(); - } else if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW)) { + } else if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW)) { getIntent().putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, "Download"); lastSelectedPosition = R.id.drawer_downloading; } @@ -138,17 +119,13 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo if (findViewById(R.id.fragment_container) != null && savedInstanceState == null) { String fragmentType = getIntent().getStringExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE); - if(fragmentType == null) { - fragmentType = Util.openToTab(this); - if(fragmentType != null) { - getIntent().putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, fragmentType); - lastSelectedPosition = getDrawerItemId(fragmentType); - } else { - lastSelectedPosition = R.id.drawer_library; - } + if (fragmentType == null) { + fragmentType = "Library"; + getIntent().putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, fragmentType); + lastSelectedPosition = getDrawerItemId(fragmentType); MenuItem item = drawerList.getMenu().findItem(lastSelectedPosition); - if(item != null) { + if (item != null) { item.setChecked(true); } } else { @@ -156,9 +133,9 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo } currentFragment = getNewFragment(fragmentType); - if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_ID)) { + if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_ID)) { Bundle currentArguments = currentFragment.getArguments(); - if(currentArguments == null) { + if (currentArguments == null) { currentArguments = new Bundle(); } currentArguments.putString(Constants.INTENT_EXTRA_NAME_ID, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ID)); @@ -167,14 +144,14 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo currentFragment.setPrimaryFragment(true); getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, currentFragment, currentFragment.getSupportTag() + "").commit(); - if(getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY) != null) { + if (getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY) != null) { SearchFragment fragment = new SearchFragment(); replaceFragment(fragment, fragment.getSupportTag()); } // If a album type is set, switch to that album type view String albumType = getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE); - if(albumType != null) { + if (albumType != null) { SubsonicFragment fragment = new SelectDirectoryFragment(); Bundle args = new Bundle(); @@ -187,7 +164,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo } } - slideUpPanel = (SlidingUpPanelLayout) findViewById(R.id.slide_up_panel); + slideUpPanel = findViewById(R.id.slide_up_panel); panelSlideListener = new SlidingUpPanelLayout.PanelSlideListener() { @Override public void onPanelSlide(View panel, float slideOffset) { @@ -198,7 +175,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo public void onPanelStateChanged(View panel, PanelState previousState, PanelState newState) { if (newState == PanelState.COLLAPSED) { isPanelClosing = false; - if(bottomBar.getVisibility() == View.GONE) { + if (bottomBar.getVisibility() == View.GONE) { bottomBar.setVisibility(View.VISIBLE); nowPlayingToolbar.setVisibility(View.GONE); nowPlayingFragment.setPrimaryFragment(false); @@ -217,7 +194,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo nowPlayingToolbar.setVisibility(View.VISIBLE); setSupportActionBar(nowPlayingToolbar); - if(secondaryFragment == null) { + if (secondaryFragment == null) { nowPlayingFragment.setPrimaryFragment(true); } else { secondaryFragment.setPrimaryFragment(true); @@ -230,24 +207,19 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo }; slideUpPanel.addPanelSlideListener(panelSlideListener); - if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD)) { + if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD)) { // Post this later so it actually runs - handler.postDelayed(new Runnable() { - @Override - public void run() { - openNowPlaying(); - } - }, 200); + handler.postDelayed(this::openNowPlaying, 200); getIntent().removeExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD); } bottomBar = findViewById(R.id.bottom_bar); - mainToolbar = (Toolbar) findViewById(R.id.main_toolbar); - nowPlayingToolbar = (Toolbar) findViewById(R.id.now_playing_toolbar); - coverArtView = (ImageView) bottomBar.findViewById(R.id.album_art); - trackView = (TextView) bottomBar.findViewById(R.id.track_name); - artistView = (TextView) bottomBar.findViewById(R.id.artist_name); + mainToolbar = findViewById(R.id.main_toolbar); + nowPlayingToolbar = findViewById(R.id.now_playing_toolbar); + coverArtView = bottomBar.findViewById(R.id.album_art); + trackView = bottomBar.findViewById(R.id.track_name); + artistView = bottomBar.findViewById(R.id.artist_name); setSupportActionBar(mainToolbar); @@ -258,97 +230,72 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo trans.commit(); } - rewindButton = (ImageButton) findViewById(R.id.download_rewind); - rewindButton.setOnClickListener(new View.OnClickListener() { + rewindButton = findViewById(R.id.download_rewind); + rewindButton.setOnClickListener(v -> new SilentBackgroundTask(SubsonicFragmentActivity.this) { @Override - public void onClick(View v) { - new SilentBackgroundTask(SubsonicFragmentActivity.this) { - @Override - protected Void doInBackground() throws Throwable { - if (getDownloadService() == null) { - return null; - } + protected Void doInBackground() throws Throwable { + if (getDownloadService() == null) { + return null; + } - getDownloadService().rewind(); - return null; - } - }.execute(); + getDownloadService().rewind(); + return null; } - }); + }.execute()); - previousButton = (ImageButton) findViewById(R.id.download_previous); - previousButton.setOnClickListener(new View.OnClickListener() { + previousButton = findViewById(R.id.download_previous); + previousButton.setOnClickListener(v -> new SilentBackgroundTask(SubsonicFragmentActivity.this) { @Override - public void onClick(View v) { - new SilentBackgroundTask(SubsonicFragmentActivity.this) { - @Override - protected Void doInBackground() throws Throwable { - if(getDownloadService() == null) { - return null; - } + protected Void doInBackground() throws Throwable { + if (getDownloadService() == null) { + return null; + } - getDownloadService().previous(); - return null; - } - }.execute(); + getDownloadService().previous(); + return null; } - }); + }.execute()); - startButton = (ImageButton) findViewById(R.id.download_start); - startButton.setOnClickListener(new View.OnClickListener() { + startButton = findViewById(R.id.download_start); + startButton.setOnClickListener(v -> new SilentBackgroundTask(SubsonicFragmentActivity.this) { @Override - public void onClick(View v) { - new SilentBackgroundTask(SubsonicFragmentActivity.this) { - @Override - protected Void doInBackground() throws Throwable { - PlayerState state = getDownloadService().getPlayerState(); - if(state == PlayerState.STARTED) { - getDownloadService().pause(); - } else { - getDownloadService().start(); - } + protected Void doInBackground() throws Throwable { + PlayerState state = getDownloadService().getPlayerState(); + if (state == PlayerState.STARTED) { + getDownloadService().pause(); + } else { + getDownloadService().start(); + } - return null; - } - }.execute(); + return null; } - }); + }.execute()); - nextButton = (ImageButton) findViewById(R.id.download_next); - nextButton.setOnClickListener(new View.OnClickListener() { + nextButton = findViewById(R.id.download_next); + nextButton.setOnClickListener(v -> new SilentBackgroundTask(SubsonicFragmentActivity.this) { @Override - public void onClick(View v) { - new SilentBackgroundTask(SubsonicFragmentActivity.this) { - @Override - protected Void doInBackground() throws Throwable { - if(getDownloadService() == null) { - return null; - } + protected Void doInBackground() throws Throwable { + if (getDownloadService() == null) { + return null; + } - getDownloadService().next(); - return null; - } - }.execute(); + getDownloadService().next(); + return null; } - }); + }.execute()); - fastforwardButton = (ImageButton) findViewById(R.id.download_fastforward); - fastforwardButton.setOnClickListener(new View.OnClickListener() { + fastforwardButton = findViewById(R.id.download_fastforward); + fastforwardButton.setOnClickListener(v -> new SilentBackgroundTask(SubsonicFragmentActivity.this) { @Override - public void onClick(View v) { - new SilentBackgroundTask(SubsonicFragmentActivity.this) { - @Override - protected Void doInBackground() throws Throwable { - if (getDownloadService() == null) { - return null; - } + protected Void doInBackground() throws Throwable { + if (getDownloadService() == null) { + return null; + } - getDownloadService().fastForward(); - return null; - } - }.execute(); + getDownloadService().fastForward(); + return null; } - }); + }.execute()); } @Override @@ -363,17 +310,17 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo public void onNewIntent(Intent intent) { super.onNewIntent(intent); - if(currentFragment != null && intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY) != null) { - if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { + if (currentFragment != null && intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY) != null) { + if (slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { closeNowPlaying(); } - if(currentFragment instanceof SearchFragment) { + if (currentFragment instanceof SearchFragment) { String query = intent.getStringExtra(Constants.INTENT_EXTRA_NAME_QUERY); boolean autoplay = intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_AUTOPLAY, false); if (query != null) { - ((SearchFragment)currentFragment).search(query, autoplay); + ((SearchFragment) currentFragment).search(query, autoplay); } getIntent().removeExtra(Constants.INTENT_EXTRA_NAME_QUERY); } else { @@ -382,17 +329,17 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo SearchFragment fragment = new SearchFragment(); replaceFragment(fragment, fragment.getSupportTag()); } - } else if(intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, false)) { - if(slideUpPanel.getPanelState() != SlidingUpPanelLayout.PanelState.EXPANDED) { + } else if (intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, false)) { + if (slideUpPanel.getPanelState() != SlidingUpPanelLayout.PanelState.EXPANDED) { openNowPlaying(); } } else { - if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { + if (slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { closeNowPlaying(); } setIntent(intent); } - if(drawer != null) { + if (drawer != null) { drawer.closeDrawers(); } } @@ -401,16 +348,16 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo public void onResume() { super.onResume(); - if(getIntent().hasExtra(Constants.INTENT_EXTRA_VIEW_ALBUM)) { + if (getIntent().hasExtra(Constants.INTENT_EXTRA_VIEW_ALBUM)) { SubsonicFragment fragment = new SelectDirectoryFragment(); Bundle args = new Bundle(); args.putString(Constants.INTENT_EXTRA_NAME_ID, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_ID)); args.putString(Constants.INTENT_EXTRA_NAME_NAME, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_NAME)); args.putString(Constants.INTENT_EXTRA_SEARCH_SONG, getIntent().getStringExtra(Constants.INTENT_EXTRA_SEARCH_SONG)); - if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_ARTIST)) { + if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_ARTIST)) { args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true); } - if(getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_CHILD_ID)) { + if (getIntent().hasExtra(Constants.INTENT_EXTRA_NAME_CHILD_ID)) { args.putString(Constants.INTENT_EXTRA_NAME_CHILD_ID, getIntent().getStringExtra(Constants.INTENT_EXTRA_NAME_CHILD_ID)); } fragment.setArguments(args); @@ -421,19 +368,14 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo UserUtil.seedCurrentUser(this); createAccount(); - runWhenServiceAvailable(new Runnable() { - @Override - public void run() { - getDownloadService().addOnSongChangedListener(SubsonicFragmentActivity.this, true); - } - }); + runWhenServiceAvailable(() -> getDownloadService().addOnSongChangedListener(SubsonicFragmentActivity.this)); } @Override public void onPause() { super.onPause(); DownloadService downloadService = getDownloadService(); - if(downloadService != null) { + if (downloadService != null) { downloadService.removeOnSongChangeListener(this); } } @@ -442,11 +384,12 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo public void onSaveInstanceState(Bundle savedInstanceState) { super.onSaveInstanceState(savedInstanceState); savedInstanceState.putString(Constants.MAIN_NOW_PLAYING, nowPlayingFragment.getTag()); - if(secondaryFragment != null) { + if (secondaryFragment != null) { savedInstanceState.putString(Constants.MAIN_NOW_PLAYING_SECONDARY, secondaryFragment.getTag()); } savedInstanceState.putInt(Constants.MAIN_SLIDE_PANEL_STATE, slideUpPanel.getPanelState().hashCode()); } + @Override public void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); @@ -456,7 +399,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo nowPlayingFragment = (NowPlayingFragment) fm.findFragmentByTag(id); String secondaryId = savedInstanceState.getString(Constants.MAIN_NOW_PLAYING_SECONDARY); - if(secondaryId != null) { + if (secondaryId != null) { secondaryFragment = (SubsonicFragment) fm.findFragmentByTag(secondaryId); nowPlayingFragment.setPrimaryFragment(false); @@ -467,11 +410,11 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo trans.commit(); } - if(drawerToggle != null && backStack.size() > 0) { + if (drawerToggle != null && backStack.size() > 0) { drawerToggle.setDrawerIndicatorEnabled(false); } - if(savedInstanceState.getInt(Constants.MAIN_SLIDE_PANEL_STATE, -1) == SlidingUpPanelLayout.PanelState.EXPANDED.hashCode()) { + if (savedInstanceState.getInt(Constants.MAIN_SLIDE_PANEL_STATE, -1) == SlidingUpPanelLayout.PanelState.EXPANDED.hashCode()) { panelSlideListener.onPanelStateChanged(null, null, PanelState.EXPANDED); } } @@ -479,28 +422,23 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo @Override public void setContentView(int viewId) { super.setContentView(viewId); - if(drawerToggle != null){ + if (drawerToggle != null) { drawerToggle.setDrawerIndicatorEnabled(true); } } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - return super.onOptionsItemSelected(item); - } - @Override public void onBackPressed() { - if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED && secondaryFragment == null) { + if (slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED && secondaryFragment == null) { slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); - } else if(onBackPressedSupport()) { + } else if (onBackPressedSupport()) { finish(); } } @Override - public boolean onBackPressedSupport() { - if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { + boolean onBackPressedSupport() { + if (slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { removeCurrent(); return false; } else { @@ -510,8 +448,8 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo @Override public SubsonicFragment getCurrentFragment() { - if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { - if(secondaryFragment == null) { + if (slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { + if (secondaryFragment == null) { return nowPlayingFragment; } else { return secondaryFragment; @@ -523,7 +461,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo @Override public void replaceFragment(SubsonicFragment fragment, int tag, boolean replaceCurrent) { - if(slideUpPanel != null && slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED && !isPanelClosing) { + if (slideUpPanel != null && slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED && !isPanelClosing) { secondaryFragment = fragment; nowPlayingFragment.setPrimaryFragment(false); secondaryFragment.setPrimaryFragment(true); @@ -538,9 +476,10 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo super.replaceFragment(fragment, tag, replaceCurrent); } } + @Override public void removeCurrent() { - if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED && secondaryFragment != null) { + if (slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED && secondaryFragment != null) { FragmentTransaction trans = getSupportFragmentManager().beginTransaction(); trans.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_left); trans.remove(secondaryFragment); @@ -557,7 +496,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo @Override public void setTitle(CharSequence title) { - if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { + if (slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { getSupportActionBar().setTitle(title); } else { super.setTitle(title); @@ -568,7 +507,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo protected void drawerItemSelected(String fragmentType) { super.drawerItemSelected(fragmentType); - if(slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { + if (slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED) { slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); } } @@ -579,7 +518,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo FragmentTransaction trans = getSupportFragmentManager().beginTransaction(); // Clear existing stack - for(int i = backStack.size() - 1; i >= 0; i--) { + for (int i = backStack.size() - 1; i >= 0; i--) { trans.remove(backStack.get(i)); } trans.remove(currentFragment); @@ -594,14 +533,14 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo trans.commit(); supportInvalidateOptionsMenu(); recreateSpinner(); - if(drawer != null) { + if (drawer != null) { drawer.closeDrawers(); } - if(secondaryContainer != null) { + if (secondaryContainer != null) { secondaryContainer.setVisibility(View.GONE); } - if(drawerToggle != null) { + if (drawerToggle != null) { drawerToggle.setDrawerIndicatorEnabled(true); } } @@ -610,6 +549,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo public void openNowPlaying() { slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED); } + @Override public void closeNowPlaying() { slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED); @@ -617,25 +557,24 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo } private SubsonicFragment getNewFragment(String fragmentType) { - if("Artist".equals(fragmentType)) { + if ("Artist".equals(fragmentType)) { return new SelectArtistFragment(); - } else if("Playlist".equals(fragmentType)) { + } else if ("Playlist".equals(fragmentType)) { return new SelectPlaylistFragment(); - } else if("Download".equals(fragmentType)) { + } else if ("Download".equals(fragmentType)) { return new DownloadFragment(); } else { return new SelectArtistFragment(); } } - public void checkUpdates() { + private void checkUpdates() { try { String version = getPackageManager().getPackageInfo(getPackageName(), 0).versionName; int ver = Integer.parseInt(version.replace(".", "")); Updater updater = new Updater(ver); updater.checkUpdates(this); - } - catch(Exception e) { + } catch (Exception ignored) { } } @@ -643,12 +582,13 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo private void loadSession() { loadSettings(); // If we are on Subsonic 5.2+, save play queue - if(!Util.isOffline(this)) { + if (!Util.isOffline(this)) { loadRemotePlayQueue(); } sessionInitialized = true; } + private void loadSettings() { PreferenceManager.setDefaultValues(this, R.xml.settings_appearance, false); PreferenceManager.setDefaultValues(this, R.xml.settings_cache, false); @@ -660,9 +600,9 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo } else { String path = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null); File cacheLocation = new File(path); - if(!FileUtil.verifyCanWrite(cacheLocation)) { + if (!FileUtil.verifyCanWrite(cacheLocation)) { // Only warn user if there is a difference saved - if(resetCacheLocation(prefs)) { + if (resetCacheLocation(prefs)) { Util.info(this, R.string.common_warning, R.string.settings_cache_location_reset); } } @@ -679,7 +619,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo editor.putInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1); editor.apply(); } - if(!prefs.contains(Constants.PREFERENCES_KEY_SERVER_COUNT)) { + if (!prefs.contains(Constants.PREFERENCES_KEY_SERVER_COUNT)) { SharedPreferences.Editor editor = prefs.edit(); editor.putInt(Constants.PREFERENCES_KEY_SERVER_COUNT, 1); editor.apply(); @@ -689,7 +629,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo private boolean resetCacheLocation(SharedPreferences prefs) { String newDirectory = FileUtil.getDefaultMusicDirectory(this).getPath(); String oldDirectory = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null); - if(newDirectory == null || (oldDirectory != null && newDirectory.equals(oldDirectory))) { + if (newDirectory == null || (oldDirectory != null && newDirectory.equals(oldDirectory))) { return false; } else { SharedPreferences.Editor editor = prefs.edit(); @@ -700,36 +640,20 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo } private void loadRemotePlayQueue() { - if(Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_RESUME_PLAY_QUEUE_NEVER, false)) { + if (Util.getPreferences(this).getBoolean(Constants.PREFERENCES_KEY_RESUME_PLAY_QUEUE_NEVER, false)) { return; } - - final SubsonicActivity context = this; new SilentBackgroundTask(this) { - private PlayerQueue playerQueue; @Override protected Void doInBackground() throws Throwable { try { - MusicService musicService = MusicServiceFactory.getMusicService(context); - PlayerQueue remoteState = musicService.getPlayQueue(context, null); - // Make sure we wait until download service is ready DownloadService downloadService = getDownloadService(); - while(downloadService == null || !downloadService.isInitialized()) { + while (downloadService == null || !downloadService.isInitialized()) { Util.sleepQuietly(100L); downloadService = getDownloadService(); } - - // If we had a remote state and it's changed is more recent than our existing state - if(remoteState != null && remoteState.changed != null) { - // Check if changed + 30 seconds since some servers have slight skew - Date remoteChange = new Date(remoteState.changed.getTime() - ALLOWED_SKEW); - Date localChange = downloadService.getLastStateChanged(); - if(localChange == null || localChange.before(remoteChange)) { - playerQueue = remoteState; - } - } } catch (Exception e) { Log.e(TAG, "Failed to get playing queue to server", e); } @@ -759,27 +683,18 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo return null; } - - @Override - protected void done(Void result) { - - } }.execute(); } private void showInfoDialog() { if (!infoDialogDisplayed) { infoDialogDisplayed = true; - if (Util.getRestUrl(this, null).contains("demo.subsonic.org")) { + if (Util.getRestUrl(this).contains("demo.subsonic.org")) { Util.info(this, R.string.main_welcome_title, R.string.main_welcome_text); } } } - public Toolbar getActiveToolbar() { - return slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.EXPANDED ? nowPlayingToolbar : mainToolbar; - } - @Override public void onSongChanged(DownloadFile currentPlaying, int currentPlayingIndex) { this.currentPlaying = currentPlaying; @@ -789,7 +704,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo song = currentPlaying.getSong(); trackView.setText(song.getTitle()); - if(song.getArtist() != null) { + if (song.getArtist() != null) { artistView.setVisibility(View.VISIBLE); artistView.setText(song.getArtist()); } else { @@ -820,7 +735,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo @Override public void onSongsChanged(List songs, DownloadFile currentPlaying, int currentPlayingIndex) { - if(this.currentPlaying != currentPlaying || this.currentPlaying == null) { + if (this.currentPlaying != currentPlaying || this.currentPlaying == null) { onSongChanged(currentPlaying, currentPlayingIndex); } } @@ -831,7 +746,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo } @Override - public void onStateUpdate(DownloadFile downloadFile, PlayerState playerState) { + public void onStateUpdate(PlayerState playerState) { int[] attrs = new int[]{(playerState == PlayerState.STARTED) ? R.attr.actionbar_pause : R.attr.actionbar_start}; TypedArray typedArray = this.obtainStyledAttributes(attrs); startButton.setImageResource(typedArray.getResourceId(0, 0)); @@ -840,7 +755,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo @Override public void onMetadataUpdate(MusicDirectory.Entry song, int fieldChange) { - if(song != null && coverArtView != null && fieldChange == DownloadService.METADATA_UPDATED_COVER_ART) { + if (song != null && coverArtView != null && fieldChange == DownloadService.METADATA_UPDATED_COVER_ART) { int height = coverArtView.getHeight(); if (height <= 0) { int[] attrs = new int[]{R.attr.actionBarSize}; @@ -851,7 +766,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo getImageLoader().loadImage(coverArtView, song, false, height, false); // We need to update it immediately since it won't update if updater is not running for it - if(nowPlayingFragment != null && slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) { + if (nowPlayingFragment != null && slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) { nowPlayingFragment.onMetadataUpdate(song, fieldChange); } } diff --git a/app/src/main/java/net/nullsum/audinaut/activity/VoiceQueryReceiverActivity.java b/app/src/main/java/net/nullsum/audinaut/activity/VoiceQueryReceiverActivity.java index 9aea6a1..b8402c6 100644 --- a/app/src/main/java/net/nullsum/audinaut/activity/VoiceQueryReceiverActivity.java +++ b/app/src/main/java/net/nullsum/audinaut/activity/VoiceQueryReceiverActivity.java @@ -24,23 +24,18 @@ import android.app.SearchManager; import android.content.Intent; import android.os.Bundle; import android.provider.MediaStore; -import android.provider.SearchRecentSuggestions; -import android.util.Log; -import net.nullsum.audinaut.fragments.SubsonicFragment; import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.Util; -import net.nullsum.audinaut.provider.AudinautSearchProvider; /** * Receives voice search queries and forwards to the SearchFragment. - * + *

* http://android-developers.blogspot.com/2010/09/supporting-new-music-voice-action.html * * @author Sindre Mehus */ public class VoiceQueryReceiverActivity extends Activity { - private static final String TAG = VoiceQueryReceiverActivity.class.getSimpleName(); @Override public void onCreate(Bundle savedInstanceState) { @@ -57,6 +52,5 @@ public class VoiceQueryReceiverActivity extends Activity { Util.startActivityWithoutTransition(VoiceQueryReceiverActivity.this, intent); } finish(); - Util.disablePendingTransition(this); } } diff --git a/app/src/main/java/net/nullsum/audinaut/adapter/AlphabeticalAlbumAdapter.java b/app/src/main/java/net/nullsum/audinaut/adapter/AlphabeticalAlbumAdapter.java index e91fdd2..f65f8a0 100644 --- a/app/src/main/java/net/nullsum/audinaut/adapter/AlphabeticalAlbumAdapter.java +++ b/app/src/main/java/net/nullsum/audinaut/adapter/AlphabeticalAlbumAdapter.java @@ -17,12 +17,12 @@ package net.nullsum.audinaut.adapter; import android.content.Context; -import java.util.List; - import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.util.ImageLoader; import net.nullsum.audinaut.view.FastScroller; +import java.util.List; + public class AlphabeticalAlbumAdapter extends EntryInfiniteGridAdapter implements FastScroller.BubbleTextGetter { public AlphabeticalAlbumAdapter(Context context, List entries, ImageLoader imageLoader, boolean largeCell) { super(context, entries, imageLoader, largeCell); @@ -31,8 +31,8 @@ public class AlphabeticalAlbumAdapter extends EntryInfiniteGridAdapter implement @Override public String getTextToShowInBubble(int position) { // Make sure that we are not trying to get an item for the loading placeholder - if(position >= sections.get(0).size()) { - if(sections.get(0).size() > 0) { + if (position >= sections.get(0).size()) { + if (sections.get(0).size() > 0) { return getTextToShowInBubble(position - 1); } else { return "*"; diff --git a/app/src/main/java/net/nullsum/audinaut/adapter/ArtistAdapter.java b/app/src/main/java/net/nullsum/audinaut/adapter/ArtistAdapter.java index 64a98ed..9f16cd9 100644 --- a/app/src/main/java/net/nullsum/audinaut/adapter/ArtistAdapter.java +++ b/app/src/main/java/net/nullsum/audinaut/adapter/ArtistAdapter.java @@ -18,17 +18,12 @@ package net.nullsum.audinaut.adapter; import android.content.Context; import android.support.v7.widget.PopupMenu; import android.view.LayoutInflater; -import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; -import java.io.Serializable; -import java.util.List; - import net.nullsum.audinaut.R; import net.nullsum.audinaut.domain.Artist; -import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.domain.MusicDirectory.Entry; import net.nullsum.audinaut.domain.MusicFolder; import net.nullsum.audinaut.util.Util; @@ -37,16 +32,14 @@ import net.nullsum.audinaut.view.FastScroller; import net.nullsum.audinaut.view.SongView; import net.nullsum.audinaut.view.UpdateView; +import java.io.Serializable; +import java.util.List; + public class ArtistAdapter extends SectionAdapter implements FastScroller.BubbleTextGetter { - public static int VIEW_TYPE_SONG = 3; - public static int VIEW_TYPE_ARTIST = 4; - - private List musicFolders; - private OnMusicFolderChanged onMusicFolderChanged; - - public ArtistAdapter(Context context, List artists, OnItemClickedListener listener) { - this(context, artists, null, listener, null); - } + public static final int VIEW_TYPE_ARTIST = 4; + private static final int VIEW_TYPE_SONG = 3; + private final List musicFolders; + private final OnMusicFolderChanged onMusicFolderChanged; public ArtistAdapter(Context context, List artists, List musicFolders, OnItemClickedListener onItemClickedListener, OnMusicFolderChanged onMusicFolderChanged) { super(context, artists); @@ -54,7 +47,7 @@ public class ArtistAdapter extends SectionAdapter implements FastS this.onItemClickedListener = onItemClickedListener; this.onMusicFolderChanged = onMusicFolderChanged; - if(musicFolders != null) { + if (musicFolders != null) { this.singleSectionHeader = true; } } @@ -62,46 +55,41 @@ public class ArtistAdapter extends SectionAdapter implements FastS @Override public UpdateView.UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) { final View header = LayoutInflater.from(context).inflate(R.layout.select_artist_header, parent, false); - header.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - PopupMenu popup = new PopupMenu(context, header.findViewById(R.id.select_artist_folder_2)); + header.setOnClickListener(v -> { + PopupMenu popup = new PopupMenu(context, header.findViewById(R.id.select_artist_folder_2)); - popup.getMenu().add(R.string.select_artist_all_folders); + popup.getMenu().add(R.string.select_artist_all_folders); + for (MusicFolder musicFolder : musicFolders) { + popup.getMenu().add(musicFolder.getName()); + } + + popup.setOnMenuItemClickListener(item -> { for (MusicFolder musicFolder : musicFolders) { - popup.getMenu().add(musicFolder.getName()); - } - - popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - for (MusicFolder musicFolder : musicFolders) { - if(item.getTitle().equals(musicFolder.getName())) { - if(onMusicFolderChanged != null) { - onMusicFolderChanged.onMusicFolderChanged(musicFolder); - } - return true; - } - } - - if(onMusicFolderChanged != null) { - onMusicFolderChanged.onMusicFolderChanged(null); + if (item.getTitle().equals(musicFolder.getName())) { + if (onMusicFolderChanged != null) { + onMusicFolderChanged.onMusicFolderChanged(musicFolder); } return true; } - }); - popup.show(); - } + } + + if (onMusicFolderChanged != null) { + onMusicFolderChanged.onMusicFolderChanged(null); + } + return true; + }); + popup.show(); }); - return new UpdateView.UpdateViewHolder(header, false); + return new UpdateView.UpdateViewHolder(header); } + @Override public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header, int sectionIndex) { - TextView folderName = (TextView) holder.getView().findViewById(R.id.select_artist_folder_2); + TextView folderName = holder.getView().findViewById(R.id.select_artist_folder_2); String musicFolderId = Util.getSelectedMusicFolderId(context); - if(musicFolderId != null) { + if (musicFolderId != null) { for (MusicFolder musicFolder : musicFolders) { if (musicFolder.getId().equals(musicFolderId)) { folderName.setText(musicFolder.getName()); @@ -114,11 +102,11 @@ public class ArtistAdapter extends SectionAdapter implements FastS } @Override - public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) { + public UpdateView.UpdateViewHolder onCreateSectionViewHolder(int viewType) { UpdateView updateView = null; - if(viewType == VIEW_TYPE_ARTIST) { + if (viewType == VIEW_TYPE_ARTIST) { updateView = new ArtistView(context); - } else if(viewType == VIEW_TYPE_SONG) { + } else if (viewType == VIEW_TYPE_SONG) { updateView = new SongView(context); } @@ -128,9 +116,9 @@ public class ArtistAdapter extends SectionAdapter implements FastS @Override public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Serializable item, int viewType) { UpdateView view = holder.getUpdateView(); - if(viewType == VIEW_TYPE_ARTIST) { + if (viewType == VIEW_TYPE_ARTIST) { view.setObject(item); - } else if(viewType == VIEW_TYPE_SONG) { + } else if (viewType == VIEW_TYPE_SONG) { SongView songView = (SongView) view; Entry entry = (Entry) item; songView.setObject(entry, checkable); @@ -139,7 +127,7 @@ public class ArtistAdapter extends SectionAdapter implements FastS @Override public int getItemViewType(Serializable item) { - if(item instanceof Artist) { + if (item instanceof Artist) { return VIEW_TYPE_ARTIST; } else { return VIEW_TYPE_SONG; @@ -149,7 +137,7 @@ public class ArtistAdapter extends SectionAdapter implements FastS @Override public String getTextToShowInBubble(int position) { Object item = getItemForPosition(position); - if(item instanceof Artist) { + if (item instanceof Artist) { return getNameIndex(((Artist) item).getName(), true); } else { return null; diff --git a/app/src/main/java/net/nullsum/audinaut/adapter/BasicListAdapter.java b/app/src/main/java/net/nullsum/audinaut/adapter/BasicListAdapter.java index ae04bca..8912677 100644 --- a/app/src/main/java/net/nullsum/audinaut/adapter/BasicListAdapter.java +++ b/app/src/main/java/net/nullsum/audinaut/adapter/BasicListAdapter.java @@ -16,15 +16,14 @@ package net.nullsum.audinaut.adapter; import android.content.Context; -import android.view.ViewGroup; - -import java.util.List; import net.nullsum.audinaut.view.BasicListView; import net.nullsum.audinaut.view.UpdateView; +import java.util.List; + public class BasicListAdapter extends SectionAdapter { - public static int VIEW_TYPE_LINE = 1; + private static final int VIEW_TYPE_LINE = 1; public BasicListAdapter(Context context, List strings, OnItemClickedListener listener) { super(context, strings); @@ -32,7 +31,7 @@ public class BasicListAdapter extends SectionAdapter { } @Override - public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) { + public UpdateView.UpdateViewHolder onCreateSectionViewHolder(int viewType) { return new UpdateView.UpdateViewHolder(new BasicListView(context)); } diff --git a/app/src/main/java/net/nullsum/audinaut/adapter/DetailsAdapter.java b/app/src/main/java/net/nullsum/audinaut/adapter/DetailsAdapter.java index dcb03f1..d45cad0 100644 --- a/app/src/main/java/net/nullsum/audinaut/adapter/DetailsAdapter.java +++ b/app/src/main/java/net/nullsum/audinaut/adapter/DetailsAdapter.java @@ -16,8 +16,6 @@ package net.nullsum.audinaut.adapter; import android.content.Context; -import android.text.SpannableString; -import android.text.method.LinkMovementMethod; import android.text.util.Linkify; import android.view.LayoutInflater; import android.view.View; @@ -25,32 +23,32 @@ import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView; -import java.util.List; - import net.nullsum.audinaut.R; -public class DetailsAdapter extends ArrayAdapter { - private List headers; - private List details; +import java.util.List; - public DetailsAdapter(Context context, int layout, List headers, List details) { - super(context, layout, headers); +public class DetailsAdapter extends ArrayAdapter { + private final List headers; + private final List details; + + public DetailsAdapter(Context context, List headers, List details) { + super(context, R.layout.details_item, headers); this.headers = headers; this.details = details; } @Override - public View getView(int position, View convertView, ViewGroup parent){ + public View getView(int position, View convertView, ViewGroup parent) { View view; - if(convertView == null) { + if (convertView == null) { view = LayoutInflater.from(getContext()).inflate(R.layout.details_item, null); } else { view = convertView; } - TextView nameView = (TextView) view.findViewById(R.id.detail_name); - TextView detailsView = (TextView) view.findViewById(R.id.detail_value); + TextView nameView = view.findViewById(R.id.detail_name); + TextView detailsView = view.findViewById(R.id.detail_value); nameView.setText(headers.get(position)); diff --git a/app/src/main/java/net/nullsum/audinaut/adapter/DownloadFileAdapter.java b/app/src/main/java/net/nullsum/audinaut/adapter/DownloadFileAdapter.java index 6a1d1dc..131bbea 100644 --- a/app/src/main/java/net/nullsum/audinaut/adapter/DownloadFileAdapter.java +++ b/app/src/main/java/net/nullsum/audinaut/adapter/DownloadFileAdapter.java @@ -18,12 +18,6 @@ package net.nullsum.audinaut.adapter; import android.content.Context; import android.view.Menu; import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; - -import java.util.List; import net.nullsum.audinaut.R; import net.nullsum.audinaut.service.DownloadFile; @@ -32,8 +26,10 @@ import net.nullsum.audinaut.view.FastScroller; import net.nullsum.audinaut.view.SongView; import net.nullsum.audinaut.view.UpdateView; +import java.util.List; + public class DownloadFileAdapter extends SectionAdapter implements FastScroller.BubbleTextGetter { - public static int VIEW_TYPE_DOWNLOAD_FILE = 1; + private static final int VIEW_TYPE_DOWNLOAD_FILE = 1; public DownloadFileAdapter(Context context, List entries, OnItemClickedListener onItemClickedListener) { super(context, entries); @@ -42,7 +38,7 @@ public class DownloadFileAdapter extends SectionAdapter implements } @Override - public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) { + public UpdateView.UpdateViewHolder onCreateSectionViewHolder(int viewType) { return new UpdateView.UpdateViewHolder(new SongView(context)); } @@ -65,7 +61,7 @@ public class DownloadFileAdapter extends SectionAdapter implements @Override public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) { - if(Util.isOffline(context)) { + if (Util.isOffline(context)) { menuInflater.inflate(R.menu.multiselect_nowplaying_offline, menu); } else { menuInflater.inflate(R.menu.multiselect_nowplaying, menu); diff --git a/app/src/main/java/net/nullsum/audinaut/adapter/EntryGridAdapter.java b/app/src/main/java/net/nullsum/audinaut/adapter/EntryGridAdapter.java index 017dfa0..e57ecf8 100644 --- a/app/src/main/java/net/nullsum/audinaut/adapter/EntryGridAdapter.java +++ b/app/src/main/java/net/nullsum/audinaut/adapter/EntryGridAdapter.java @@ -18,11 +18,6 @@ package net.nullsum.audinaut.adapter; import android.content.Context; import android.view.Menu; import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; - -import java.util.List; import net.nullsum.audinaut.R; import net.nullsum.audinaut.domain.MusicDirectory; @@ -34,19 +29,17 @@ import net.nullsum.audinaut.view.SongView; import net.nullsum.audinaut.view.UpdateView; import net.nullsum.audinaut.view.UpdateView.UpdateViewHolder; +import java.util.List; + public class EntryGridAdapter extends SectionAdapter { - private static String TAG = EntryGridAdapter.class.getSimpleName(); - - public static int VIEW_TYPE_ALBUM_CELL = 1; - public static int VIEW_TYPE_ALBUM_LINE = 2; - public static int VIEW_TYPE_SONG = 3; - - private ImageLoader imageLoader; - private boolean largeAlbums; + public static final int VIEW_TYPE_ALBUM_CELL = 1; + public static final int VIEW_TYPE_ALBUM_LINE = 2; + public static final int VIEW_TYPE_SONG = 3; + private final ImageLoader imageLoader; + private final boolean largeAlbums; private boolean showArtist = false; private boolean showAlbum = false; private boolean removeFromPlaylist = false; - private View header; public EntryGridAdapter(Context context, List entries, ImageLoader imageLoader, boolean largeCell) { super(context, entries); @@ -55,12 +48,12 @@ public class EntryGridAdapter extends SectionAdapter { // Always show artist if they aren't all the same String artist = null; - for(MusicDirectory.Entry entry: entries) { - if(artist == null) { + for (MusicDirectory.Entry entry : entries) { + if (artist == null) { artist = entry.getArtist(); } - if(artist != null && !artist.equals(entry.getArtist())) { + if (artist != null && !artist.equals(entry.getArtist())) { showArtist = true; } } @@ -68,11 +61,11 @@ public class EntryGridAdapter extends SectionAdapter { } @Override - public UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) { + public UpdateViewHolder onCreateSectionViewHolder(int viewType) { UpdateView updateView = null; - if(viewType == VIEW_TYPE_ALBUM_LINE || viewType == VIEW_TYPE_ALBUM_CELL) { + if (viewType == VIEW_TYPE_ALBUM_LINE || viewType == VIEW_TYPE_ALBUM_CELL) { updateView = new AlbumView(context, viewType == VIEW_TYPE_ALBUM_CELL); - } else if(viewType == VIEW_TYPE_SONG) { + } else if (viewType == VIEW_TYPE_SONG) { updateView = new SongView(context); } @@ -82,27 +75,24 @@ public class EntryGridAdapter extends SectionAdapter { @Override public void onBindViewHolder(UpdateViewHolder holder, Entry entry, int viewType) { UpdateView view = holder.getUpdateView(); - if(viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) { + if (viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) { AlbumView albumView = (AlbumView) view; albumView.setShowArtist(showArtist); albumView.setObject(entry, imageLoader); - } else if(viewType == VIEW_TYPE_SONG) { + } else if (viewType == VIEW_TYPE_SONG) { SongView songView = (SongView) view; songView.setShowAlbum(showAlbum); songView.setObject(entry, checkable); } } - public UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) { - return new UpdateViewHolder(header, false); - } public void onBindHeaderHolder(UpdateViewHolder holder, String header, int sectionIndex) { } @Override public int getItemViewType(Entry entry) { - if(entry.isDirectory()) { + if (entry.isDirectory()) { if (largeAlbums) { return VIEW_TYPE_ALBUM_CELL; } else { @@ -113,27 +103,16 @@ public class EntryGridAdapter extends SectionAdapter { } } - public void setHeader(View header) { - this.header = header; - this.singleSectionHeader = true; - } - public View getHeader() { - return header; + public void setShowArtist() { + this.showArtist = true; } - public void setShowArtist(boolean showArtist) { - this.showArtist = showArtist; - } - - public void setShowAlbum(boolean showAlbum) { - this.showAlbum = showAlbum; + public void setShowAlbum() { + this.showAlbum = true; } public void removeAt(int index) { sections.get(0).remove(index); - if(header != null) { - index++; - } notifyItemRemoved(index); } @@ -143,13 +122,13 @@ public class EntryGridAdapter extends SectionAdapter { @Override public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) { - if(Util.isOffline(context)) { + if (Util.isOffline(context)) { menuInflater.inflate(R.menu.multiselect_media_offline, menu); } else { menuInflater.inflate(R.menu.multiselect_media, menu); } - if(!removeFromPlaylist) { + if (!removeFromPlaylist) { menu.removeItem(R.id.menu_remove_playlist); } } diff --git a/app/src/main/java/net/nullsum/audinaut/adapter/EntryInfiniteGridAdapter.java b/app/src/main/java/net/nullsum/audinaut/adapter/EntryInfiniteGridAdapter.java index 5af5066..f05aace 100644 --- a/app/src/main/java/net/nullsum/audinaut/adapter/EntryInfiniteGridAdapter.java +++ b/app/src/main/java/net/nullsum/audinaut/adapter/EntryInfiniteGridAdapter.java @@ -20,8 +20,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import java.util.List; - import net.nullsum.audinaut.R; import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.domain.MusicDirectory.Entry; @@ -32,8 +30,10 @@ import net.nullsum.audinaut.util.ImageLoader; import net.nullsum.audinaut.util.SilentBackgroundTask; import net.nullsum.audinaut.view.UpdateView; +import java.util.List; + public class EntryInfiniteGridAdapter extends EntryGridAdapter { - public static int VIEW_TYPE_LOADING = 4; + public static final int VIEW_TYPE_LOADING = 4; private String type; private String extra; @@ -48,10 +48,10 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter { @Override public UpdateView.UpdateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - if(viewType == VIEW_TYPE_LOADING) { + if (viewType == VIEW_TYPE_LOADING) { View progress = LayoutInflater.from(context).inflate(R.layout.tab_progress, null); progress.setVisibility(View.VISIBLE); - return new UpdateView.UpdateViewHolder(progress, false); + return new UpdateView.UpdateViewHolder(progress); } return super.onCreateViewHolder(parent, viewType); @@ -59,7 +59,7 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter { @Override public int getItemViewType(int position) { - if(isLoadingView(position)) { + if (isLoadingView(position)) { return VIEW_TYPE_LOADING; } @@ -68,7 +68,7 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter { @Override public void onBindViewHolder(UpdateView.UpdateViewHolder holder, int position) { - if(!isLoadingView(position)) { + if (!isLoadingView(position)) { super.onBindViewHolder(holder, position); } } @@ -77,7 +77,7 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter { public int getItemCount() { int size = super.getItemCount(); - if(!allLoaded) { + if (!allLoaded) { size++; } @@ -89,13 +89,13 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter { this.extra = extra; this.size = size; - if(super.getItemCount() < size) { + if (super.getItemCount() < size) { allLoaded = true; } } public void loadMore() { - if(loading || allLoaded) { + if (loading || allLoaded) { return; } loading = true; @@ -114,7 +114,7 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter { appendCachedData(newData); loading = false; - if(newData.size() < size) { + if (newData.size() < size) { allLoaded = true; notifyDataSetChanged(); } @@ -122,15 +122,15 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter { }.execute(); } - protected List cacheInBackground() throws Exception { + private List cacheInBackground() throws Exception { MusicService service = MusicServiceFactory.getMusicService(context); MusicDirectory result; int offset = sections.get(0).size(); - if("genres".equals(type) || "years".equals(type)) { + if ("genres".equals(type) || "years".equals(type)) { result = service.getAlbumList(type, extra, size, offset, false, context, null); - } else if("genres".equals(type) || "genres-songs".equals(type)) { + } else if ("genres".equals(type) || "genres-songs".equals(type)) { result = service.getSongsByGenre(extra, size, offset, context, null); - }else if(type.indexOf(MainFragment.SONGS_LIST_PREFIX) != -1) { + } else if (type.contains(MainFragment.SONGS_LIST_PREFIX)) { result = service.getSongList(type, size, offset, context, null); } else { result = service.getAlbumList(type, size, offset, false, context, null); @@ -138,15 +138,15 @@ public class EntryInfiniteGridAdapter extends EntryGridAdapter { return result.getChildren(); } - protected void appendCachedData(List newData) { - if(newData.size() > 0) { + private void appendCachedData(List newData) { + if (newData.size() > 0) { int start = sections.get(0).size(); sections.get(0).addAll(newData); this.notifyItemRangeInserted(start, newData.size()); } } - protected boolean isLoadingView(int position) { + private boolean isLoadingView(int position) { return !allLoaded && position >= sections.get(0).size(); } } diff --git a/app/src/main/java/net/nullsum/audinaut/adapter/ExpandableSectionAdapter.java b/app/src/main/java/net/nullsum/audinaut/adapter/ExpandableSectionAdapter.java index 7212496..0a8985c 100644 --- a/app/src/main/java/net/nullsum/audinaut/adapter/ExpandableSectionAdapter.java +++ b/app/src/main/java/net/nullsum/audinaut/adapter/ExpandableSectionAdapter.java @@ -16,51 +16,34 @@ package net.nullsum.audinaut.adapter; import android.content.Context; -import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import net.nullsum.audinaut.R; import net.nullsum.audinaut.util.DrawableTint; import net.nullsum.audinaut.view.BasicHeaderView; import net.nullsum.audinaut.view.UpdateView; -public abstract class ExpandableSectionAdapter extends SectionAdapter { - private static final String TAG = ExpandableSectionAdapter.class.getSimpleName(); +import java.util.ArrayList; +import java.util.List; + +abstract class ExpandableSectionAdapter extends SectionAdapter { private static final int DEFAULT_VISIBLE = 4; private static final int EXPAND_TOGGLE = R.attr.select_server; private static final int COLLAPSE_TOGGLE = R.attr.select_tabs; - protected List sectionsDefaultVisible; - protected List> sectionsExtras; - protected int expandToggleRes; - protected int collapseToggleRes; + private List> sectionsExtras; - protected ExpandableSectionAdapter() {} - public ExpandableSectionAdapter(Context context, List section) { - List> sections = new ArrayList<>(); - sections.add(section); + ExpandableSectionAdapter() { + } - init(context, Arrays.asList("Section"), sections, Arrays.asList((Integer) null)); - } - public ExpandableSectionAdapter(Context context, List headers, List> sections) { - init(context, headers, sections, null); - } - public ExpandableSectionAdapter(Context context, List headers, List> sections, List sectionsDefaultVisible) { - init(context, headers, sections, sectionsDefaultVisible); - } - protected void init(Context context, List headers, List> fullSections, List sectionsDefaultVisible) { + void init(Context context, List headers, List> fullSections, List sectionsDefaultVisible) { this.context = context; this.headers = headers; - this.sectionsDefaultVisible = sectionsDefaultVisible; - if(sectionsDefaultVisible == null) { + if (sectionsDefaultVisible == null) { sectionsDefaultVisible = new ArrayList<>(fullSections.size()); - for(int i = 0; i < fullSections.size(); i++) { + for (int i = 0; i < fullSections.size(); i++) { sectionsDefaultVisible.add(DEFAULT_VISIBLE); } } @@ -68,11 +51,11 @@ public abstract class ExpandableSectionAdapter extends SectionAdapter { this.sections = new ArrayList<>(); this.sectionsExtras = new ArrayList<>(); int i = 0; - for(List fullSection: fullSections) { + for (List fullSection : fullSections) { List visibleSection = new ArrayList<>(); Integer defaultVisible = sectionsDefaultVisible.get(i); - if(defaultVisible == null || defaultVisible >= fullSection.size()) { + if (defaultVisible == null || defaultVisible >= fullSection.size()) { visibleSection.addAll(fullSection); this.sectionsExtras.add(null); } else { @@ -83,9 +66,6 @@ public abstract class ExpandableSectionAdapter extends SectionAdapter { i++; } - - expandToggleRes = DrawableTint.getDrawableRes(context, EXPAND_TOGGLE); - collapseToggleRes = DrawableTint.getDrawableRes(context, COLLAPSE_TOGGLE); } @Override @@ -96,39 +76,36 @@ public abstract class ExpandableSectionAdapter extends SectionAdapter { @Override public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header, final int sectionIndex) { UpdateView view = holder.getUpdateView(); - ImageView toggleSelectionView = (ImageView) view.findViewById(R.id.item_select); + ImageView toggleSelectionView = view.findViewById(R.id.item_select); List visibleSelection = sections.get(sectionIndex); List sectionExtras = sectionsExtras.get(sectionIndex); - if(sectionExtras != null && !sectionExtras.isEmpty()) { + if (sectionExtras != null && !sectionExtras.isEmpty()) { toggleSelectionView.setVisibility(View.VISIBLE); - toggleSelectionView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - List visibleSelection = sections.get(sectionIndex); - List sectionExtras = sectionsExtras.get(sectionIndex); + toggleSelectionView.setOnClickListener(v -> { + List visibleSelection1 = sections.get(sectionIndex); + List sectionExtras1 = sectionsExtras.get(sectionIndex); - // Update icon - int selectToggleAttr; - if (!visibleSelection.contains(sectionExtras.get(0))) { - selectToggleAttr = COLLAPSE_TOGGLE; + // Update icon + int selectToggleAttr; + if (!visibleSelection1.contains(sectionExtras1.get(0))) { + selectToggleAttr = COLLAPSE_TOGGLE; - // Update how many are displayed - int lastIndex = getItemPosition(visibleSelection.get(visibleSelection.size() - 1)); - visibleSelection.addAll(sectionExtras); - notifyItemRangeInserted(lastIndex, sectionExtras.size()); - } else { - selectToggleAttr = EXPAND_TOGGLE; + // Update how many are displayed + int lastIndex = getItemPosition(visibleSelection1.get(visibleSelection1.size() - 1)); + visibleSelection1.addAll(sectionExtras1); + notifyItemRangeInserted(lastIndex, sectionExtras1.size()); + } else { + selectToggleAttr = EXPAND_TOGGLE; - // Update how many are displayed - visibleSelection.removeAll(sectionExtras); - int lastIndex = getItemPosition(visibleSelection.get(visibleSelection.size() - 1)); - notifyItemRangeRemoved(lastIndex, sectionExtras.size()); - } - - ((ImageView) v).setImageResource(DrawableTint.getDrawableRes(context, selectToggleAttr)); + // Update how many are displayed + visibleSelection1.removeAll(sectionExtras1); + int lastIndex = getItemPosition(visibleSelection1.get(visibleSelection1.size() - 1)); + notifyItemRangeRemoved(lastIndex, sectionExtras1.size()); } + + ((ImageView) v).setImageResource(DrawableTint.getDrawableRes(context, selectToggleAttr)); }); int selectToggleAttr; @@ -143,7 +120,7 @@ public abstract class ExpandableSectionAdapter extends SectionAdapter { toggleSelectionView.setVisibility(View.GONE); } - if(view != null) { + if (view != null) { view.setObject(header); } } diff --git a/app/src/main/java/net/nullsum/audinaut/adapter/GenreAdapter.java b/app/src/main/java/net/nullsum/audinaut/adapter/GenreAdapter.java index eb9fab0..b0ed006 100644 --- a/app/src/main/java/net/nullsum/audinaut/adapter/GenreAdapter.java +++ b/app/src/main/java/net/nullsum/audinaut/adapter/GenreAdapter.java @@ -16,7 +16,7 @@ package net.nullsum.audinaut.adapter; import android.content.Context; -import android.view.ViewGroup; + import net.nullsum.audinaut.domain.Genre; import net.nullsum.audinaut.view.FastScroller; import net.nullsum.audinaut.view.GenreView; @@ -24,8 +24,8 @@ import net.nullsum.audinaut.view.UpdateView; import java.util.List; -public class GenreAdapter extends SectionAdapter implements FastScroller.BubbleTextGetter{ - public static int VIEW_TYPE_GENRE = 1; +public class GenreAdapter extends SectionAdapter implements FastScroller.BubbleTextGetter { + private static final int VIEW_TYPE_GENRE = 1; public GenreAdapter(Context context, List genres, OnItemClickedListener listener) { super(context, genres); @@ -33,7 +33,7 @@ public class GenreAdapter extends SectionAdapter implements FastScroller. } @Override - public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) { + public UpdateView.UpdateViewHolder onCreateSectionViewHolder(int viewType) { return new UpdateView.UpdateViewHolder(new GenreView(context)); } diff --git a/app/src/main/java/net/nullsum/audinaut/adapter/MainAdapter.java b/app/src/main/java/net/nullsum/audinaut/adapter/MainAdapter.java index b44cdd4..00182ff 100644 --- a/app/src/main/java/net/nullsum/audinaut/adapter/MainAdapter.java +++ b/app/src/main/java/net/nullsum/audinaut/adapter/MainAdapter.java @@ -19,18 +19,16 @@ import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; -import android.widget.CompoundButton; - -import java.util.List; import net.nullsum.audinaut.R; -import net.nullsum.audinaut.util.Util; import net.nullsum.audinaut.view.BasicHeaderView; import net.nullsum.audinaut.view.BasicListView; import net.nullsum.audinaut.view.UpdateView; +import java.util.List; + public class MainAdapter extends SectionAdapter { - public static final int VIEW_TYPE_ALBUM_LIST = 1; + private static final int VIEW_TYPE_ALBUM_LIST = 1; public MainAdapter(Context context, List headers, List> sections, OnItemClickedListener onItemClickedListener) { super(context, headers, sections); @@ -38,7 +36,7 @@ public class MainAdapter extends SectionAdapter { } @Override - public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) { + public UpdateView.UpdateViewHolder onCreateSectionViewHolder(int viewType) { UpdateView updateView = new BasicListView(context); return new UpdateView.UpdateViewHolder(updateView); } @@ -47,7 +45,7 @@ public class MainAdapter extends SectionAdapter { public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Integer item, int viewType) { UpdateView updateView = holder.getUpdateView(); - if(viewType == VIEW_TYPE_ALBUM_LIST) { + if (viewType == VIEW_TYPE_ALBUM_LIST) { updateView.setObject(context.getResources().getString(item)); } else { updateView.setObject(item); @@ -63,13 +61,14 @@ public class MainAdapter extends SectionAdapter { public UpdateView.UpdateViewHolder onCreateHeaderHolder(ViewGroup parent) { return new UpdateView.UpdateViewHolder(new BasicHeaderView(context, R.layout.album_list_header)); } + @Override public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String header, int sectionIndex) { UpdateView view = holder.getUpdateView(); - CheckBox checkBox = (CheckBox) view.findViewById(R.id.item_checkbox); + CheckBox checkBox = view.findViewById(R.id.item_checkbox); String display; - if("songs".equals(header)) { + if ("songs".equals(header)) { display = context.getResources().getString(R.string.search_songs); checkBox.setVisibility(View.GONE); } else { @@ -77,7 +76,7 @@ public class MainAdapter extends SectionAdapter { checkBox.setVisibility(View.GONE); } - if(view != null) { + if (view != null) { view.setObject(display); } } diff --git a/app/src/main/java/net/nullsum/audinaut/adapter/PlaylistAdapter.java b/app/src/main/java/net/nullsum/audinaut/adapter/PlaylistAdapter.java index 94a48a4..7ad551f 100644 --- a/app/src/main/java/net/nullsum/audinaut/adapter/PlaylistAdapter.java +++ b/app/src/main/java/net/nullsum/audinaut/adapter/PlaylistAdapter.java @@ -16,20 +16,19 @@ package net.nullsum.audinaut.adapter; import android.content.Context; -import java.util.List; - -import android.view.ViewGroup; import net.nullsum.audinaut.domain.Playlist; import net.nullsum.audinaut.util.ImageLoader; import net.nullsum.audinaut.view.FastScroller; import net.nullsum.audinaut.view.PlaylistView; import net.nullsum.audinaut.view.UpdateView; -public class PlaylistAdapter extends SectionAdapter implements FastScroller.BubbleTextGetter { - public static int VIEW_TYPE_PLAYLIST = 1; +import java.util.List; - private ImageLoader imageLoader; - private boolean largeCell; +public class PlaylistAdapter extends SectionAdapter implements FastScroller.BubbleTextGetter { + private static final int VIEW_TYPE_PLAYLIST = 1; + + private final ImageLoader imageLoader; + private final boolean largeCell; public PlaylistAdapter(Context context, List playlists, ImageLoader imageLoader, boolean largeCell, OnItemClickedListener listener) { super(context, playlists); @@ -37,15 +36,9 @@ public class PlaylistAdapter extends SectionAdapter implements FastScr this.largeCell = largeCell; this.onItemClickedListener = listener; } - public PlaylistAdapter(Context context, List headers, List> sections, ImageLoader imageLoader, boolean largeCell, OnItemClickedListener listener) { - super(context, headers, sections); - this.imageLoader = imageLoader; - this.largeCell = largeCell; - this.onItemClickedListener = listener; - } @Override - public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) { + public UpdateView.UpdateViewHolder onCreateSectionViewHolder(int viewType) { return new UpdateView.UpdateViewHolder(new PlaylistView(context, imageLoader, largeCell)); } @@ -63,7 +56,7 @@ public class PlaylistAdapter extends SectionAdapter implements FastScr @Override public String getTextToShowInBubble(int position) { Object item = getItemForPosition(position); - if(item instanceof Playlist) { + if (item instanceof Playlist) { return getNameIndex(((Playlist) item).getName()); } else { return null; diff --git a/app/src/main/java/net/nullsum/audinaut/adapter/SearchAdapter.java b/app/src/main/java/net/nullsum/audinaut/adapter/SearchAdapter.java index b76ffa2..113b59d 100644 --- a/app/src/main/java/net/nullsum/audinaut/adapter/SearchAdapter.java +++ b/app/src/main/java/net/nullsum/audinaut/adapter/SearchAdapter.java @@ -19,38 +19,32 @@ import android.content.Context; import android.content.res.Resources; import android.view.Menu; import android.view.MenuInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; import net.nullsum.audinaut.R; import net.nullsum.audinaut.domain.MusicDirectory.Entry; import net.nullsum.audinaut.domain.SearchResult; -import net.nullsum.audinaut.util.DrawableTint; import net.nullsum.audinaut.util.ImageLoader; import net.nullsum.audinaut.util.Util; import net.nullsum.audinaut.view.AlbumView; import net.nullsum.audinaut.view.ArtistView; -import net.nullsum.audinaut.view.BasicHeaderView; import net.nullsum.audinaut.view.SongView; import net.nullsum.audinaut.view.UpdateView; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + import static net.nullsum.audinaut.adapter.ArtistAdapter.VIEW_TYPE_ARTIST; import static net.nullsum.audinaut.adapter.EntryGridAdapter.VIEW_TYPE_ALBUM_CELL; import static net.nullsum.audinaut.adapter.EntryGridAdapter.VIEW_TYPE_ALBUM_LINE; import static net.nullsum.audinaut.adapter.EntryGridAdapter.VIEW_TYPE_SONG; public class SearchAdapter extends ExpandableSectionAdapter { - private ImageLoader imageLoader; - private boolean largeAlbums; - private static final int MAX_ARTISTS = 10; private static final int MAX_ALBUMS = 4; private static final int MAX_SONGS = 10; + private final ImageLoader imageLoader; + private final boolean largeAlbums; public SearchAdapter(Context context, SearchResult searchResult, ImageLoader imageLoader, boolean largeAlbums, OnItemClickedListener listener) { this.imageLoader = imageLoader; @@ -60,17 +54,17 @@ public class SearchAdapter extends ExpandableSectionAdapter { List headers = new ArrayList<>(); List defaultVisible = new ArrayList<>(); Resources res = context.getResources(); - if(!searchResult.getArtists().isEmpty()) { + if (!searchResult.getArtists().isEmpty()) { sections.add((List) (List) searchResult.getArtists()); headers.add(res.getString(R.string.search_artists)); defaultVisible.add(MAX_ARTISTS); } - if(!searchResult.getAlbums().isEmpty()) { + if (!searchResult.getAlbums().isEmpty()) { sections.add((List) (List) searchResult.getAlbums()); headers.add(res.getString(R.string.search_albums)); defaultVisible.add(MAX_ALBUMS); } - if(!searchResult.getSongs().isEmpty()) { + if (!searchResult.getSongs().isEmpty()) { sections.add((List) (List) searchResult.getSongs()); headers.add(res.getString(R.string.search_songs)); defaultVisible.add(MAX_SONGS); @@ -82,13 +76,13 @@ public class SearchAdapter extends ExpandableSectionAdapter { } @Override - public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) { + public UpdateView.UpdateViewHolder onCreateSectionViewHolder(int viewType) { UpdateView updateView = null; - if(viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) { + if (viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) { updateView = new AlbumView(context, viewType == VIEW_TYPE_ALBUM_CELL); - } else if(viewType == VIEW_TYPE_SONG) { + } else if (viewType == VIEW_TYPE_SONG) { updateView = new SongView(context); - } else if(viewType == VIEW_TYPE_ARTIST) { + } else if (viewType == VIEW_TYPE_ARTIST) { updateView = new ArtistView(context); } @@ -98,20 +92,20 @@ public class SearchAdapter extends ExpandableSectionAdapter { @Override public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Serializable item, int viewType) { UpdateView view = holder.getUpdateView(); - if(viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) { + if (viewType == VIEW_TYPE_ALBUM_CELL || viewType == VIEW_TYPE_ALBUM_LINE) { AlbumView albumView = (AlbumView) view; albumView.setObject((Entry) item, imageLoader); - } else if(viewType == VIEW_TYPE_SONG) { + } else if (viewType == VIEW_TYPE_SONG) { SongView songView = (SongView) view; songView.setObject((Entry) item, true); - } else if(viewType == VIEW_TYPE_ARTIST) { + } else if (viewType == VIEW_TYPE_ARTIST) { view.setObject(item); } } @Override public int getItemViewType(Serializable item) { - if(item instanceof Entry) { + if (item instanceof Entry) { Entry entry = (Entry) item; if (entry.isDirectory()) { if (largeAlbums) { @@ -129,7 +123,7 @@ public class SearchAdapter extends ExpandableSectionAdapter { @Override public void onCreateActionModeMenu(Menu menu, MenuInflater menuInflater) { - if(Util.isOffline(context)) { + if (Util.isOffline(context)) { menuInflater.inflate(R.menu.multiselect_media_offline, menu); } else { menuInflater.inflate(R.menu.multiselect_media, menu); diff --git a/app/src/main/java/net/nullsum/audinaut/adapter/SectionAdapter.java b/app/src/main/java/net/nullsum/audinaut/adapter/SectionAdapter.java index 1a310b1..6b97749 100644 --- a/app/src/main/java/net/nullsum/audinaut/adapter/SectionAdapter.java +++ b/app/src/main/java/net/nullsum/audinaut/adapter/SectionAdapter.java @@ -32,10 +32,6 @@ import android.view.Window; import android.view.WindowManager; import android.widget.PopupMenu; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import net.nullsum.audinaut.R; import net.nullsum.audinaut.activity.SubsonicFragmentActivity; import net.nullsum.audinaut.util.Constants; @@ -45,129 +41,103 @@ import net.nullsum.audinaut.view.BasicHeaderView; import net.nullsum.audinaut.view.UpdateView; import net.nullsum.audinaut.view.UpdateView.UpdateViewHolder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + public abstract class SectionAdapter extends RecyclerView.Adapter> { - private static String TAG = SectionAdapter.class.getSimpleName(); - public static int VIEW_TYPE_HEADER = 0; - public static String[] ignoredArticles; + public static final int VIEW_TYPE_HEADER = 0; + private static final String TAG = SectionAdapter.class.getSimpleName(); + private static String[] ignoredArticles; + private final List selected = new ArrayList<>(); + private final List selectedViews = new ArrayList<>(); + Context context; + List headers; + List> sections; + boolean singleSectionHeader; + OnItemClickedListener onItemClickedListener; + boolean checkable = false; + private ActionMode currentActionMode; - protected Context context; - protected List headers; - protected List> sections; - protected boolean singleSectionHeader; - protected OnItemClickedListener onItemClickedListener; - protected List selected = new ArrayList<>(); - protected List selectedViews = new ArrayList<>(); - protected ActionMode currentActionMode; - protected boolean checkable = false; - - protected SectionAdapter() {} - public SectionAdapter(Context context, List section) { - this(context, section, false); + SectionAdapter() { } - public SectionAdapter(Context context, List section, boolean singleSectionHeader) { + + SectionAdapter(Context context, List section) { this.context = context; - this.headers = Arrays.asList("Section"); + this.headers = Collections.singletonList("Section"); this.sections = new ArrayList<>(); this.sections.add(section); - this.singleSectionHeader = singleSectionHeader; + this.singleSectionHeader = false; } - public SectionAdapter(Context context, List headers, List> sections) { - this(context, headers, sections, true); - } - public SectionAdapter(Context context, List headers, List> sections, boolean singleSectionHeader){ + + SectionAdapter(Context context, List headers, List> sections) { this.context = context; this.headers = headers; this.sections = sections; - this.singleSectionHeader = singleSectionHeader; - } - - public void replaceExistingData(List section) { - this.sections = new ArrayList<>(); - this.sections.add(section); - notifyDataSetChanged(); - } - public void replaceExistingData(List headers, List> sections) { - this.headers = headers; - this.sections = sections; - notifyDataSetChanged(); + this.singleSectionHeader = true; } @Override public UpdateViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - if(viewType == VIEW_TYPE_HEADER) { + if (viewType == VIEW_TYPE_HEADER) { return onCreateHeaderHolder(parent); } else { - final UpdateViewHolder holder = onCreateSectionViewHolder(parent, viewType); + final UpdateViewHolder holder = onCreateSectionViewHolder(viewType); final UpdateView updateView = holder.getUpdateView(); - if(updateView != null) { - updateView.getChildAt(0).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - T item = holder.getItem(); - updateView.onClick(); - if (currentActionMode != null) { - if(updateView.isCheckable()) { - if (selected.contains(item)) { - selected.remove(item); - selectedViews.remove(updateView); - setChecked(updateView, false); - } else { - selected.add(item); - selectedViews.add(updateView); - setChecked(updateView, true); - } - - if (selected.isEmpty()) { - currentActionMode.finish(); - } else { - currentActionMode.setTitle(context.getResources().getString(R.string.select_album_n_selected, selected.size())); - } + if (updateView != null) { + updateView.getChildAt(0).setOnClickListener(v -> { + T item = holder.getItem(); + if (currentActionMode != null) { + if (updateView.isCheckable()) { + if (selected.contains(item)) { + selected.remove(item); + selectedViews.remove(updateView); + setChecked(updateView, false); + } else { + selected.add(item); + selectedViews.add(updateView); + setChecked(updateView, true); + } + + if (selected.isEmpty()) { + currentActionMode.finish(); + } else { + currentActionMode.setTitle(context.getResources().getString(R.string.select_album_n_selected, selected.size())); } - } else if (onItemClickedListener != null) { - onItemClickedListener.onItemClicked(updateView, item); } + } else if (onItemClickedListener != null) { + onItemClickedListener.onItemClicked(updateView, item); } }); View moreButton = updateView.findViewById(R.id.item_more); if (moreButton != null) { - moreButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - try { - final T item = holder.getItem(); - if (onItemClickedListener != null) { - PopupMenu popup = new PopupMenu(context, v); - onItemClickedListener.onCreateContextMenu(popup.getMenu(), popup.getMenuInflater(), updateView, item); + moreButton.setOnClickListener(v -> { + try { + final T item = holder.getItem(); + if (onItemClickedListener != null) { + PopupMenu popup = new PopupMenu(context, v); + onItemClickedListener.onCreateContextMenu(popup.getMenu(), popup.getMenuInflater(), updateView, item); - popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem menuItem) { - return onItemClickedListener.onContextItemSelected(menuItem, updateView, item); - } - }); - popup.show(); - } - } catch(Exception e) { - Log.w(TAG, "Failed to show popup", e); + popup.setOnMenuItemClickListener(menuItem -> onItemClickedListener.onContextItemSelected(menuItem, updateView, item)); + popup.show(); } + } catch (Exception e) { + Log.w(TAG, "Failed to show popup", e); } }); - if(checkable) { - updateView.getChildAt(0).setOnLongClickListener(new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - if(updateView.isCheckable()) { - if (currentActionMode == null) { - startActionMode(holder); - } else { - updateView.getChildAt(0).performClick(); - } + if (checkable) { + updateView.getChildAt(0).setOnLongClickListener(v -> { + if (updateView.isCheckable()) { + if (currentActionMode == null) { + startActionMode(holder); + } else { + updateView.getChildAt(0).performClick(); } - return true; } + return true; }); } } @@ -181,7 +151,7 @@ public abstract class SectionAdapter extends RecyclerView.Adapter extends RecyclerView.Adapter section: sections) { + for (List section : sections) { boolean validHeader = headers.get(subHeader) != null; - if(position == subPosition && validHeader) { + if (position == subPosition && validHeader) { onBindHeaderHolder(holder, headers.get(subHeader), subHeader); return; } int headerOffset = validHeader ? 1 : 0; - if(position < (subPosition + section.size() + headerOffset)) { + if (position < (subPosition + section.size() + headerOffset)) { T item = section.get(position - subPosition - headerOffset); onBindViewHolder(holder, item, getItemViewType(item)); @@ -209,7 +179,7 @@ public abstract class SectionAdapter extends RecyclerView.Adapter extends RecyclerView.Adapter extends RecyclerView.Adapter section: sections) { + for (List section : sections) { count += section.size(); } @@ -259,25 +229,25 @@ public abstract class SectionAdapter extends RecyclerView.Adapter section: sections) { + for (List section : sections) { boolean validHeader = headers.get(subHeader) != null; - if(position == subPosition && validHeader) { + if (position == subPosition && validHeader) { return VIEW_TYPE_HEADER; } int headerOffset = validHeader ? 1 : 0; - if(position < (subPosition + section.size() + headerOffset)) { + if (position < (subPosition + section.size() + headerOffset)) { return getItemViewType(section.get(position - subPosition - headerOffset)); } subPosition += section.size(); - if(validHeader) { + if (validHeader) { subPosition += 1; } subHeader++; @@ -286,28 +256,29 @@ public abstract class SectionAdapter extends RecyclerView.Adapter section: sections) { - if(position == subPosition) { + for (List section : sections) { + if (position == subPosition) { return null; } - if(position <= (subPosition + section.size())) { + if (position <= (subPosition + section.size())) { return section.get(position - subPosition - 1); } @@ -316,17 +287,18 @@ public abstract class SectionAdapter extends RecyclerView.Adapter section: sections) { + for (List section : sections) { subPosition += section.size() + 1; int position = section.indexOf(item); - if(position != -1) { + if (position != -1) { return position + subPosition; } } @@ -341,6 +313,7 @@ public abstract class SectionAdapter extends RecyclerView.Adapter getSelected() { List selected = new ArrayList<>(); selected.addAll(this.selected); @@ -348,17 +321,9 @@ public abstract class SectionAdapter extends RecyclerView.Adapter extends RecyclerView.Adapter section = sections.get(0); int max = section.size(); - if(to >= max) { + if (to >= max) { to = max - 1; - } else if(to < 0) { + } else if (to < 0) { to = 0; } @@ -377,10 +342,11 @@ public abstract class SectionAdapter extends RecyclerView.Adapter section: sections) { - if(sections.size() > 1 || singleSectionHeader) { + for (List section : sections) { + if (sections.size() > 1 || singleSectionHeader) { subPosition++; } @@ -395,16 +361,18 @@ public abstract class SectionAdapter extends RecyclerView.Adapter holder) { final UpdateView updateView = holder.getUpdateView(); @@ -470,21 +438,23 @@ public abstract class SectionAdapter extends RecyclerView.Adapter extends RecyclerView.Adapter { void onItemClicked(UpdateView updateView, T item); + void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView updateView, T item); + boolean onContextItemSelected(MenuItem menuItem, UpdateView updateView, T item); } } diff --git a/app/src/main/java/net/nullsum/audinaut/adapter/SettingsAdapter.java b/app/src/main/java/net/nullsum/audinaut/adapter/SettingsAdapter.java deleted file mode 100644 index 4cf06cf..0000000 --- a/app/src/main/java/net/nullsum/audinaut/adapter/SettingsAdapter.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - This file is part of Subsonic. - Subsonic is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - Subsonic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with Subsonic. If not, see . - Copyright 2014 (C) Scott Jackson -*/ - -package net.nullsum.audinaut.adapter; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import java.util.ArrayList; -import java.util.List; - -import net.nullsum.audinaut.R; -import net.nullsum.audinaut.domain.User; -import net.nullsum.audinaut.util.ImageLoader; -import net.nullsum.audinaut.util.UserUtil; -import net.nullsum.audinaut.view.BasicHeaderView; -import net.nullsum.audinaut.view.RecyclingImageView; -import net.nullsum.audinaut.view.SettingView; -import net.nullsum.audinaut.view.UpdateView; - -import static net.nullsum.audinaut.domain.User.Setting; - -public class SettingsAdapter extends SectionAdapter { - private static final String TAG = SettingsAdapter.class.getSimpleName(); - public final int VIEW_TYPE_SETTING = 1; - public final int VIEW_TYPE_SETTING_HEADER = 2; - - private final User user; - private final boolean editable; - private final ImageLoader imageLoader; - - public SettingsAdapter(Context context, User user, List headers, List> settingSections, ImageLoader imageLoader, boolean editable, OnItemClickedListener onItemClickedListener) { - super(context, headers, settingSections, imageLoader != null); - this.user = user; - this.imageLoader = imageLoader; - this.editable = editable; - this.onItemClickedListener = onItemClickedListener; - - for(List settings: sections) { - for (Setting setting : settings) { - if (setting.getValue()) { - addSelected(setting); - } - } - } - } - - @Override - public int getItemViewType(int position) { - int viewType = super.getItemViewType(position); - if(viewType == SectionAdapter.VIEW_TYPE_HEADER) { - if(position == 0 && imageLoader != null) { - return VIEW_TYPE_HEADER; - } else { - return VIEW_TYPE_SETTING_HEADER; - } - } else { - return viewType; - } - } - - public void onBindHeaderHolder(UpdateView.UpdateViewHolder holder, String description, int sectionIndex) { - View header = holder.getView(); - } - - @Override - public UpdateView.UpdateViewHolder onCreateSectionViewHolder(ViewGroup parent, int viewType) { - if(viewType == VIEW_TYPE_SETTING_HEADER) { - return new UpdateView.UpdateViewHolder(new BasicHeaderView(context)); - } else { - return new UpdateView.UpdateViewHolder(new SettingView(context)); - } - } - - @Override - public void onBindViewHolder(UpdateView.UpdateViewHolder holder, Setting item, int viewType) { - holder.getUpdateView().setObject(item, editable); - } - - @Override - public int getItemViewType(Setting item) { - return VIEW_TYPE_SETTING; - } - - @Override - public void setChecked(UpdateView updateView, boolean checked) { - if(updateView instanceof SettingView) { - updateView.setChecked(checked); - } - } - - public static SettingsAdapter getSettingsAdapter(Context context, User user, ImageLoader imageLoader, OnItemClickedListener onItemClickedListener) { - return getSettingsAdapter(context, user, imageLoader, true, onItemClickedListener); - } - public static SettingsAdapter getSettingsAdapter(Context context, User user, ImageLoader imageLoader, boolean isEditable, OnItemClickedListener onItemClickedListener) { - List headers = new ArrayList<>(); - List> settingsSections = new ArrayList<>(); - settingsSections.add(user.getSettings()); - - if(user.getMusicFolderSettings() != null) { - settingsSections.add(user.getMusicFolderSettings()); - } - - return new SettingsAdapter(context, user, headers, settingsSections, imageLoader, isEditable, onItemClickedListener); - } -} diff --git a/app/src/main/java/net/nullsum/audinaut/audiofx/AudioEffectsController.java b/app/src/main/java/net/nullsum/audinaut/audiofx/AudioEffectsController.java index 6549538..d9505f2 100644 --- a/app/src/main/java/net/nullsum/audinaut/audiofx/AudioEffectsController.java +++ b/app/src/main/java/net/nullsum/audinaut/audiofx/AudioEffectsController.java @@ -19,14 +19,8 @@ package net.nullsum.audinaut.audiofx; import android.content.Context; -import android.media.MediaPlayer; -import android.media.audiofx.AudioEffect; -import android.media.audiofx.LoudnessEnhancer; -import android.os.Build; -import android.util.Log; public class AudioEffectsController { - private static final String TAG = AudioEffectsController.class.getSimpleName(); private final Context context; private int audioSessionId = 0; @@ -39,7 +33,7 @@ public class AudioEffectsController { } public void release() { - if(equalizerController != null) { + if (equalizerController != null) { equalizerController.release(); } } diff --git a/app/src/main/java/net/nullsum/audinaut/audiofx/EqualizerController.java b/app/src/main/java/net/nullsum/audinaut/audiofx/EqualizerController.java index 1b2b3be..1801647 100644 --- a/app/src/main/java/net/nullsum/audinaut/audiofx/EqualizerController.java +++ b/app/src/main/java/net/nullsum/audinaut/audiofx/EqualizerController.java @@ -18,14 +18,15 @@ */ package net.nullsum.audinaut.audiofx; -import java.io.Serializable; - import android.content.Context; import android.media.audiofx.BassBoost; import android.media.audiofx.Equalizer; import android.util.Log; + import net.nullsum.audinaut.util.FileUtil; +import java.io.Serializable; + /** * Backward-compatible wrapper for {@link Equalizer}, which is API Level 9. * @@ -54,7 +55,7 @@ public class EqualizerController { equalizer = new Equalizer(0, audioSessionId); bass = new BassBoost(0, audioSessionId); loudnessAvailable = true; - loudnessEnhancerController = new LoudnessEnhancerController(context, audioSessionId); + loudnessEnhancerController = new LoudnessEnhancerController(audioSessionId); } public void saveSettings() { @@ -80,14 +81,14 @@ public class EqualizerController { } } - public boolean isAvailable() { + private boolean isAvailable() { return equalizer != null && bass != null; } public boolean isEnabled() { try { return isAvailable() && equalizer.getEnabled(); - } catch(Exception e) { + } catch (Exception e) { return false; } } @@ -97,14 +98,14 @@ public class EqualizerController { released = true; equalizer.release(); bass.release(); - if(loudnessEnhancerController != null && loudnessEnhancerController.isAvailable()) { + if (loudnessEnhancerController != null && loudnessEnhancerController.isAvailable()) { loudnessEnhancerController.release(); } } } public Equalizer getEqualizer() { - if(released) { + if (released) { released = false; try { init(); @@ -116,8 +117,9 @@ public class EqualizerController { } return equalizer; } + public BassBoost getBassBoost() { - if(released) { + if (released) { released = false; try { init(); @@ -128,8 +130,9 @@ public class EqualizerController { } return bass; } + public LoudnessEnhancerController getLoudnessEnhancerController() { - if(loudnessAvailable && released) { + if (loudnessAvailable && released) { released = false; try { init(); @@ -144,7 +147,6 @@ public class EqualizerController { private static class EqualizerSettings implements Serializable { private short[] bandLevels; - private short preset; private boolean enabled; private short bass; private int loudness; @@ -152,26 +154,22 @@ public class EqualizerController { public EqualizerSettings() { } + public EqualizerSettings(Equalizer equalizer, BassBoost boost, LoudnessEnhancerController loudnessEnhancerController) { enabled = equalizer.getEnabled(); bandLevels = new short[equalizer.getNumberOfBands()]; for (short i = 0; i < equalizer.getNumberOfBands(); i++) { bandLevels[i] = equalizer.getBandLevel(i); } - try { - preset = equalizer.getCurrentPreset(); - } catch (Exception x) { - preset = -1; - } try { bass = boost.getRoundedStrength(); - } catch(Exception e) { + } catch (Exception e) { bass = 0; } try { loudness = (int) loudnessEnhancerController.getGain(); - } catch(Exception e) { + } catch (Exception e) { loudness = 0; } } @@ -181,11 +179,11 @@ public class EqualizerController { equalizer.setBandLevel(i, bandLevels[i]); } equalizer.setEnabled(enabled); - if(bass != 0) { + if (bass != 0) { boost.setEnabled(true); boost.setStrength(bass); } - if(loudness != 0) { + if (loudness != 0) { loudnessController.enable(); loudnessController.setGain(loudness); } diff --git a/app/src/main/java/net/nullsum/audinaut/audiofx/LoudnessEnhancerController.java b/app/src/main/java/net/nullsum/audinaut/audiofx/LoudnessEnhancerController.java index 3e67334..2e433e6 100644 --- a/app/src/main/java/net/nullsum/audinaut/audiofx/LoudnessEnhancerController.java +++ b/app/src/main/java/net/nullsum/audinaut/audiofx/LoudnessEnhancerController.java @@ -18,22 +18,16 @@ */ package net.nullsum.audinaut.audiofx; -import android.content.Context; import android.media.audiofx.LoudnessEnhancer; import android.util.Log; public class LoudnessEnhancerController { private static final String TAG = LoudnessEnhancerController.class.getSimpleName(); - private final Context context; private LoudnessEnhancer enhancer; - private boolean released = false; - private int audioSessionId = 0; - public LoudnessEnhancerController(Context context, int audioSessionId) { - this.context = context; + public LoudnessEnhancerController(int audioSessionId) { try { - this.audioSessionId = audioSessionId; enhancer = new LoudnessEnhancer(audioSessionId); } catch (Throwable x) { Log.w(TAG, "Failed to create enhancer", x); @@ -47,7 +41,7 @@ public class LoudnessEnhancerController { public boolean isEnabled() { try { return isAvailable() && enhancer.getEnabled(); - } catch(Exception e) { + } catch (Exception e) { return false; } } @@ -55,6 +49,7 @@ public class LoudnessEnhancerController { public void enable() { enhancer.setEnabled(true); } + public void disable() { enhancer.setEnabled(false); } @@ -62,6 +57,7 @@ public class LoudnessEnhancerController { public float getGain() { return enhancer.getTargetGain(); } + public void setGain(int gain) { enhancer.setTargetGain(gain); } @@ -69,7 +65,6 @@ public class LoudnessEnhancerController { public void release() { if (isAvailable()) { enhancer.release(); - released = true; } } diff --git a/app/src/main/java/net/nullsum/audinaut/domain/MusicDirectory.java b/app/src/main/java/net/nullsum/audinaut/domain/MusicDirectory.java index 61d9512..caa9fe0 100644 --- a/app/src/main/java/net/nullsum/audinaut/domain/MusicDirectory.java +++ b/app/src/main/java/net/nullsum/audinaut/domain/MusicDirectory.java @@ -19,26 +19,25 @@ package net.nullsum.audinaut.domain; import android.content.Context; -import android.content.SharedPreferences; import android.media.MediaMetadataRetriever; -import android.os.Build; import android.util.Log; -import java.text.Collator; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.io.File; -import java.io.Serializable; -import java.util.Collections; -import java.util.Comparator; -import java.util.Locale; - import net.nullsum.audinaut.service.DownloadService; import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.UpdateHelper; import net.nullsum.audinaut.util.Util; +import java.io.File; +import java.io.Serializable; +import java.text.Collator; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Objects; + /** * @author Sindre Mehus */ @@ -51,8 +50,9 @@ public class MusicDirectory implements Serializable { private List children; public MusicDirectory() { - children = new ArrayList(); + children = new ArrayList<>(); } + public MusicDirectory(List children) { this.children = children; } @@ -65,7 +65,7 @@ public class MusicDirectory implements Serializable { this.name = name; } - public String getId() { + public String getId() { return id; } @@ -82,10 +82,11 @@ public class MusicDirectory implements Serializable { } public void addChild(Entry child) { - if(child != null) { + if (child != null) { children.add(child); } } + public void addChildren(List children) { this.children.addAll(children); } @@ -103,7 +104,7 @@ public class MusicDirectory implements Serializable { return children; } - List result = new ArrayList(children.size()); + List result = new ArrayList<>(children.size()); for (Entry child : children) { if (child != null && child.isDirectory() && includeDirs || !child.isDirectory() && includeFiles) { result.add(child); @@ -111,8 +112,9 @@ public class MusicDirectory implements Serializable { } return result; } + public synchronized List getSongs() { - List result = new ArrayList(); + List result = new ArrayList<>(); for (Entry child : children) { if (child != null && !child.isDirectory()) { result.add(child); @@ -125,24 +127,19 @@ public class MusicDirectory implements Serializable { return children.size(); } - public void shuffleChildren() { - Collections.shuffle(this.children); - } - - public void sortChildren(Context context, int instance) { + public void sortChildren(Context context) { sortChildren(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_CUSTOM_SORT_ENABLED, true)); } + public void sortChildren(boolean byYear) { EntryComparator.sort(children, byYear); } public synchronized boolean updateMetadata(MusicDirectory refreshedDirectory) { boolean metadataUpdated = false; - Iterator it = children.iterator(); - while(it.hasNext()) { - Entry entry = it.next(); + for (Entry entry : children) { int index = refreshedDirectory.children.indexOf(entry); - if(index != -1) { + if (index != -1) { final Entry refreshed = refreshedDirectory.children.get(index); entry.setTitle(refreshed.getTitle()); @@ -155,7 +152,7 @@ public class MusicDirectory implements Serializable { entry.setTranscodedSuffix(refreshed.getTranscodedSuffix()); entry.setDiscNumber(refreshed.getDiscNumber()); entry.setType(refreshed.getType()); - if(!Util.equals(entry.getCoverArt(), refreshed.getCoverArt())) { + if (!Util.equals(entry.getCoverArt(), refreshed.getCoverArt())) { metadataUpdated = true; entry.setCoverArt(refreshed.getCoverArt()); } @@ -173,7 +170,7 @@ public class MusicDirectory implements Serializable { found.setTranscodedSuffix(refreshed.getTranscodedSuffix()); found.setDiscNumber(refreshed.getDiscNumber()); found.setType(refreshed.getType()); - if(!Util.equals(found.getCoverArt(), refreshed.getCoverArt())) { + if (!Util.equals(found.getCoverArt(), refreshed.getCoverArt())) { found.setCoverArt(refreshed.getCoverArt()); metadataUpdate = DownloadService.METADATA_UPDATED_COVER_ART; } @@ -184,13 +181,14 @@ public class MusicDirectory implements Serializable { return metadataUpdated; } - public synchronized boolean updateEntriesList(Context context, int instance, MusicDirectory refreshedDirectory) { + + public synchronized boolean updateEntriesList(Context context, MusicDirectory refreshedDirectory) { boolean changed = false; Iterator it = children.iterator(); - while(it.hasNext()) { + while (it.hasNext()) { Entry entry = it.next(); // No longer exists in here - if(refreshedDirectory.children.indexOf(entry) == -1) { + if (refreshedDirectory.children.indexOf(entry) == -1) { it.remove(); changed = true; } @@ -198,16 +196,16 @@ public class MusicDirectory implements Serializable { // Make sure we contain all children from refreshed set boolean resort = false; - for(Entry refreshed: refreshedDirectory.children) { - if(!this.children.contains(refreshed)) { + for (Entry refreshed : refreshedDirectory.children) { + if (!this.children.contains(refreshed)) { this.children.add(refreshed); resort = true; changed = true; } } - if(resort) { - this.sortChildren(context, instance); + if (resort) { + this.sortChildren(context); } return changed; @@ -218,7 +216,6 @@ public class MusicDirectory implements Serializable { private String id; private String parent; - private String grandParent; private String albumId; private String artistId; private boolean directory; @@ -233,26 +230,25 @@ public class MusicDirectory implements Serializable { private String transcodedContentType; private String transcodedSuffix; private String coverArt; - private Long size; private Integer duration; private Integer bitRate; private String path; private Integer discNumber; private int type = 0; private int closeness; - private transient Artist linkedArtist; public Entry() { } + public Entry(String id) { this.id = id; } + public Entry(Artist artist) { this.id = artist.getId(); this.title = artist.getName(); this.directory = true; - this.linkedArtist = artist; } public void loadMetadata(File file) { @@ -260,16 +256,16 @@ public class MusicDirectory implements Serializable { MediaMetadataRetriever metadata = new MediaMetadataRetriever(); metadata.setDataSource(file.getAbsolutePath()); String discNumber = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER); - if(discNumber == null) { + if (discNumber == null) { discNumber = "1/1"; } int slashIndex = discNumber.indexOf("/"); - if(slashIndex > 0) { + if (slashIndex > 0) { discNumber = discNumber.substring(0, slashIndex); } try { setDiscNumber(Integer.parseInt(discNumber)); - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Non numbers in disc field!"); } String bitrate = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE); @@ -277,22 +273,23 @@ public class MusicDirectory implements Serializable { String length = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); setDuration(Integer.parseInt(length) / 1000); String artist = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST); - if(artist != null) { + if (artist != null) { setArtist(artist); } String album = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM); - if(album != null) { + if (album != null) { setAlbum(album); } metadata.release(); - } catch(Exception e) { + } catch (Exception e) { Log.i(TAG, "Device doesn't properly support MediaMetadataRetreiver", e); } } + public void rebaseTitleOffPath() { try { String filename = getPath(); - if(filename == null) { + if (filename == null) { return; } @@ -304,13 +301,13 @@ public class MusicDirectory implements Serializable { } index = filename.lastIndexOf('.'); - if(index != -1) { + if (index != -1) { filename = filename.substring(0, index); } setTitle(filename); } - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to update title based off of path", e); } } @@ -331,14 +328,6 @@ public class MusicDirectory implements Serializable { this.parent = parent; } - public String getGrandParent() { - return grandParent; - } - - public void setGrandParent(String grandParent) { - this.grandParent = grandParent; - } - public String getAlbumId() { return albumId; } @@ -379,18 +368,18 @@ public class MusicDirectory implements Serializable { return getParent() != null || getArtist() != null; } + public void setAlbum(String album) { + this.album = album; + } + public String getAlbumDisplay() { - if(album != null && title.startsWith("Disc ")) { + if (album != null && title.startsWith("Disc ")) { return album; } else { return title; } } - public void setAlbum(String album) { - this.album = album; - } - public String getArtist() { return artist; } @@ -455,14 +444,6 @@ public class MusicDirectory implements Serializable { this.transcodedSuffix = transcodedSuffix; } - public Long getSize() { - return size; - } - - public void setSize(Long size) { - this.size = size; - } - public Integer getDuration() { return duration; } @@ -506,9 +487,11 @@ public class MusicDirectory implements Serializable { public int getType() { return type; } + public void setType(int type) { this.type = type; } + public boolean isSong() { return type == TYPE_SONG; } @@ -521,18 +504,6 @@ public class MusicDirectory implements Serializable { this.closeness = closeness; } - public boolean isOnlineId(Context context) { - try { - String cacheLocation = Util.getPreferences(context).getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null); - return cacheLocation == null || id == null || id.indexOf(cacheLocation) == -1; - } catch(Exception e) { - Log.w(TAG, "Failed to check online id validity"); - - // Err on the side of default functionality - return true; - } - } - @Override public boolean equals(Object o) { if (this == o) { @@ -558,8 +529,8 @@ public class MusicDirectory implements Serializable { } public static class EntryComparator implements Comparator { - private boolean byYear; - private Collator collator; + private final boolean byYear; + private final Collator collator; public EntryComparator(boolean byYear) { this.byYear = byYear; @@ -567,20 +538,28 @@ public class MusicDirectory implements Serializable { this.collator.setStrength(Collator.PRIMARY); } + public static void sort(List entries, boolean byYear) { + try { + Collections.sort(entries, new EntryComparator(byYear)); + } catch (Exception e) { + Log.w(TAG, "Failed to sort MusicDirectory"); + } + } + public int compare(Entry lhs, Entry rhs) { - if(lhs.isDirectory() && !rhs.isDirectory()) { + if (lhs.isDirectory() && !rhs.isDirectory()) { return -1; - } else if(!lhs.isDirectory() && rhs.isDirectory()) { + } else if (!lhs.isDirectory() && rhs.isDirectory()) { return 1; - } else if(lhs.isDirectory() && rhs.isDirectory()) { - if(byYear) { + } else if (lhs.isDirectory() && rhs.isDirectory()) { + if (byYear) { Integer lhsYear = lhs.getYear(); Integer rhsYear = rhs.getYear(); - if(lhsYear != null && rhsYear != null) { + if (lhsYear != null && rhsYear != null) { return lhsYear.compareTo(rhsYear); - } else if(lhsYear != null) { + } else if (lhsYear != null) { return -1; - } else if(rhsYear != null) { + } else if (rhsYear != null) { return 1; } } @@ -591,36 +570,25 @@ public class MusicDirectory implements Serializable { Integer lhsDisc = lhs.getDiscNumber(); Integer rhsDisc = rhs.getDiscNumber(); - if(lhsDisc != null && rhsDisc != null) { - if(lhsDisc < rhsDisc) { + if (lhsDisc != null && rhsDisc != null) { + if (lhsDisc < rhsDisc) { return -1; - } else if(lhsDisc > rhsDisc) { + } else if (lhsDisc > rhsDisc) { return 1; } } Integer lhsTrack = lhs.getTrack(); Integer rhsTrack = rhs.getTrack(); - if(lhsTrack != null && rhsTrack != null && lhsTrack != rhsTrack) { + if (lhsTrack != null && rhsTrack != null && !Objects.equals(lhsTrack, rhsTrack)) { return lhsTrack.compareTo(rhsTrack); - } else if(lhsTrack != null) { + } else if (lhsTrack != null) { return -1; - } else if(rhsTrack != null) { + } else if (rhsTrack != null) { return 1; } return collator.compare(lhs.getTitle(), rhs.getTitle()); } - - public static void sort(List entries) { - sort(entries, true); - } - public static void sort(List entries, boolean byYear) { - try { - Collections.sort(entries, new EntryComparator(byYear)); - } catch (Exception e) { - Log.w(TAG, "Failed to sort MusicDirectory"); - } - } } } diff --git a/app/src/main/java/net/nullsum/audinaut/domain/MusicFolder.java b/app/src/main/java/net/nullsum/audinaut/domain/MusicFolder.java index 0524b6e..83453b5 100644 --- a/app/src/main/java/net/nullsum/audinaut/domain/MusicFolder.java +++ b/app/src/main/java/net/nullsum/audinaut/domain/MusicFolder.java @@ -35,16 +35,24 @@ public class MusicFolder implements Serializable { private static final String TAG = MusicFolder.class.getSimpleName(); private String id; private String name; - private boolean enabled; public MusicFolder() { } + public MusicFolder(String id, String name) { this.id = id; this.name = name; } + public static void sort(List musicFolders) { + try { + Collections.sort(musicFolders, new MusicFolderComparator()); + } catch (Exception e) { + Log.w(TAG, "Failed to sort music folders", e); + } + } + public String getId() { return id; } @@ -53,28 +61,13 @@ public class MusicFolder implements Serializable { return name; } - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - public boolean getEnabled() { - return enabled; - } - public static class MusicFolderComparator implements Comparator { public int compare(MusicFolder lhsMusicFolder, MusicFolder rhsMusicFolder) { - if(lhsMusicFolder == rhsMusicFolder || lhsMusicFolder.getName().equals(rhsMusicFolder.getName())) { + if (lhsMusicFolder == rhsMusicFolder || lhsMusicFolder.getName().equals(rhsMusicFolder.getName())) { return 0; } else { return lhsMusicFolder.getName().compareToIgnoreCase(rhsMusicFolder.getName()); } } } - - public static void sort(List musicFolders) { - try { - Collections.sort(musicFolders, new MusicFolderComparator()); - } catch (Exception e) { - Log.w(TAG, "Failed to sort music folders", e); - } - } } diff --git a/app/src/main/java/net/nullsum/audinaut/domain/PlayerQueue.java b/app/src/main/java/net/nullsum/audinaut/domain/PlayerQueue.java index 827f27b..42e98f4 100644 --- a/app/src/main/java/net/nullsum/audinaut/domain/PlayerQueue.java +++ b/app/src/main/java/net/nullsum/audinaut/domain/PlayerQueue.java @@ -17,14 +17,12 @@ package net.nullsum.audinaut.domain; import java.io.Serializable; import java.util.ArrayList; -import java.util.Date; import java.util.List; public class PlayerQueue implements Serializable { - public List songs = new ArrayList(); - public List toDelete = new ArrayList(); + public final List songs = new ArrayList<>(); + public final List toDelete = new ArrayList<>(); public int currentPlayingIndex; public int currentPlayingPosition; public boolean renameCurrent = false; - public Date changed = null; } diff --git a/app/src/main/java/net/nullsum/audinaut/domain/Playlist.java b/app/src/main/java/net/nullsum/audinaut/domain/Playlist.java index 86708dd..c3b1380 100644 --- a/app/src/main/java/net/nullsum/audinaut/domain/Playlist.java +++ b/app/src/main/java/net/nullsum/audinaut/domain/Playlist.java @@ -45,10 +45,12 @@ public class Playlist implements Serializable { public Playlist() { } + public Playlist(String id, String name) { this.id = id; this.name = name; } + public Playlist(String id, String name, String owner, String comment, String songCount, String pub, String created, String changed, Integer duration) { this.id = id; this.name = name; @@ -65,10 +67,6 @@ public class Playlist implements Serializable { return id; } - public void setId(String id) { - this.id = id; - } - public String getName() { return name; } @@ -81,10 +79,6 @@ public class Playlist implements Serializable { return this.owner; } - public void setOwner(String owner) { - this.owner = owner; - } - public String getComment() { return this.comment; } @@ -104,6 +98,7 @@ public class Playlist implements Serializable { public Boolean getPublic() { return this.pub; } + public void setPublic(Boolean pub) { this.pub = pub; } @@ -112,7 +107,7 @@ public class Playlist implements Serializable { return created; } - public void setCreated(String created) { + private void setCreated(String created) { if (created != null) { try { this.created = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(created); @@ -123,14 +118,12 @@ public class Playlist implements Serializable { this.created = null; } } - public void setCreated(Date created) { - this.created = created; - } public Date getChanged() { return changed; } - public void setChanged(String changed) { + + private void setChanged(String changed) { if (changed != null) { try { this.changed = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH).parse(changed); @@ -141,16 +134,10 @@ public class Playlist implements Serializable { this.changed = null; } } - public void setChanged(Date changed) { - this.changed = changed; - } public Integer getDuration() { return duration; } - public void setDuration(Integer duration) { - this.duration = duration; - } @Override public String toString() { @@ -159,13 +146,13 @@ public class Playlist implements Serializable { @Override public boolean equals(Object o) { - if(o == this) { + if (o == this) { return true; - } else if(o == null) { + } else if (o == null) { return false; - } else if(o instanceof String) { + } else if (o instanceof String) { return o.equals(this.id); - } else if(o.getClass() != getClass()) { + } else if (o.getClass() != getClass()) { return false; } @@ -174,14 +161,14 @@ public class Playlist implements Serializable { } public static class PlaylistComparator implements Comparator { - @Override - public int compare(Playlist playlist1, Playlist playlist2) { - return playlist1.getName().compareToIgnoreCase(playlist2.getName()); - } - public static List sort(List playlists) { Collections.sort(playlists, new PlaylistComparator()); return playlists; } + + @Override + public int compare(Playlist playlist1, Playlist playlist2) { + return playlist1.getName().compareToIgnoreCase(playlist2.getName()); + } } } diff --git a/app/src/main/java/net/nullsum/audinaut/domain/SearchCritera.java b/app/src/main/java/net/nullsum/audinaut/domain/SearchCritera.java index beacdb3..e065587 100644 --- a/app/src/main/java/net/nullsum/audinaut/domain/SearchCritera.java +++ b/app/src/main/java/net/nullsum/audinaut/domain/SearchCritera.java @@ -68,24 +68,24 @@ public class SearchCritera { // * Replace spaces and wildcard '*' characters with ".*" // * All other characters are properly quoted if (this.pattern == null) { - String regex = ".*"; - String currentPart = ""; + StringBuilder regex = new StringBuilder(".*"); + StringBuilder currentPart = new StringBuilder(); for (int i = 0; i < query.length(); i++) { char c = query.charAt(i); if (c == '*' || c == ' ') { - regex += Pattern.quote(currentPart); - regex += ".*"; - currentPart = ""; + regex.append(Pattern.quote(currentPart.toString())); + regex.append(".*"); + currentPart = new StringBuilder(); } else { - currentPart += c; + currentPart.append(c); } } if (currentPart.length() > 0) { - regex += Pattern.quote(currentPart); + regex.append(Pattern.quote(currentPart.toString())); } - regex += ".*"; - this.pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE); + regex.append(".*"); + this.pattern = Pattern.compile(regex.toString(), Pattern.CASE_INSENSITIVE); } return this.pattern; diff --git a/app/src/main/java/net/nullsum/audinaut/domain/SearchResult.java b/app/src/main/java/net/nullsum/audinaut/domain/SearchResult.java index 18835f6..c98b8c0 100644 --- a/app/src/main/java/net/nullsum/audinaut/domain/SearchResult.java +++ b/app/src/main/java/net/nullsum/audinaut/domain/SearchResult.java @@ -50,13 +50,4 @@ public class SearchResult implements Serializable { return songs; } - public boolean hasArtists() { - return !artists.isEmpty(); - } - public boolean hasAlbums() { - return !albums.isEmpty(); - } - public boolean hasSongs() { - return !songs.isEmpty(); - } } diff --git a/app/src/main/java/net/nullsum/audinaut/domain/User.java b/app/src/main/java/net/nullsum/audinaut/domain/User.java index cf0b15c..cabbf95 100644 --- a/app/src/main/java/net/nullsum/audinaut/domain/User.java +++ b/app/src/main/java/net/nullsum/audinaut/domain/User.java @@ -15,21 +15,19 @@ package net.nullsum.audinaut.domain; -import android.util.Pair; - import java.io.Serializable; import java.util.ArrayList; import java.util.List; public class User implements Serializable { - public static final String ADMIN = "adminRole"; - public static final String SETTINGS = "settingsRole"; - public static final String DOWNLOAD = "downloadRole"; - public static final String UPLOAD = "uploadRole"; - public static final String COVERART = "coverArtRole"; - public static final String COMMENT = "commentRole"; - public static final String STREAM = "streamRole"; public static final List ROLES = new ArrayList<>(); + private static final String ADMIN = "adminRole"; + private static final String SETTINGS = "settingsRole"; + private static final String DOWNLOAD = "downloadRole"; + private static final String UPLOAD = "uploadRole"; + private static final String COVERART = "coverArtRole"; + private static final String COMMENT = "commentRole"; + private static final String STREAM = "streamRole"; static { ROLES.add(ADMIN); @@ -41,66 +39,25 @@ public class User implements Serializable { ROLES.add(COMMENT); } - private String username; - private String password; - private String email; - - private List settings = new ArrayList(); + private final List settings = new ArrayList<>(); private List musicFolders; public User() { } - public String getUsername() { - return username; - } - - public void setUsername(String username) { - this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public List getSettings() { - return settings; - } - public void setSettings(List settings) { - this.settings.clear(); - this.settings.addAll(settings); - } public void addSetting(String name, Boolean value) { settings.add(new Setting(name, value)); } public void addMusicFolder(MusicFolder musicFolder) { - if(musicFolders == null) { + if (musicFolders == null) { musicFolders = new ArrayList<>(); } - musicFolders.add(new MusicFolderSetting(musicFolder.getId(), musicFolder.getName(), false)); + musicFolders.add(new MusicFolderSetting(musicFolder.getId(), musicFolder.getName())); } - public void addMusicFolder(MusicFolderSetting musicFolderSetting, boolean defaultValue) { - if(musicFolders == null) { - musicFolders = new ArrayList<>(); - } - musicFolders.add(new MusicFolderSetting(musicFolderSetting.getName(), musicFolderSetting.getLabel(), defaultValue)); - } public List getMusicFolderSettings() { return musicFolders; } @@ -112,6 +69,7 @@ public class User implements Serializable { public Setting() { } + public Setting(String name, Boolean value) { this.name = name; this.value = value; @@ -120,22 +78,21 @@ public class User implements Serializable { public String getName() { return name; } + public Boolean getValue() { return value; } + public void setValue(Boolean value) { this.value = value; } } public static class MusicFolderSetting extends Setting { - private String label; + private final String label; - public MusicFolderSetting() { - - } - public MusicFolderSetting(String name, String label, Boolean value) { - super(name, value); + public MusicFolderSetting(String name, String label) { + super(name, false); this.label = label; } diff --git a/app/src/main/java/net/nullsum/audinaut/fragments/DownloadFragment.java b/app/src/main/java/net/nullsum/audinaut/fragments/DownloadFragment.java index 6c1ea72..9046ac7 100644 --- a/app/src/main/java/net/nullsum/audinaut/fragments/DownloadFragment.java +++ b/app/src/main/java/net/nullsum/audinaut/fragments/DownloadFragment.java @@ -15,7 +15,6 @@ package net.nullsum.audinaut.fragments; -import android.content.DialogInterface; import android.os.Bundle; import android.os.Handler; import android.support.v7.widget.helper.ItemTouchHelper; @@ -26,13 +25,8 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - import net.nullsum.audinaut.R; +import net.nullsum.audinaut.adapter.DownloadFileAdapter; import net.nullsum.audinaut.adapter.SectionAdapter; import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.service.DownloadFile; @@ -42,9 +36,14 @@ import net.nullsum.audinaut.util.DownloadFileItemHelperCallback; import net.nullsum.audinaut.util.ProgressListener; import net.nullsum.audinaut.util.SilentBackgroundTask; import net.nullsum.audinaut.util.Util; -import net.nullsum.audinaut.adapter.DownloadFileAdapter; import net.nullsum.audinaut.view.UpdateView; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + public class DownloadFragment extends SelectRecyclerFragment implements SectionAdapter.OnItemClickedListener { private long currentRevision; private ScheduledExecutorService executorService; @@ -69,17 +68,7 @@ public class DownloadFragment extends SelectRecyclerFragment imple super.onResume(); final Handler handler = new Handler(); - Runnable runnable = new Runnable() { - @Override - public void run() { - handler.post(new Runnable() { - @Override - public void run() { - update(); - } - }); - } - }; + Runnable runnable = () -> handler.post(this::update); executorService = Executors.newSingleThreadScheduledExecutor(); executorService.scheduleWithFixedDelay(runnable, 0L, 1000L, TimeUnit.MILLISECONDS); @@ -104,11 +93,11 @@ public class DownloadFragment extends SelectRecyclerFragment imple @Override public List getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception { DownloadService downloadService = getDownloadService(); - if(downloadService == null) { - return new ArrayList(); + if (downloadService == null) { + return new ArrayList<>(); } - List songList = new ArrayList(); + List songList = new ArrayList<>(); songList.addAll(downloadService.getBackgroundDownloads()); currentRevision = downloadService.getDownloadListUpdateRevision(); return songList; @@ -128,7 +117,7 @@ public class DownloadFragment extends SelectRecyclerFragment imple public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView updateView, DownloadFile downloadFile) { MusicDirectory.Entry selectedItem = downloadFile.getSong(); onCreateContextMenuSupport(menu, menuInflater, updateView, selectedItem); - if(!Util.isOffline(context)) { + if (!Util.isOffline(context)) { menu.removeItem(R.id.song_menu_remove_playlist); } @@ -143,29 +132,24 @@ public class DownloadFragment extends SelectRecyclerFragment imple @Override public boolean onOptionsItemSelected(MenuItem menuItem) { - if(super.onOptionsItemSelected(menuItem)) { + if (super.onOptionsItemSelected(menuItem)) { return true; } switch (menuItem.getItemId()) { case R.id.menu_remove_all: - Util.confirmDialog(context, R.string.download_menu_remove_all, "", new DialogInterface.OnClickListener() { + Util.confirmDialog(context, R.string.download_menu_remove_all, "", (dialog, which) -> new SilentBackgroundTask(context) { @Override - public void onClick(DialogInterface dialog, int which) { - new SilentBackgroundTask(context) { - @Override - protected Void doInBackground() throws Throwable { - getDownloadService().clearBackground(); - return null; - } - - @Override - protected void done(Void result) { - update(); - } - }.execute(); + protected Void doInBackground() throws Throwable { + getDownloadService().clearBackground(); + return null; } - }); + + @Override + protected void done(Void result) { + update(); + } + }.execute()); return true; } diff --git a/app/src/main/java/net/nullsum/audinaut/fragments/EqualizerFragment.java b/app/src/main/java/net/nullsum/audinaut/fragments/EqualizerFragment.java index e17c8b8..899d4da 100644 --- a/app/src/main/java/net/nullsum/audinaut/fragments/EqualizerFragment.java +++ b/app/src/main/java/net/nullsum/audinaut/fragments/EqualizerFragment.java @@ -29,14 +29,10 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; -import android.widget.CompoundButton; import android.widget.LinearLayout; import android.widget.SeekBar; import android.widget.TextView; -import java.util.HashMap; -import java.util.Map; - import net.nullsum.audinaut.R; import net.nullsum.audinaut.audiofx.EqualizerController; import net.nullsum.audinaut.audiofx.LoudnessEnhancerController; @@ -44,6 +40,9 @@ import net.nullsum.audinaut.service.DownloadService; import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.Util; +import java.util.HashMap; +import java.util.Map; + /** * Created by Scott on 10/27/13. */ @@ -52,7 +51,7 @@ public class EqualizerFragment extends SubsonicFragment { private static final int MENU_GROUP_PRESET = 100; - private final Map bars = new HashMap(); + private final Map bars = new HashMap<>(); private SeekBar bassBar; private SeekBar loudnessBar; private EqualizerController equalizerController; @@ -73,7 +72,7 @@ public class EqualizerFragment extends SubsonicFragment { loudnessEnhancer = equalizerController.getLoudnessEnhancerController(); initEqualizer(); - } catch(Exception e) { + } catch (Exception e) { Log.e(TAG, "Failed to initialize EQ", e); Util.toast(context, "Failed to initialize EQ"); context.onBackPressed(); @@ -81,25 +80,17 @@ public class EqualizerFragment extends SubsonicFragment { final View presetButton = rootView.findViewById(R.id.equalizer_preset); registerForContextMenu(presetButton); - presetButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - presetButton.showContextMenu(); - } - }); + presetButton.setOnClickListener(view -> presetButton.showContextMenu()); - CheckBox enabledCheckBox = (CheckBox) rootView.findViewById(R.id.equalizer_enabled); + CheckBox enabledCheckBox = rootView.findViewById(R.id.equalizer_enabled); enabledCheckBox.setChecked(equalizer.getEnabled()); - enabledCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton compoundButton, boolean b) { - try { - setEqualizerEnabled(b); - } catch(Exception e) { - Log.e(TAG, "Failed to set EQ enabled", e); - Util.toast(context, "Failed to set EQ enabled"); - context.onBackPressed(); - } + enabledCheckBox.setOnCheckedChangeListener((compoundButton, b) -> { + try { + setEqualizerEnabled(b); + } catch (Exception e) { + Log.e(TAG, "Failed to set EQ enabled", e); + Util.toast(context, "Failed to set EQ enabled"); + context.onBackPressed(); } }); @@ -119,7 +110,7 @@ public class EqualizerFragment extends SubsonicFragment { if (!equalizer.getEnabled()) { equalizerController.release(); } - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to release controller", e); } } @@ -135,7 +126,7 @@ public class EqualizerFragment extends SubsonicFragment { @Override public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, view, menuInfo); - if(!primaryFragment) { + if (!primaryFragment) { return; } @@ -158,7 +149,7 @@ public class EqualizerFragment extends SubsonicFragment { @Override public boolean onContextItemSelected(MenuItem menuItem) { short preset = (short) menuItem.getItemId(); - for(int i = 0; i < 10; i++) { + for (int i = 0; i < 10; i++) { try { equalizer.usePreset(preset); i = 10; @@ -178,7 +169,7 @@ public class EqualizerFragment extends SubsonicFragment { SharedPreferences.Editor editor = prefs.edit(); editor.putBoolean(Constants.PREFERENCES_EQUALIZER_ON, enabled); editor.apply(); - for(int i = 0; i < 10; i++) { + for (int i = 0; i < 10; i++) { try { equalizer.setEnabled(enabled); updateBars(true); @@ -245,36 +236,36 @@ public class EqualizerFragment extends SubsonicFragment { editor.putInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, masterLevel); editor.apply(); } - } catch(Exception e) { + } catch (Exception e) { Log.e(TAG, "Failed to update bars"); } } private void initEqualizer() { - LinearLayout layout = (LinearLayout) rootView.findViewById(R.id.equalizer_layout); + LinearLayout layout = rootView.findViewById(R.id.equalizer_layout); final short minEQLevel = equalizer.getBandLevelRange()[0]; final short maxEQLevel = equalizer.getBandLevelRange()[1]; // Setup Pregain SharedPreferences prefs = Util.getPreferences(context); - masterLevel = (short)prefs.getInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, 0); + masterLevel = (short) prefs.getInt(Constants.PREFERENCES_EQUALIZER_SETTINGS, 0); initPregain(layout, minEQLevel, maxEQLevel); for (short i = 0; i < equalizer.getNumberOfBands(); i++) { final short band = i; View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null); - TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency); - final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level); - SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar); + TextView freqTextView = bandBar.findViewById(R.id.equalizer_frequency); + final TextView levelTextView = bandBar.findViewById(R.id.equalizer_level); + SeekBar bar = bandBar.findViewById(R.id.equalizer_bar); freqTextView.setText((equalizer.getCenterFreq(band) / 1000) + " Hz"); bars.put(band, bar); bar.setMax(maxEQLevel - minEQLevel); short level = equalizer.getBandLevel(band); - if(equalizer.getEnabled()) { + if (equalizer.getEnabled()) { level = (short) (level - masterLevel); } bar.setProgress(level - minEQLevel); @@ -290,7 +281,7 @@ public class EqualizerFragment extends SubsonicFragment { equalizer.setBandLevel(band, (short) (level + masterLevel)); } updateLevelText(levelTextView, level); - } catch(Exception e) { + } catch (Exception e) { Log.e(TAG, "Failed to change equalizer", e); } } @@ -306,18 +297,18 @@ public class EqualizerFragment extends SubsonicFragment { layout.addView(bandBar); } - LinearLayout specialLayout = (LinearLayout) rootView.findViewById(R.id.special_effects_layout); + LinearLayout specialLayout = rootView.findViewById(R.id.special_effects_layout); // Setup bass booster View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null); - TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency); - final TextView bassTextView = (TextView) bandBar.findViewById(R.id.equalizer_level); - bassBar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar); + TextView freqTextView = bandBar.findViewById(R.id.equalizer_frequency); + final TextView bassTextView = bandBar.findViewById(R.id.equalizer_level); + bassBar = bandBar.findViewById(R.id.equalizer_bar); freqTextView.setText(R.string.equalizer_bass_booster); bassBar.setEnabled(equalizer.getEnabled()); short bassLevel = 0; - if(bass.getEnabled()) { + if (bass.getEnabled()) { bassLevel = bass.getRoundedStrength(); } bassTextView.setText(context.getResources().getString(R.string.equalizer_bass_size, bassLevel)); @@ -339,7 +330,7 @@ public class EqualizerFragment extends SubsonicFragment { bass.setEnabled(false); } } - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Error on changing bass: ", e); } } @@ -356,17 +347,17 @@ public class EqualizerFragment extends SubsonicFragment { }); specialLayout.addView(bandBar); - if(loudnessEnhancer != null && loudnessEnhancer.isAvailable()) { + if (loudnessEnhancer != null && loudnessEnhancer.isAvailable()) { // Setup loudness enhancer bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null); - freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency); - final TextView loudnessTextView = (TextView) bandBar.findViewById(R.id.equalizer_level); - loudnessBar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar); + freqTextView = bandBar.findViewById(R.id.equalizer_frequency); + final TextView loudnessTextView = bandBar.findViewById(R.id.equalizer_level); + loudnessBar = bandBar.findViewById(R.id.equalizer_bar); freqTextView.setText(R.string.equalizer_voice_booster); loudnessBar.setEnabled(equalizer.getEnabled()); int loudnessLevel = 0; - if(loudnessEnhancer.isEnabled()) { + if (loudnessEnhancer.isEnabled()) { loudnessLevel = (int) loudnessEnhancer.getGain(); } loudnessBar.setProgress(loudnessLevel / 100); @@ -377,18 +368,18 @@ public class EqualizerFragment extends SubsonicFragment { public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { try { loudnessTextView.setText(context.getResources().getString(R.string.equalizer_db_size, progress)); - if(fromUser) { - if(progress > 0) { - if(!loudnessEnhancer.isEnabled()) { + if (fromUser) { + if (progress > 0) { + if (!loudnessEnhancer.isEnabled()) { loudnessEnhancer.enable(); } loudnessEnhancer.setGain(progress * 100); - } else if(progress == 0 && loudnessEnhancer.isEnabled()) { + } else if (progress == 0 && loudnessEnhancer.isEnabled()) { loudnessEnhancer.setGain(progress * 100); loudnessEnhancer.disable(); } } - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Error on changing loudness: ", e); } } @@ -409,13 +400,13 @@ public class EqualizerFragment extends SubsonicFragment { private void initPregain(LinearLayout layout, final short minEQLevel, final short maxEQLevel) { View bandBar = LayoutInflater.from(context).inflate(R.layout.equalizer_bar, null); - TextView freqTextView = (TextView) bandBar.findViewById(R.id.equalizer_frequency); - final TextView levelTextView = (TextView) bandBar.findViewById(R.id.equalizer_level); - SeekBar bar = (SeekBar) bandBar.findViewById(R.id.equalizer_bar); + TextView freqTextView = bandBar.findViewById(R.id.equalizer_frequency); + final TextView levelTextView = bandBar.findViewById(R.id.equalizer_level); + SeekBar bar = bandBar.findViewById(R.id.equalizer_bar); freqTextView.setText("Master"); - bars.put((short)-1, bar); + bars.put((short) -1, bar); bar.setMax(maxEQLevel - minEQLevel); bar.setProgress(masterLevel - minEQLevel); bar.setEnabled(equalizer.getEnabled()); @@ -437,7 +428,7 @@ public class EqualizerFragment extends SubsonicFragment { } } updateLevelText(levelTextView, masterLevel); - } catch(Exception e) { + } catch (Exception e) { Log.e(TAG, "Failed to change equalizer", e); } } diff --git a/app/src/main/java/net/nullsum/audinaut/fragments/MainFragment.java b/app/src/main/java/net/nullsum/audinaut/fragments/MainFragment.java index 8fead61..5a5d700 100644 --- a/app/src/main/java/net/nullsum/audinaut/fragments/MainFragment.java +++ b/app/src/main/java/net/nullsum/audinaut/fragments/MainFragment.java @@ -1,15 +1,7 @@ package net.nullsum.audinaut.fragments; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.res.Resources; -import android.net.Uri; -import android.os.Build; -import android.os.Environment; import android.content.SharedPreferences; import android.os.Bundle; -import android.os.StatFs; -import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -17,32 +9,17 @@ import android.view.MenuItem; import net.nullsum.audinaut.R; import net.nullsum.audinaut.adapter.MainAdapter; import net.nullsum.audinaut.adapter.SectionAdapter; -import net.nullsum.audinaut.util.Constants; -import net.nullsum.audinaut.util.EnvironmentVariables; -import net.nullsum.audinaut.util.FileUtil; -import net.nullsum.audinaut.util.LoadingTask; -import net.nullsum.audinaut.util.ProgressListener; -import net.nullsum.audinaut.util.UserUtil; -import net.nullsum.audinaut.util.Util; import net.nullsum.audinaut.service.MusicService; -import net.nullsum.audinaut.service.MusicServiceFactory; +import net.nullsum.audinaut.util.Constants; +import net.nullsum.audinaut.util.ProgressListener; +import net.nullsum.audinaut.util.Util; import net.nullsum.audinaut.view.UpdateView; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.net.URL; -import java.net.URLEncoder; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.List; public class MainFragment extends SelectRecyclerFragment { - private static final String TAG = MainFragment.class.getSimpleName(); public static final String SONGS_LIST_PREFIX = "songs-"; public static final String SONGS_NEWEST = SONGS_LIST_PREFIX + "newest"; public static final String SONGS_TOP_PLAYED = SONGS_LIST_PREFIX + "topPlayed"; @@ -63,15 +40,6 @@ public class MainFragment extends SelectRecyclerFragment { onFinishSetupOptionsMenu(menu); } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if(super.onOptionsItemSelected(item)) { - return true; - } - - return false; - } - @Override public int getOptionsMenu() { return 0; @@ -98,7 +66,7 @@ public class MainFragment extends SelectRecyclerFragment { @Override public List getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception { - return Arrays.asList(0); + return Collections.singletonList(0); } @Override @@ -107,15 +75,15 @@ public class MainFragment extends SelectRecyclerFragment { } private void showAlbumList(String type) { - if("genres".equals(type)) { + if ("genres".equals(type)) { SubsonicFragment fragment = new SelectGenreFragment(); replaceFragment(fragment); - } else if("years".equals(type)) { + } else if ("years".equals(type)) { SubsonicFragment fragment = new SelectYearFragment(); replaceFragment(fragment); } else { // Clear out recently added count when viewing - if("newest".equals(type)) { + if ("newest".equals(type)) { SharedPreferences.Editor editor = Util.getPreferences(context).edit(); editor.putInt(Constants.PREFERENCES_KEY_RECENT_COUNT + Util.getActiveServer(context), 0); editor.apply(); @@ -132,59 +100,6 @@ public class MainFragment extends SelectRecyclerFragment { } } - private void showAboutDialog() { - new LoadingTask(context) { - Long[] used; - long bytesTotalFs; - long bytesAvailableFs; - - @Override - protected Void doInBackground() throws Throwable { - File rootFolder = FileUtil.getMusicDirectory(context); - StatFs stat = new StatFs(rootFolder.getPath()); - bytesTotalFs = (long) stat.getBlockCount() * (long) stat.getBlockSize(); - bytesAvailableFs = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize(); - - used = FileUtil.getUsedSize(context, rootFolder); - return null; - } - - @Override - protected void done(Void result) { - List headers = new ArrayList<>(); - List details = new ArrayList<>(); - - headers.add(R.string.details_author); - details.add("Andrew Rabert"); - - headers.add(R.string.details_email); - details.add("ar@nullsum.net"); - - try { - headers.add(R.string.details_version); - details.add(context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName); - } catch(Exception e) { - details.add(""); - } - - Resources res = context.getResources(); - headers.add(R.string.details_files_cached); - details.add(Long.toString(used[0])); - - headers.add(R.string.details_files_permanent); - details.add(Long.toString(used[1])); - - headers.add(R.string.details_used_space); - details.add(res.getString(R.string.details_of, Util.formatLocalizedBytes(used[2], context), Util.formatLocalizedBytes(Util.getCacheSizeMB(context) * 1024L * 1024L, context))); - - headers.add(R.string.details_available_space); - details.add(res.getString(R.string.details_of, Util.formatLocalizedBytes(bytesAvailableFs, context), Util.formatLocalizedBytes(bytesTotalFs, context))); - - Util.showDetailsDialog(context, R.string.main_about_title, headers, details); - } - }.execute(); - } - @Override public void onItemClicked(UpdateView updateView, Integer item) { if (item == R.string.main_albums_random) { @@ -193,11 +108,11 @@ public class MainFragment extends SelectRecyclerFragment { showAlbumList("recent"); } else if (item == R.string.main_albums_frequent) { showAlbumList("frequent"); - } else if(item == R.string.main_albums_genres) { + } else if (item == R.string.main_albums_genres) { showAlbumList("genres"); - } else if(item == R.string.main_albums_year) { + } else if (item == R.string.main_albums_year) { showAlbumList("years"); - } else if(item == R.string.main_albums_alphabetical) { + } else if (item == R.string.main_albums_alphabetical) { showAlbumList("alphabeticalByName"); } else if (item == R.string.main_songs_newest) { showAlbumList(SONGS_NEWEST); @@ -211,7 +126,8 @@ public class MainFragment extends SelectRecyclerFragment { } @Override - public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView updateView, Integer item) {} + public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView updateView, Integer item) { + } @Override public boolean onContextItemSelected(MenuItem menuItem, UpdateView updateView, Integer item) { diff --git a/app/src/main/java/net/nullsum/audinaut/fragments/NowPlayingFragment.java b/app/src/main/java/net/nullsum/audinaut/fragments/NowPlayingFragment.java index 219b244..209785a 100644 --- a/app/src/main/java/net/nullsum/audinaut/fragments/NowPlayingFragment.java +++ b/app/src/main/java/net/nullsum/audinaut/fragments/NowPlayingFragment.java @@ -14,25 +14,13 @@ */ package net.nullsum.audinaut.fragments; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import android.support.v7.app.AlertDialog; -import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.os.Build; import android.os.Bundle; import android.os.Handler; -import android.support.v4.view.MenuItemCompat; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; -import android.util.Log; import android.view.Display; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; @@ -42,19 +30,18 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; -import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.WindowManager; import android.view.animation.AnimationUtils; -import android.widget.EditText; import android.widget.ImageButton; import android.widget.ImageView; -import android.widget.PopupMenu; import android.widget.SeekBar; import android.widget.TextView; import android.widget.ViewFlipper; + import net.nullsum.audinaut.R; import net.nullsum.audinaut.activity.SubsonicFragmentActivity; +import net.nullsum.audinaut.adapter.DownloadFileAdapter; import net.nullsum.audinaut.adapter.SectionAdapter; import net.nullsum.audinaut.audiofx.EqualizerController; import net.nullsum.audinaut.domain.PlayerState; @@ -62,26 +49,33 @@ import net.nullsum.audinaut.domain.RepeatMode; import net.nullsum.audinaut.service.DownloadFile; import net.nullsum.audinaut.service.DownloadService; import net.nullsum.audinaut.service.DownloadService.OnSongChangedListener; -import net.nullsum.audinaut.service.MusicService; -import net.nullsum.audinaut.service.MusicServiceFactory; -import net.nullsum.audinaut.service.OfflineException; import net.nullsum.audinaut.util.Constants; +import net.nullsum.audinaut.util.DownloadFileItemHelperCallback; +import net.nullsum.audinaut.util.DrawableTint; +import net.nullsum.audinaut.util.FileUtil; +import net.nullsum.audinaut.util.MenuUtil; import net.nullsum.audinaut.util.SilentBackgroundTask; -import net.nullsum.audinaut.adapter.DownloadFileAdapter; +import net.nullsum.audinaut.util.Util; +import net.nullsum.audinaut.view.AutoRepeatButton; import net.nullsum.audinaut.view.FadeOutAnimation; import net.nullsum.audinaut.view.FastScroller; import net.nullsum.audinaut.view.UpdateView; -import net.nullsum.audinaut.util.Util; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; import static net.nullsum.audinaut.domain.MusicDirectory.Entry; -import static net.nullsum.audinaut.domain.PlayerState.*; -import net.nullsum.audinaut.util.*; -import net.nullsum.audinaut.view.AutoRepeatButton; -import java.util.ArrayList; -import java.util.concurrent.ScheduledFuture; +import static net.nullsum.audinaut.domain.PlayerState.COMPLETED; +import static net.nullsum.audinaut.domain.PlayerState.IDLE; +import static net.nullsum.audinaut.domain.PlayerState.PAUSED; +import static net.nullsum.audinaut.domain.PlayerState.STOPPED; public class NowPlayingFragment extends SubsonicFragment implements OnGestureListener, SectionAdapter.OnItemClickedListener, OnSongChangedListener { - private static final String TAG = NowPlayingFragment.class.getSimpleName(); private static final int PERCENTAGE_OF_SCREEN_FOR_SWIPE = 10; private static final int ACTION_PREVIOUS = 1; @@ -128,8 +122,8 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if(savedInstanceState != null) { - if(savedInstanceState.getInt(Constants.FRAGMENT_DOWNLOAD_FLIPPER) == 1) { + if (savedInstanceState != null) { + if (savedInstanceState.getInt(Constants.FRAGMENT_DOWNLOAD_FLIPPER) == 1) { startFlipped = true; } } @@ -151,198 +145,136 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis Display d = w.getDefaultDisplay(); swipeDistance = (d.getWidth() + d.getHeight()) * PERCENTAGE_OF_SCREEN_FOR_SWIPE / 100; swipeVelocity = (d.getWidth() + d.getHeight()) * PERCENTAGE_OF_SCREEN_FOR_SWIPE / 100; - gestureScanner = new GestureDetector(this); + gestureScanner = new GestureDetector(context, this); - playlistFlipper = (ViewFlipper)rootView.findViewById(R.id.download_playlist_flipper); - emptyTextView = (TextView)rootView.findViewById(R.id.download_empty); - songTitleTextView = (TextView)rootView.findViewById(R.id.download_song_title); - albumArtImageView = (ImageView)rootView.findViewById(R.id.download_album_art_image); - positionTextView = (TextView)rootView.findViewById(R.id.download_position); - durationTextView = (TextView)rootView.findViewById(R.id.download_duration); - statusTextView = (TextView)rootView.findViewById(R.id.download_status); - progressBar = (SeekBar)rootView.findViewById(R.id.download_progress_bar); - previousButton = (AutoRepeatButton)rootView.findViewById(R.id.download_previous); - nextButton = (AutoRepeatButton)rootView.findViewById(R.id.download_next); - rewindButton = (AutoRepeatButton) rootView.findViewById(R.id.download_rewind); - fastforwardButton = (AutoRepeatButton) rootView.findViewById(R.id.download_fastforward); - pauseButton =rootView.findViewById(R.id.download_pause); - stopButton =rootView.findViewById(R.id.download_stop); - startButton =rootView.findViewById(R.id.download_start); - repeatButton = (ImageButton)rootView.findViewById(R.id.download_repeat); - toggleListButton =rootView.findViewById(R.id.download_toggle_list); + playlistFlipper = rootView.findViewById(R.id.download_playlist_flipper); + emptyTextView = rootView.findViewById(R.id.download_empty); + songTitleTextView = rootView.findViewById(R.id.download_song_title); + albumArtImageView = rootView.findViewById(R.id.download_album_art_image); + positionTextView = rootView.findViewById(R.id.download_position); + durationTextView = rootView.findViewById(R.id.download_duration); + statusTextView = rootView.findViewById(R.id.download_status); + progressBar = rootView.findViewById(R.id.download_progress_bar); + previousButton = rootView.findViewById(R.id.download_previous); + nextButton = rootView.findViewById(R.id.download_next); + rewindButton = rootView.findViewById(R.id.download_rewind); + fastforwardButton = rootView.findViewById(R.id.download_fastforward); + pauseButton = rootView.findViewById(R.id.download_pause); + stopButton = rootView.findViewById(R.id.download_stop); + startButton = rootView.findViewById(R.id.download_start); + repeatButton = rootView.findViewById(R.id.download_repeat); + toggleListButton = rootView.findViewById(R.id.download_toggle_list); - playlistView = (RecyclerView)rootView.findViewById(R.id.download_list); - FastScroller fastScroller = (FastScroller) rootView.findViewById(R.id.download_fast_scroller); + playlistView = rootView.findViewById(R.id.download_list); + FastScroller fastScroller = rootView.findViewById(R.id.download_fast_scroller); fastScroller.attachRecyclerView(playlistView); setupLayoutManager(playlistView, false); ItemTouchHelper touchHelper = new ItemTouchHelper(new DownloadFileItemHelperCallback(this, true)); touchHelper.attachToRecyclerView(playlistView); - View.OnTouchListener touchListener = new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent me) { - return gestureScanner.onTouchEvent(me); - } - }; + View.OnTouchListener touchListener = (v, me) -> gestureScanner.onTouchEvent(me); pauseButton.setOnTouchListener(touchListener); stopButton.setOnTouchListener(touchListener); startButton.setOnTouchListener(touchListener); emptyTextView.setOnTouchListener(touchListener); - albumArtImageView.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent me) { - if (me.getAction() == MotionEvent.ACTION_DOWN) { - lastY = (int) me.getRawY(); + albumArtImageView.setOnTouchListener((v, me) -> { + if (me.getAction() == MotionEvent.ACTION_DOWN) { + lastY = (int) me.getRawY(); + } + return gestureScanner.onTouchEvent(me); + }); + + previousButton.setOnClickListener(view -> { + warnIfStorageUnavailable(); + new SilentBackgroundTask(context) { + @Override + protected Void doInBackground() throws Throwable { + getDownloadService().previous(); + return null; } - return gestureScanner.onTouchEvent(me); - } + }.execute(); + setControlsVisible(true); }); + previousButton.setOnRepeatListener(() -> changeProgress(true)); - previousButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - warnIfStorageUnavailable(); - new SilentBackgroundTask(context) { - @Override - protected Void doInBackground() throws Throwable { - getDownloadService().previous(); - return null; - } - }.execute(); - setControlsVisible(true); - } - }); - previousButton.setOnRepeatListener(new Runnable() { - public void run() { - changeProgress(true); - } - }); - - nextButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - warnIfStorageUnavailable(); - new SilentBackgroundTask(context) { - @Override - protected Boolean doInBackground() throws Throwable { - getDownloadService().next(); - return true; - } - }.execute(); - setControlsVisible(true); - } - }); - nextButton.setOnRepeatListener(new Runnable() { - public void run() { - changeProgress(false); - } - }); - - rewindButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - changeProgress(true); - } - }); - rewindButton.setOnRepeatListener(new Runnable() { - public void run() { - changeProgress(true); - } - }); - - fastforwardButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - changeProgress(false); - } - }); - fastforwardButton.setOnRepeatListener(new Runnable() { - public void run() { - changeProgress(false); - } - }); - - - pauseButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - new SilentBackgroundTask(context) { - @Override - protected Void doInBackground() throws Throwable { - getDownloadService().pause(); - return null; - } - }.execute(); - } - }); - - stopButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - new SilentBackgroundTask(context) { - @Override - protected Void doInBackground() throws Throwable { - getDownloadService().reset(); - return null; - } - }.execute(); - } - }); - - startButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - warnIfStorageUnavailable(); - new SilentBackgroundTask(context) { - @Override - protected Void doInBackground() throws Throwable { - start(); - return null; - } - }.execute(); - } - }); - - repeatButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - RepeatMode repeatMode = getDownloadService().getRepeatMode().next(); - getDownloadService().setRepeatMode(repeatMode); - switch (repeatMode) { - case OFF: - Util.toast(context, R.string.download_repeat_off); - break; - case ALL: - Util.toast(context, R.string.download_repeat_all); - break; - case SINGLE: - Util.toast(context, R.string.download_repeat_single); - break; - default: - break; + nextButton.setOnClickListener(view -> { + warnIfStorageUnavailable(); + new SilentBackgroundTask(context) { + @Override + protected Boolean doInBackground() throws Throwable { + getDownloadService().next(); + return true; } - updateRepeatButton(); - setControlsVisible(true); + }.execute(); + setControlsVisible(true); + }); + nextButton.setOnRepeatListener(() -> changeProgress(false)); + + rewindButton.setOnClickListener(view -> changeProgress(true)); + rewindButton.setOnRepeatListener(() -> changeProgress(true)); + + fastforwardButton.setOnClickListener(view -> changeProgress(false)); + fastforwardButton.setOnRepeatListener(() -> changeProgress(false)); + + + pauseButton.setOnClickListener(view -> new SilentBackgroundTask(context) { + @Override + protected Void doInBackground() throws Throwable { + getDownloadService().pause(); + return null; } + }.execute()); + + stopButton.setOnClickListener(view -> new SilentBackgroundTask(context) { + @Override + protected Void doInBackground() throws Throwable { + getDownloadService().reset(); + return null; + } + }.execute()); + + startButton.setOnClickListener(view -> { + warnIfStorageUnavailable(); + new SilentBackgroundTask(context) { + @Override + protected Void doInBackground() throws Throwable { + start(); + return null; + } + }.execute(); }); - toggleListButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - toggleFullscreenAlbumArt(); - setControlsVisible(true); + repeatButton.setOnClickListener(view -> { + RepeatMode repeatMode = getDownloadService().getRepeatMode().next(); + getDownloadService().setRepeatMode(repeatMode); + switch (repeatMode) { + case OFF: + Util.toast(context, R.string.download_repeat_off); + break; + case ALL: + Util.toast(context, R.string.download_repeat_all); + break; + case SINGLE: + Util.toast(context, R.string.download_repeat_single); + break; + default: + break; } + updateRepeatButton(); + setControlsVisible(true); + }); + + toggleListButton.setOnClickListener(view -> { + toggleFullscreenAlbumArt(); + setControlsVisible(true); }); View overlay = rootView.findViewById(R.id.download_overlay_buttons); final int overlayHeight = overlay != null ? overlay.getHeight() : -1; - albumArtImageView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (overlayHeight == -1 || lastY < (view.getBottom() - overlayHeight)) { - toggleFullscreenAlbumArt(); - setControlsVisible(true); - } + albumArtImageView.setOnClickListener(view -> { + if (overlayHeight == -1 || lastY < (view.getBottom() - overlayHeight)) { + toggleFullscreenAlbumArt(); + setControlsVisible(true); } }); @@ -383,20 +315,20 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis @Override public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) { DownloadService downloadService = getDownloadService(); - if(Util.isOffline(context)) { + if (Util.isOffline(context)) { menuInflater.inflate(R.menu.nowplaying_offline, menu); } else { menuInflater.inflate(R.menu.nowplaying, menu); } - if(downloadService != null && downloadService.isRemovePlayed()) { + if (downloadService != null && downloadService.isRemovePlayed()) { menu.findItem(R.id.menu_remove_played).setChecked(true); } - if(downloadService != null) { + if (downloadService != null) { SharedPreferences prefs = Util.getPreferences(context); boolean equalizerOn = prefs.getBoolean(Constants.PREFERENCES_EQUALIZER_ON, false); if (equalizerOn && downloadService != null) { - if(downloadService.getEqualizerController() != null && downloadService.getEqualizerController().isEnabled()) { + if (downloadService.getEqualizerController() != null && downloadService.getEqualizerController().isEnabled()) { menu.findItem(R.id.menu_equalizer).setChecked(true); } } @@ -404,23 +336,20 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis menu.removeItem(R.id.menu_equalizer); } - if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_BATCH_MODE, false)) { + if (Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_BATCH_MODE, false)) { menu.findItem(R.id.menu_batch_mode).setChecked(true); } } @Override public boolean onOptionsItemSelected(MenuItem menuItem) { - if(menuItemSelected(menuItem.getItemId(), null)) { - return true; - } + return menuItemSelected(menuItem.getItemId(), null) || super.onOptionsItemSelected(menuItem); - return super.onOptionsItemSelected(menuItem); } @Override public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView updateView, DownloadFile downloadFile) { - if(Util.isOffline(context)) { + if (Util.isOffline(context)) { menuInflater.inflate(R.menu.nowplaying_context_offline, menu); } else { menuInflater.inflate(R.menu.nowplaying_context, menu); @@ -436,39 +365,25 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis @Override public boolean onContextItemSelected(MenuItem menuItem, UpdateView updateView, DownloadFile downloadFile) { - if(onContextItemSelected(menuItem, downloadFile.getSong())) { - return true; - } + return onContextItemSelected(menuItem, downloadFile.getSong()) || menuItemSelected(menuItem.getItemId(), downloadFile); - return menuItemSelected(menuItem.getItemId(), downloadFile); } private boolean menuItemSelected(int menuItemId, final DownloadFile song) { - List songs; switch (menuItemId) { - case R.id.menu_show_album: case R.id.menu_show_artist: + case R.id.menu_show_album: + case R.id.menu_show_artist: Entry entry = song.getSong(); Intent intent = new Intent(context, SubsonicFragmentActivity.class); intent.putExtra(Constants.INTENT_EXTRA_VIEW_ALBUM, true); String albumId; String albumName; - if(menuItemId == R.id.menu_show_album) { - if(Util.isTagBrowsing(context)) { - albumId = entry.getAlbumId(); - } else { - albumId = entry.getParent(); - } + if (menuItemId == R.id.menu_show_album) { + albumId = entry.getAlbumId(); albumName = entry.getAlbum(); } else { - if(Util.isTagBrowsing(context)) { - albumId = entry.getArtistId(); - } else { - albumId = entry.getGrandParent(); - if(albumId == null) { - intent.putExtra(Constants.INTENT_EXTRA_NAME_CHILD_ID, entry.getParent()); - } - } + albumId = entry.getArtistId(); albumName = entry.getArtist(); intent.putExtra(Constants.INTENT_EXTRA_NAME_ARTIST, true); } @@ -476,23 +391,23 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, albumName); intent.putExtra(Constants.INTENT_EXTRA_FRAGMENT_TYPE, "Artist"); - if(Util.isOffline(context)) { + if (Util.isOffline(context)) { try { // This should only be successful if this is a online song in offline mode Integer.parseInt(entry.getParent()); String root = FileUtil.getMusicDirectory(context).getPath(); String id = root + "/" + entry.getPath(); id = id.substring(0, id.lastIndexOf("/")); - if(menuItemId == R.id.menu_show_album) { + if (menuItemId == R.id.menu_show_album) { intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, id); } id = id.substring(0, id.lastIndexOf("/")); - if(menuItemId != R.id.menu_show_album) { + if (menuItemId != R.id.menu_show_album) { intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, id); intent.putExtra(Constants.INTENT_EXTRA_NAME_NAME, entry.getArtist()); intent.removeExtra(Constants.INTENT_EXTRA_NAME_CHILD_ID); } - } catch(Exception e) { + } catch (Exception e) { // Do nothing, entry.getParent() is fine } } @@ -501,24 +416,19 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis Util.startActivityWithoutTransition(context, intent); return true; case R.id.menu_remove_all: - Util.confirmDialog(context, R.string.download_menu_remove_all, "", new DialogInterface.OnClickListener() { + Util.confirmDialog(context, R.string.download_menu_remove_all, "", (dialog, which) -> new SilentBackgroundTask(context) { @Override - public void onClick(DialogInterface dialog, int which) { - new SilentBackgroundTask(context) { - @Override - protected Void doInBackground() throws Throwable { - getDownloadService().setShufflePlayEnabled(false); - getDownloadService().clear(); - return null; - } - - @Override - protected void done(Void result) { - context.closeNowPlaying(); - } - }.execute(); + protected Void doInBackground() throws Throwable { + getDownloadService().setShufflePlayEnabled(false); + getDownloadService().clear(); + return null; } - }); + + @Override + protected void done(Void result) { + context.closeNowPlaying(); + } + }.execute()); return true; case R.id.menu_remove_played: if (getDownloadService().isRemovePlayed()) { @@ -543,7 +453,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis }.execute(); return true; case R.id.menu_save_playlist: - List entries = new LinkedList(); + List entries = new LinkedList<>(); for (DownloadFile downloadFile : getDownloadService().getSongs()) { entries.add(downloadFile.getSong()); } @@ -556,7 +466,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis DownloadService downloadService = getDownloadService(); if (downloadService != null) { EqualizerController controller = downloadService.getEqualizerController(); - if(controller != null) { + if (controller != null) { SubsonicFragment fragment = new EqualizerFragment(); replaceFragment(fragment); setControlsVisible(true); @@ -568,8 +478,9 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis // Any failed condition will get here Util.toast(context, "Failed to start equalizer. Try restarting."); return true; - }case R.id.menu_batch_mode: - if(Util.isBatchMode(context)) { + } + case R.id.menu_batch_mode: + if (Util.isBatchMode(context)) { Util.setBatchMode(context, false); songListAdapter.notifyDataSetChanged(); } else { @@ -587,12 +498,13 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis @Override public void onResume() { super.onResume(); - if(this.primaryFragment) { + if (this.primaryFragment) { onResumeHandlers(); } else { update(); } } + private void onResumeHandlers() { executorService = Executors.newSingleThreadScheduledExecutor(); setControlsVisible(true); @@ -603,22 +515,17 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis startFlipped = false; } - updateButtons(); - - if(currentPlaying == null && downloadService != null && currentPlaying == downloadService.getCurrentPlaying()) { - getImageLoader().loadImage(albumArtImageView, (Entry) null, true, false); + if (currentPlaying == null && downloadService != null && currentPlaying == downloadService.getCurrentPlaying()) { + getImageLoader().loadImage(albumArtImageView, null, true, false); } - context.runWhenServiceAvailable(new Runnable() { - @Override - public void run() { - if (primaryFragment) { - DownloadService downloadService = getDownloadService(); - downloadService.addOnSongChangedListener(NowPlayingFragment.this, true); - } - updateRepeatButton(); - updateTitle(); + context.runWhenServiceAvailable(() -> { + if (primaryFragment) { + DownloadService downloadService1 = getDownloadService(); + downloadService1.addOnSongChangedListener(NowPlayingFragment.this); } + updateRepeatButton(); + updateTitle(); }); } @@ -627,8 +534,9 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis super.onPause(); onPauseHandlers(); } + private void onPauseHandlers() { - if(executorService != null) { + if (executorService != null) { DownloadService downloadService = getDownloadService(); if (downloadService != null) { downloadService.removeOnSongChangeListener(this); @@ -640,8 +548,8 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis @Override public void setPrimaryFragment(boolean primary) { super.setPrimaryFragment(primary); - if(rootView != null) { - if(primary) { + if (rootView != null) { + if (primary) { onResumeHandlers(); } else { onPauseHandlers(); @@ -650,16 +558,17 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis } @Override - public void setTitle(int title) { + void setTitle(int title) { this.title = context.getResources().getString(title); - if(this.primaryFragment) { + if (this.primaryFragment) { context.setTitle(this.title); } } + @Override - public void setSubtitle(CharSequence title) { + void setSubtitle(CharSequence title) { this.subtitle = title; - if(this.primaryFragment) { + if (this.primaryFragment) { context.setSubtitle(title); } } @@ -675,22 +584,11 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis } final Handler handler = new Handler(); - Runnable runnable = new Runnable() { - @Override - public void run() { - handler.post(new Runnable() { - @Override - public void run() { - setControlsVisible(false); - } - }); - } - }; + Runnable runnable = () -> handler.post(() -> setControlsVisible(false)); hideControlsFuture = executorService.schedule(runnable, 3000L, TimeUnit.MILLISECONDS); } private void setControlsVisible(boolean visible) { - DownloadService downloadService = getDownloadService(); try { long duration = 1700L; FadeOutAnimation.createAndStart(rootView.findViewById(R.id.download_overlay_buttons), !visible, duration); @@ -698,17 +596,11 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis if (visible) { scheduleHideControls(); } - } catch(Exception e) { + } catch (Exception ignored) { } } - private void updateButtons() { - if(context == null) { - return; - } - } - // Scroll to current playing/downloading. private void scrollToCurrent() { if (getDownloadService() == null || songListAdapter == null) { @@ -718,13 +610,13 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis // Try to get position of current playing/downloading int position = songListAdapter.getItemPosition(currentPlaying); - if(position == -1) { + if (position == -1) { DownloadFile currentDownloading = getDownloadService().getCurrentDownloading(); position = songListAdapter.getItemPosition(currentDownloading); } // If found, scroll to it - if(position != -1) { + if (position != -1) { // RecyclerView.scrollToPosition just puts it on the screen (ie: bottom if scrolled below it) LinearLayoutManager layoutManager = (LinearLayoutManager) playlistView.getLayoutManager(); layoutManager.scrollToPositionWithOffset(position, 0); @@ -732,26 +624,12 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis } private void update() { - if(startFlipped) { + if (startFlipped) { startFlipped = false; scrollToCurrent(); } } - private int getMinutes(int progress) { - if(progress < 30) { - return progress + 1; - } else if(progress < 49) { - return (progress - 30) * 5 + getMinutes(29); - } else if(progress < 57) { - return (progress - 48) * 30 + getMinutes(48); - } else if(progress < 81) { - return (progress - 56) * 60 + getMinutes(56); - } else { - return (progress - 80) * 150 + getMinutes(80); - } - } - private void toggleFullscreenAlbumArt() { if (playlistFlipper.getDisplayedChild() == 1) { playlistFlipper.setInAnimation(AnimationUtils.loadAnimation(context, R.anim.push_down_in)); @@ -786,7 +664,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis private void changeProgress(final boolean rewind) { final DownloadService downloadService = getDownloadService(); - if(downloadService == null) { + if (downloadService == null) { return; } @@ -795,7 +673,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis @Override protected Void doInBackground() throws Throwable { - if(rewind) { + if (rewind) { seekTo = downloadService.rewind(); } else { seekTo = downloadService.fastForward(); @@ -841,13 +719,13 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis action = ACTION_REWIND; } - if(action > 0) { + if (action > 0) { final int performAction = action; warnIfStorageUnavailable(); new SilentBackgroundTask(context) { @Override protected Void doInBackground() throws Throwable { - switch(performAction) { + switch (performAction) { case ACTION_NEXT: downloadService.next(); break; @@ -929,14 +807,14 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis getImageLoader().loadImage(albumArtImageView, song, true, true); DownloadService downloadService = getDownloadService(); - if(downloadService.isShufflePlayEnabled()) { + if (downloadService.isShufflePlayEnabled()) { setSubtitle(context.getResources().getString(R.string.download_playerstate_playing_shuffle)); } else { setSubtitle(context.getResources().getString(R.string.download_playing_out_of, currentPlayingIndex + 1, currentPlayingSize)); } } else { songTitleTextView.setText(null); - getImageLoader().loadImage(albumArtImageView, (Entry) null, true, false); + getImageLoader().loadImage(albumArtImageView, null, true, false); setSubtitle(null); } } @@ -946,14 +824,13 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis currentPlayingSize = songs.size(); DownloadService downloadService = getDownloadService(); - if(downloadService.isShufflePlayEnabled()) { + if (downloadService.isShufflePlayEnabled()) { emptyTextView.setText(R.string.download_shuffle_loading); - } - else { + } else { emptyTextView.setText(R.string.download_empty); } - if(songListAdapter == null) { + if (songListAdapter == null) { songList = new ArrayList<>(); songList.addAll(songs); playlistView.setAdapter(songListAdapter = new DownloadFileAdapter(context, songList, NowPlayingFragment.this)); @@ -965,12 +842,12 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis emptyTextView.setVisibility(songs.isEmpty() ? View.VISIBLE : View.GONE); - if(scrollWhenLoaded) { + if (scrollWhenLoaded) { scrollToCurrent(); scrollWhenLoaded = false; } - if(this.currentPlaying != currentPlaying) { + if (this.currentPlaying != currentPlaying) { onSongChanged(currentPlaying, currentPlayingIndex); onMetadataUpdate(currentPlaying != null ? currentPlaying.getSong() : null, DownloadService.METADATA_UPDATED_ALL); } else { @@ -987,13 +864,13 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis int millisTotal = duration == null ? 0 : duration; positionTextView.setText(Util.formatDuration(millisPlayed / 1000)); - if(millisTotal > 0) { + if (millisTotal > 0) { durationTextView.setText(Util.formatDuration(millisTotal / 1000)); } else { durationTextView.setText("-:--"); } progressBar.setMax(millisTotal == 0 ? 100 : millisTotal); // Work-around for apparent bug. - if(!seekInProgress) { + if (!seekInProgress) { progressBar.setProgress(millisPlayed); } progressBar.setEnabled(isSeekable); @@ -1006,11 +883,11 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis } @Override - public void onStateUpdate(DownloadFile downloadFile, PlayerState playerState) { + public void onStateUpdate(PlayerState playerState) { switch (playerState) { case DOWNLOADING: - if(currentPlaying != null) { - if(Util.isWifiRequiredForDownload(context)) { + if (currentPlaying != null) { + if (Util.isWifiRequiredForDownload(context)) { statusTextView.setText(context.getResources().getString(R.string.download_playerstate_mobile_disabled)); } else { long bytes = currentPlaying.getPartialFile().length(); @@ -1022,9 +899,9 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis statusTextView.setText(R.string.download_playerstate_buffering); break; default: - if(currentPlaying != null) { + if (currentPlaying != null) { Entry entry = currentPlaying.getSong(); - if(entry.getAlbum() != null) { + if (entry.getAlbum() != null) { String artist = ""; if (entry.getArtist() != null) { artist = currentPlaying.getSong().getArtist().trim() + " - "; @@ -1061,12 +938,12 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis @Override public void onMetadataUpdate(Entry song, int fieldChange) { - if(song != null && albumArtImageView != null && fieldChange == DownloadService.METADATA_UPDATED_COVER_ART) { + if (song != null && albumArtImageView != null && fieldChange == DownloadService.METADATA_UPDATED_COVER_ART) { getImageLoader().loadImage(albumArtImageView, song, true, true); } } - public void updateRepeatButton() { + private void updateRepeatButton() { DownloadService downloadService = getDownloadService(); switch (downloadService.getRepeatMode()) { case OFF: @@ -1082,9 +959,8 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis break; } } - private void updateTitle() { - DownloadService downloadService = getDownloadService(); + private void updateTitle() { String title = context.getResources().getString(R.string.button_bar_now_playing); setTitle(title); @@ -1095,8 +971,8 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis List selected = getCurrentAdapter().getSelected(); List entries = new ArrayList<>(); - for(DownloadFile downloadFile: selected) { - if(downloadFile.getSong() != null) { + for (DownloadFile downloadFile : selected) { + if (downloadFile.getSong() != null) { entries.add(downloadFile.getSong()); } } diff --git a/app/src/main/java/net/nullsum/audinaut/fragments/PreferenceCompatFragment.java b/app/src/main/java/net/nullsum/audinaut/fragments/PreferenceCompatFragment.java index 46ac06c..2343c74 100644 --- a/app/src/main/java/net/nullsum/audinaut/fragments/PreferenceCompatFragment.java +++ b/app/src/main/java/net/nullsum/audinaut/fragments/PreferenceCompatFragment.java @@ -26,32 +26,33 @@ import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.preference.Preference; -import android.preference.PreferenceFragment; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ListView; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; - import net.nullsum.audinaut.R; import net.nullsum.audinaut.util.Constants; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + public abstract class PreferenceCompatFragment extends SubsonicFragment { - private static final String TAG = PreferenceCompatFragment.class.getSimpleName(); private static final int FIRST_REQUEST_CODE = 100; private static final int MSG_BIND_PREFERENCES = 1; private static final String PREFERENCES_TAG = "android:preferences"; private boolean mHavePrefs; private boolean mInitDone; private ListView mList; + final private Runnable mRequestFocus = new Runnable() { + public void run() { + mList.focusableViewAvailable(mList); + } + }; private PreferenceManager mPreferenceManager; - - private Handler mHandler = new Handler() { + private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { @@ -63,12 +64,6 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment { } }; - final private Runnable mRequestFocus = new Runnable() { - public void run() { - mList.focusableViewAvailable(mList); - } - }; - private void bindPreferences() { PreferenceScreen localPreferenceScreen = getPreferenceScreen(); if (localPreferenceScreen != null) { @@ -89,7 +84,7 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment { throw new RuntimeException("Content has view with id attribute 'android.R.id.list' that is not a ListView class"); } - mList = (ListView)listView; + mList = (ListView) listView; if (mList == null) { throw new RuntimeException("Your content must have a ListView whose id attribute is 'android.R.id.list'"); } @@ -110,26 +105,17 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment { } } - public void addPreferencesFromIntent(Intent intent) { - requirePreferenceManager(); - PreferenceScreen screen = inflateFromIntent(intent, getPreferenceScreen()); - setPreferenceScreen(screen); - } - - public PreferenceScreen addPreferencesFromResource(int resId) { + private PreferenceScreen addPreferencesFromResource(int resId) { requirePreferenceManager(); PreferenceScreen screen = inflateFromResource(getActivity(), resId, getPreferenceScreen()); setPreferenceScreen(screen); - for(int i = 0; i < screen.getPreferenceCount(); i++) { + for (int i = 0; i < screen.getPreferenceCount(); i++) { Preference preference = screen.getPreference(i); - if(preference instanceof PreferenceScreen && preference.getKey() != null) { - preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - onStartNewFragment(preference.getKey()); - return false; - } + if (preference instanceof PreferenceScreen && preference.getKey() != null) { + preference.setOnPreferenceClickListener(preference1 -> { + onStartNewFragment(preference1.getKey()); + return false; }); } } @@ -137,19 +123,19 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment { return screen; } - public Preference findPreference(CharSequence key) { + Preference findPreference(CharSequence key) { if (mPreferenceManager == null) { return null; } return mPreferenceManager.findPreference(key); } - public ListView getListView() { + private ListView getListView() { ensureList(); return mList; } - public PreferenceManager getPreferenceManager() { + PreferenceManager getPreferenceManager() { return mPreferenceManager; } @@ -184,7 +170,7 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment { mPreferenceManager = createPreferenceManager(); int res = this.getArguments().getInt(Constants.INTENT_EXTRA_FRAGMENT_TYPE, 0); - if(res != 0) { + if (res != 0) { PreferenceScreen preferenceScreen = addPreferencesFromResource(res); onInitPreferences(preferenceScreen); } @@ -226,7 +212,9 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment { dispatchActivityStop(); } - /** Access methods with visibility private **/ + /** + * Access methods with visibility private + **/ private PreferenceManager createPreferenceManager() { try { @@ -248,7 +236,7 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment { } } - protected void setPreferenceScreen(PreferenceScreen preferenceScreen) { + void setPreferenceScreen(PreferenceScreen preferenceScreen) { try { Method m = PreferenceManager.class.getDeclaredMethod("setPreferences", PreferenceScreen.class); m.setAccessible(true); @@ -294,19 +282,8 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment { } } - - private void setFragment(PreferenceFragment preferenceFragment) { - try { - Method m = PreferenceManager.class.getDeclaredMethod("setFragment", PreferenceFragment.class); - m.setAccessible(true); - m.invoke(mPreferenceManager, preferenceFragment); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public PreferenceScreen inflateFromResource(Context context, int resId, PreferenceScreen rootPreferences) { - PreferenceScreen preferenceScreen ; + private PreferenceScreen inflateFromResource(Context context, int resId, PreferenceScreen rootPreferences) { + PreferenceScreen preferenceScreen; try { Method m = PreferenceManager.class.getDeclaredMethod("inflateFromResource", Context.class, int.class, PreferenceScreen.class); m.setAccessible(true); @@ -317,18 +294,7 @@ public abstract class PreferenceCompatFragment extends SubsonicFragment { return preferenceScreen; } - public PreferenceScreen inflateFromIntent(Intent queryIntent, PreferenceScreen rootPreferences) { - PreferenceScreen preferenceScreen ; - try { - Method m = PreferenceManager.class.getDeclaredMethod("inflateFromIntent", Intent.class, PreferenceScreen.class); - m.setAccessible(true); - preferenceScreen = (PreferenceScreen) m.invoke(mPreferenceManager, queryIntent, rootPreferences); - } catch (Exception e) { - throw new RuntimeException(e); - } - return preferenceScreen; - } - protected abstract void onInitPreferences(PreferenceScreen preferenceScreen); + protected abstract void onStartNewFragment(String name); } diff --git a/app/src/main/java/net/nullsum/audinaut/fragments/SearchFragment.java b/app/src/main/java/net/nullsum/audinaut/fragments/SearchFragment.java index d950206..d0d0969 100644 --- a/app/src/main/java/net/nullsum/audinaut/fragments/SearchFragment.java +++ b/app/src/main/java/net/nullsum/audinaut/fragments/SearchFragment.java @@ -1,24 +1,16 @@ package net.nullsum.audinaut.fragments; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import android.content.Intent; import android.os.Bundle; import android.support.v4.view.MenuItemCompat; -import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; -import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; -import android.view.View; import android.view.MenuItem; -import android.net.Uri; +import android.view.View; import android.view.ViewGroup; + import net.nullsum.audinaut.R; import net.nullsum.audinaut.adapter.ArtistAdapter; import net.nullsum.audinaut.adapter.EntryGridAdapter; @@ -28,26 +20,30 @@ import net.nullsum.audinaut.domain.Artist; import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.domain.SearchCritera; import net.nullsum.audinaut.domain.SearchResult; +import net.nullsum.audinaut.service.DownloadService; import net.nullsum.audinaut.service.MusicService; import net.nullsum.audinaut.service.MusicServiceFactory; -import net.nullsum.audinaut.service.DownloadService; import net.nullsum.audinaut.util.BackgroundTask; import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.TabBackgroundTask; import net.nullsum.audinaut.util.Util; import net.nullsum.audinaut.view.UpdateView; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + public class SearchFragment extends SubsonicFragment implements SectionAdapter.OnItemClickedListener { - private static final String TAG = SearchFragment.class.getSimpleName(); private static final int MAX_ARTISTS = 20; private static final int MAX_ALBUMS = 20; private static final int MAX_SONGS = 50; private static final int MIN_CLOSENESS = 1; - protected RecyclerView recyclerView; - protected SearchAdapter adapter; - protected boolean largeAlbums = false; + private RecyclerView recyclerView; + private SearchAdapter adapter; + private boolean largeAlbums = false; private SearchResult searchResult; private boolean skipSearch = false; @@ -62,7 +58,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - if(savedInstanceState != null) { + if (savedInstanceState != null) { searchResult = (SearchResult) savedInstanceState.getSerializable(Constants.FRAGMENT_LIST); } largeAlbums = Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_LARGE_ALBUM_ART, true); @@ -79,16 +75,16 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O rootView = inflater.inflate(R.layout.abstract_recycler_fragment, container, false); setTitle(R.string.search_title); - refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout); + refreshLayout = rootView.findViewById(R.id.refresh_layout); refreshLayout.setEnabled(false); - recyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_recycler); + recyclerView = rootView.findViewById(R.id.fragment_recycler); setupLayoutManager(recyclerView, largeAlbums); registerForContextMenu(recyclerView); context.onNewIntent(context.getIntent()); - if(searchResult != null) { + if (searchResult != null) { skipSearch = true; recyclerView.setAdapter(adapter = new SearchAdapter(context, searchResult, getImageLoader(), largeAlbums, this)); } @@ -100,9 +96,9 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O public void setIsOnlyVisible(boolean isOnlyVisible) { boolean update = this.isOnlyVisible != isOnlyVisible; super.setIsOnlyVisible(isOnlyVisible); - if(update && adapter != null) { + if (update && adapter != null) { RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); - if(layoutManager instanceof GridLayoutManager) { + if (layoutManager instanceof GridLayoutManager) { ((GridLayoutManager) layoutManager).setSpanCount(getRecyclerColumnCount()); } } @@ -114,7 +110,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O @Override public int getSpanSize(int position) { int viewType = adapter.getItemViewType(position); - if(viewType == EntryGridAdapter.VIEW_TYPE_SONG || viewType == EntryGridAdapter.VIEW_TYPE_HEADER || viewType == ArtistAdapter.VIEW_TYPE_ARTIST) { + if (viewType == EntryGridAdapter.VIEW_TYPE_SONG || viewType == EntryGridAdapter.VIEW_TYPE_HEADER || viewType == ArtistAdapter.VIEW_TYPE_ARTIST) { return gridLayoutManager.getSpanCount(); } else { return 1; @@ -132,7 +128,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O @Override public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView updateView, Serializable item) { onCreateContextMenuSupport(menu, menuInflater, updateView, item); - if(item instanceof MusicDirectory.Entry && !Util.isOffline(context)) { + if (item instanceof MusicDirectory.Entry && !Util.isOffline(context)) { menu.removeItem(R.id.song_menu_remove_playlist); } recreateContextMenu(menu); @@ -157,7 +153,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O if (entry.isDirectory()) { onAlbumSelected(entry, false); } else { - onSongSelected(entry, false, true, true, false); + onSongSelected(entry, true); } } } @@ -166,8 +162,8 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O protected List getSelectedEntries() { List selected = adapter.getSelected(); List selectedMedia = new ArrayList<>(); - for(Serializable ser: selected) { - if(ser instanceof MusicDirectory.Entry) { + for (Serializable ser : selected) { + if (ser instanceof MusicDirectory.Entry) { selectedMedia.add((MusicDirectory.Entry) ser); } } @@ -181,7 +177,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O } public void search(final String query, final boolean autoplay) { - if(skipSearch) { + if (skipSearch) { skipSearch = false; return; } @@ -207,7 +203,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O }; task.execute(); - if(searchItem != null) { + if (searchItem != null) { MenuItemCompat.collapseActionView(searchItem); } } @@ -221,7 +217,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O Bundle args = new Bundle(); args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId()); args.putString(Constants.INTENT_EXTRA_NAME_NAME, artist.getName()); - if(autoplay) { + if (autoplay) { args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true); } args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true); @@ -235,7 +231,7 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O Bundle args = new Bundle(); args.putString(Constants.INTENT_EXTRA_NAME_ID, album.getId()); args.putString(Constants.INTENT_EXTRA_NAME_NAME, album.getTitle()); - if(autoplay) { + if (autoplay) { args.putBoolean(Constants.INTENT_EXTRA_NAME_AUTOPLAY, true); } fragment.setArguments(args); @@ -243,16 +239,14 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O replaceFragment(fragment); } - private void onSongSelected(MusicDirectory.Entry song, boolean save, boolean append, boolean autoplay, boolean playNext) { + private void onSongSelected(MusicDirectory.Entry song, boolean append) { DownloadService downloadService = getDownloadService(); if (downloadService != null) { if (!append) { downloadService.clear(); } - downloadService.download(Arrays.asList(song), save, false, playNext, false); - if (autoplay) { - downloadService.play(downloadService.size() - 1); - } + downloadService.download(Collections.singletonList(song), false, false, false, false); + downloadService.play(downloadService.size() - 1); Util.toast(context, getResources().getQuantityString(R.plurals.select_album_n_songs_added, 1, 1)); } @@ -262,30 +256,30 @@ public class SearchFragment extends SubsonicFragment implements SectionAdapter.O query = query.toLowerCase(); Artist artist = null; - if(!searchResult.getArtists().isEmpty()) { + if (!searchResult.getArtists().isEmpty()) { artist = searchResult.getArtists().get(0); artist.setCloseness(Util.getStringDistance(artist.getName().toLowerCase(), query)); } MusicDirectory.Entry album = null; - if(!searchResult.getAlbums().isEmpty()) { + if (!searchResult.getAlbums().isEmpty()) { album = searchResult.getAlbums().get(0); album.setCloseness(Util.getStringDistance(album.getTitle().toLowerCase(), query)); } MusicDirectory.Entry song = null; - if(!searchResult.getSongs().isEmpty()) { + if (!searchResult.getSongs().isEmpty()) { song = searchResult.getSongs().get(0); song.setCloseness(Util.getStringDistance(song.getTitle().toLowerCase(), query)); } - if(artist != null && (artist.getCloseness() <= MIN_CLOSENESS || + if (artist != null && (artist.getCloseness() <= MIN_CLOSENESS || (album == null || artist.getCloseness() <= album.getCloseness()) && - (song == null || artist.getCloseness() <= song.getCloseness()))) { + (song == null || artist.getCloseness() <= song.getCloseness()))) { onArtistSelected(artist, true); - } else if(album != null && (album.getCloseness() <= MIN_CLOSENESS || - song == null || album.getCloseness() <= song.getCloseness())) { + } else if (album != null && (album.getCloseness() <= MIN_CLOSENESS || + song == null || album.getCloseness() <= song.getCloseness())) { onAlbumSelected(album, true); - } else if(song != null) { - onSongSelected(song, false, false, true, false); + } else if (song != null) { + onSongSelected(song, false); } } } diff --git a/app/src/main/java/net/nullsum/audinaut/fragments/SelectArtistFragment.java b/app/src/main/java/net/nullsum/audinaut/fragments/SelectArtistFragment.java index a397995..9c5e845 100644 --- a/app/src/main/java/net/nullsum/audinaut/fragments/SelectArtistFragment.java +++ b/app/src/main/java/net/nullsum/audinaut/fragments/SelectArtistFragment.java @@ -1,6 +1,5 @@ package net.nullsum.audinaut.fragments; -import android.os.Build; import android.os.Bundle; import android.view.LayoutInflater; import android.view.Menu; @@ -29,7 +28,6 @@ import java.util.ArrayList; import java.util.List; public class SelectArtistFragment extends SelectRecyclerFragment implements ArtistAdapter.OnMusicFolderChanged { - private static final String TAG = SelectArtistFragment.class.getSimpleName(); private List musicFolders = null; private List entries; @@ -44,7 +42,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment i public void onCreate(Bundle bundle) { super.onCreate(bundle); - if(bundle != null) { + if (bundle != null) { musicFolders = (List) bundle.getSerializable(Constants.FRAGMENT_LIST2); } artist = true; @@ -59,8 +57,8 @@ public class SelectArtistFragment extends SelectRecyclerFragment i @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { Bundle args = getArguments(); - if(args != null) { - if(args.getBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, false)) { + if (args != null) { + if (args.getBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, false)) { groupId = args.getString(Constants.INTENT_EXTRA_NAME_ID); groupName = args.getString(Constants.INTENT_EXTRA_NAME_NAME); @@ -90,10 +88,10 @@ public class SelectArtistFragment extends SelectRecyclerFragment i @Override public void onItemClicked(UpdateView updateView, Serializable item) { SubsonicFragment fragment; - if(item instanceof Artist) { + if (item instanceof Artist) { Artist artist = (Artist) item; - if ((Util.isFirstLevelArtist(context) || Util.isOffline(context) || Util.isTagBrowsing(context)) || groupId != null) { + if ((Util.isFirstLevelArtist(context) || Util.isOffline(context)) || groupId != null) { fragment = new SelectDirectoryFragment(); Bundle args = new Bundle(); args.putString(Constants.INTENT_EXTRA_NAME_ID, artist.getId()); @@ -129,7 +127,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment i public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) { super.onCreateOptionsMenu(menu, menuInflater); - if(Util.isOffline(context) || Util.isTagBrowsing(context) || groupId != null) { + if (Util.isOffline(context) || groupId != null) { menu.removeItem(R.id.menu_first_level_artist); } else { if (Util.isFirstLevelArtist(context)) { @@ -145,7 +143,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment i @Override public boolean onOptionsItemSelected(MenuItem item) { - if(super.onOptionsItemSelected(item)) { + if (super.onOptionsItemSelected(item)) { return true; } @@ -166,18 +164,8 @@ public class SelectArtistFragment extends SelectRecyclerFragment i @Override public List getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception { List items; - if(groupId == null) { - if (!Util.isOffline(context) && !Util.isTagBrowsing(context)) { - musicFolders = musicService.getMusicFolders(refresh, context, listener); - - // Hide folders option if there is only one - if (musicFolders.size() == 1) { - musicFolders = null; - Util.setSelectedMusicFolderId(context, null); - } - } else { - musicFolders = null; - } + if (groupId == null) { + musicFolders = null; String musicFolderId = Util.getSelectedMusicFolderId(context); Indexes indexes = musicService.getIndexes(musicFolderId, refresh, context, listener); @@ -191,7 +179,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment i List artists = new ArrayList<>(); items = new ArrayList<>(); MusicDirectory dir = musicService.getMusicDirectory(groupId, groupName, refresh, context, listener); - for(Entry entry: dir.getChildren(true, false)) { + for (Entry entry : dir.getChildren(true, false)) { Artist artist = new Artist(); artist.setId(entry.getId()); artist.setName(entry.getTitle()); @@ -204,9 +192,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment i items.addAll(indexes.getArtists()); entries = dir.getChildren(false, true); - for(Entry entry: entries) { - items.add(entry); - } + items.addAll(entries); } return items; @@ -221,7 +207,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment i public void setEmpty(boolean empty) { super.setEmpty(empty); - if(empty && !Util.isOffline(context)) { + if (empty && !Util.isOffline(context)) { objects.clear(); recyclerView.setAdapter(new ArtistAdapter(context, objects, musicFolders, this, this)); recyclerView.setVisibility(View.VISIBLE); @@ -244,7 +230,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment i String startMusicFolderId = Util.getSelectedMusicFolderId(context); String musicFolderId = selectedFolder == null ? null : selectedFolder.getId(); - if(!Util.equals(startMusicFolderId, musicFolderId)) { + if (!Util.equals(startMusicFolderId, musicFolderId)) { Util.setSelectedMusicFolderId(context, musicFolderId); context.invalidate(); } diff --git a/app/src/main/java/net/nullsum/audinaut/fragments/SelectDirectoryFragment.java b/app/src/main/java/net/nullsum/audinaut/fragments/SelectDirectoryFragment.java index 4f60608..41176c6 100644 --- a/app/src/main/java/net/nullsum/audinaut/fragments/SelectDirectoryFragment.java +++ b/app/src/main/java/net/nullsum/audinaut/fragments/SelectDirectoryFragment.java @@ -1,74 +1,57 @@ package net.nullsum.audinaut.fragments; -import android.support.v7.app.AlertDialog; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.SharedPreferences; -import android.net.Uri; -import android.os.Build; import android.os.Bundle; -import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; -import android.text.Html; -import android.text.SpannableString; -import android.text.Spanned; -import android.text.method.LinkMovementMethod; -import android.util.Log; -import android.view.Display; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.widget.ImageButton; -import android.widget.ImageView; -import android.widget.RelativeLayout; -import android.widget.TextView; + import net.nullsum.audinaut.R; import net.nullsum.audinaut.adapter.AlphabeticalAlbumAdapter; -import net.nullsum.audinaut.adapter.EntryInfiniteGridAdapter; import net.nullsum.audinaut.adapter.EntryGridAdapter; +import net.nullsum.audinaut.adapter.EntryInfiniteGridAdapter; import net.nullsum.audinaut.adapter.SectionAdapter; import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.service.CachedMusicService; -import net.nullsum.audinaut.service.DownloadService; -import net.nullsum.audinaut.util.DrawableTint; -import net.nullsum.audinaut.util.ImageLoader; - -import java.io.Serializable; -import java.util.Iterator; -import java.util.List; - import net.nullsum.audinaut.service.MusicService; import net.nullsum.audinaut.service.MusicServiceFactory; import net.nullsum.audinaut.service.OfflineException; import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.LoadingTask; import net.nullsum.audinaut.util.Pair; -import net.nullsum.audinaut.util.SilentBackgroundTask; import net.nullsum.audinaut.util.TabBackgroundTask; -import net.nullsum.audinaut.util.UpdateHelper; -import net.nullsum.audinaut.util.UserUtil; import net.nullsum.audinaut.util.Util; import net.nullsum.audinaut.view.FastScroller; -import net.nullsum.audinaut.view.GridSpacingDecoration; -import net.nullsum.audinaut.view.MyLeadingMarginSpan2; -import net.nullsum.audinaut.view.RecyclingImageView; import net.nullsum.audinaut.view.UpdateView; +import java.io.Serializable; import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; +import java.util.Collections; +import java.util.List; import static net.nullsum.audinaut.domain.MusicDirectory.Entry; public class SelectDirectoryFragment extends SubsonicFragment implements SectionAdapter.OnItemClickedListener { - private static final String TAG = SelectDirectoryFragment.class.getSimpleName(); - + private String id; + private String name; + private Entry directory; + private String playlistId; + private String playlistName; + private boolean playlistOwner; + private String albumListType; + private String albumListExtra; + private int albumListSize; + private boolean refreshListing = false; + private boolean restoredInstance = false; + private boolean lookupParent = false; + private boolean largeAlbums = false; + private boolean topTracks = false; + private String lookupEntry; private RecyclerView recyclerView; private FastScroller fastScroller; private EntryGridAdapter entryGridAdapter; @@ -76,27 +59,6 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section private List entries; private LoadTask currentTask; - private SilentBackgroundTask updateCoverArtTask; - private ImageView coverArtView; - private Entry coverArtRep; - private String coverArtId; - - String id; - String name; - Entry directory; - String playlistId; - String playlistName; - boolean playlistOwner; - String albumListType; - String albumListExtra; - int albumListSize; - boolean refreshListing = false; - boolean restoredInstance = false; - boolean lookupParent = false; - boolean largeAlbums = false; - boolean topTracks = false; - String lookupEntry; - public SelectDirectoryFragment() { super(); } @@ -104,10 +66,10 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section @Override public void onCreate(Bundle bundle) { super.onCreate(bundle); - if(bundle != null) { + if (bundle != null) { entries = (List) bundle.getSerializable(Constants.FRAGMENT_LIST); albums = (List) bundle.getSerializable(Constants.FRAGMENT_LIST2); - if(albums == null) { + if (albums == null) { albums = new ArrayList<>(); } restoredInstance = true; @@ -124,14 +86,13 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { Bundle args = getArguments(); - if(args != null) { + if (args != null) { id = args.getString(Constants.INTENT_EXTRA_NAME_ID); name = args.getString(Constants.INTENT_EXTRA_NAME_NAME); directory = (Entry) args.getSerializable(Constants.INTENT_EXTRA_NAME_DIRECTORY); playlistId = args.getString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID); playlistName = args.getString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME); playlistOwner = args.getBoolean(Constants.INTENT_EXTRA_NAME_PLAYLIST_OWNER, false); - Object shareObj = args.getSerializable(Constants.INTENT_EXTRA_NAME_SHARE); albumListType = args.getString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_TYPE); albumListExtra = args.getString(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_EXTRA); albumListSize = args.getInt(Constants.INTENT_EXTRA_NAME_ALBUM_LIST_SIZE, 0); @@ -141,37 +102,37 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section topTracks = args.getBoolean(Constants.INTENT_EXTRA_TOP_TRACKS); String childId = args.getString(Constants.INTENT_EXTRA_NAME_CHILD_ID); - if(childId != null) { + if (childId != null) { id = childId; lookupParent = true; } - if(entries == null) { + if (entries == null) { entries = (List) args.getSerializable(Constants.FRAGMENT_LIST); albums = (List) args.getSerializable(Constants.FRAGMENT_LIST2); - if(albums == null) { - albums = new ArrayList(); + if (albums == null) { + albums = new ArrayList<>(); } } } rootView = inflater.inflate(R.layout.abstract_recycler_fragment, container, false); - refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout); + refreshLayout = rootView.findViewById(R.id.refresh_layout); refreshLayout.setOnRefreshListener(this); - if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_LARGE_ALBUM_ART, true)) { + if (Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_LARGE_ALBUM_ART, true)) { largeAlbums = true; } - recyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_recycler); + recyclerView = rootView.findViewById(R.id.fragment_recycler); recyclerView.setHasFixedSize(true); - fastScroller = (FastScroller) rootView.findViewById(R.id.fragment_fast_scroller); + fastScroller = rootView.findViewById(R.id.fragment_fast_scroller); setupScrollList(recyclerView); setupLayoutManager(recyclerView, largeAlbums); - if(entries == null) { - if(primaryFragment || secondaryFragment) { + if (entries == null) { + if (primaryFragment || secondaryFragment) { load(false); } else { invalidated = true; @@ -180,7 +141,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section finishLoading(); } - if(name != null) { + if (name != null) { setTitle(name); } @@ -191,9 +152,9 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section public void setIsOnlyVisible(boolean isOnlyVisible) { boolean update = this.isOnlyVisible != isOnlyVisible; super.setIsOnlyVisible(isOnlyVisible); - if(update && entryGridAdapter != null) { + if (update && entryGridAdapter != null) { RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); - if(layoutManager instanceof GridLayoutManager) { + if (layoutManager instanceof GridLayoutManager) { ((GridLayoutManager) layoutManager).setSpanCount(getRecyclerColumnCount()); } } @@ -201,18 +162,17 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section @Override public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) { - if(albumListType != null) { + if (albumListType != null) { menuInflater.inflate(R.menu.select_album_list, menu); - } else if(artist) { + } else if (artist) { menuInflater.inflate(R.menu.select_album, menu); } else { - if(Util.isOffline(context)) { + if (Util.isOffline(context)) { menuInflater.inflate(R.menu.select_song_offline, menu); - } - else { + } else { menuInflater.inflate(R.menu.select_song, menu); - if(playlistId == null || !playlistOwner) { + if (playlistId == null || !playlistOwner) { menu.removeItem(R.id.menu_remove_playlist); } } @@ -234,21 +194,22 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section @Override public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView updateView, Entry entry) { onCreateContextMenuSupport(menu, menuInflater, updateView, entry); - if(!Util.isOffline(context) && (playlistId == null || !playlistOwner)) { + if (!Util.isOffline(context) && (playlistId == null || !playlistOwner)) { menu.removeItem(R.id.song_menu_remove_playlist); } recreateContextMenu(menu); } + @Override public boolean onContextItemSelected(MenuItem menuItem, UpdateView updateView, Entry entry) { - if(onContextItemSelected(menuItem, entry)) { + if (onContextItemSelected(menuItem, entry)) { return true; } switch (menuItem.getItemId()) { case R.id.song_menu_remove_playlist: - removeFromPlaylist(playlistId, playlistName, Arrays.asList(entries.indexOf(entry))); + removeFromPlaylist(playlistId, playlistName, Collections.singletonList(entries.indexOf(entry))); break; } @@ -266,12 +227,12 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section if ("newest".equals(albumListType)) { args.putBoolean(Constants.INTENT_EXTRA_REFRESH_LISTINGS, true); } - if(!entry.isAlbum()) { + if (!entry.isAlbum()) { args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true); } fragment.setArguments(args); - replaceFragment(fragment, true); + replaceFragment(fragment); } else { onSongPress(entries, entry, albumListType == null); } @@ -288,11 +249,11 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section } private void load(boolean refresh) { - if(refreshListing) { + if (refreshListing) { refresh = true; } - if(currentTask != null) { + if (currentTask != null) { currentTask.cancel(); } @@ -309,21 +270,21 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section private void getMusicDirectory(final String id, final String name, final boolean refresh) { setTitle(name); - new LoadTask(refresh) { + new LoadTask() { @Override protected MusicDirectory load(MusicService service) throws Exception { MusicDirectory dir = getMusicDirectory(id, name, refresh, service, this); - if(lookupParent && dir.getParent() != null) { + if (lookupParent && dir.getParent() != null) { dir = getMusicDirectory(dir.getParent(), name, refresh, service, this); // Update the fragment pointers so other stuff works correctly SelectDirectoryFragment.this.id = dir.getId(); SelectDirectoryFragment.this.name = dir.getName(); - } else if(id != null && directory == null && dir.getParent() != null && !artist) { + } else if (id != null && directory == null && dir.getParent() != null && !artist) { MusicDirectory parentDir = getMusicDirectory(dir.getParent(), name, refresh, true, service, this); - for(Entry child: parentDir.getChildren()) { - if(id.equals(child.getId())) { + for (Entry child : parentDir.getChildren()) { + if (id.equals(child.getId())) { directory = child; break; } @@ -342,47 +303,10 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section }.execute(); } - private void getRecursiveMusicDirectory(final String id, final String name, final boolean refresh) { - setTitle(name); - - new LoadTask(refresh) { - @Override - protected MusicDirectory load(MusicService service) throws Exception { - MusicDirectory root = getMusicDirectory(id, name, refresh, service, this); - List songs = new ArrayList(); - getSongsRecursively(root, songs); - root.replaceChildren(songs); - return root; - } - - private void getSongsRecursively(MusicDirectory parent, List songs) throws Exception { - songs.addAll(parent.getChildren(false, true)); - for (Entry dir : parent.getChildren(true, false)) { - MusicService musicService = MusicServiceFactory.getMusicService(context); - - MusicDirectory musicDirectory; - if(Util.isTagBrowsing(context) && !Util.isOffline(context)) { - musicDirectory = musicService.getAlbum(dir.getId(), dir.getTitle(), false, context, this); - } else { - musicDirectory = musicService.getMusicDirectory(dir.getId(), dir.getTitle(), false, context, this); - } - getSongsRecursively(musicDirectory, songs); - } - } - - @Override - protected void done(Pair result) { - SelectDirectoryFragment.this.name = result.getFirst().getName(); - setTitle(SelectDirectoryFragment.this.name); - super.done(result); - } - }.execute(); - } - private void getPlaylist(final String playlistId, final String playlistName, final boolean refresh) { setTitle(playlistName); - new LoadTask(refresh) { + new LoadTask() { @Override protected MusicDirectory load(MusicService service) throws Exception { return service.getPlaylist(refresh, playlistId, playlistName, context, this); @@ -397,11 +321,12 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section setTitle(R.string.main_albums_recent); } else if ("frequent".equals(albumListType)) { setTitle(R.string.main_albums_frequent); - } else if("genres".equals(albumListType) || "years".equals(albumListType)) { + } else if ("genres".equals(albumListType) || "years".equals(albumListType)) { setTitle(albumListExtra); - } else if("alphabeticalByName".equals(albumListType)) { + } else if ("alphabeticalByName".equals(albumListType)) { setTitle(R.string.main_albums_alphabetical); - } if (MainFragment.SONGS_NEWEST.equals(albumListType)) { + } + if (MainFragment.SONGS_NEWEST.equals(albumListType)) { setTitle(R.string.main_songs_newest); } else if (MainFragment.SONGS_TOP_PLAYED.equals(albumListType)) { setTitle(R.string.main_songs_top_played); @@ -411,19 +336,19 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section setTitle(R.string.main_songs_frequent); } - new LoadTask(true) { + new LoadTask() { @Override protected MusicDirectory load(MusicService service) throws Exception { MusicDirectory result; - if("genres".equals(albumListType) || "years".equals(albumListType)) { + if ("genres".equals(albumListType) || "years".equals(albumListType)) { result = service.getAlbumList(albumListType, albumListExtra, size, 0, refresh, context, this); - if(result.getChildrenSize() == 0 && "genres".equals(albumListType)) { + if (result.getChildrenSize() == 0 && "genres".equals(albumListType)) { SelectDirectoryFragment.this.albumListType = "genres-songs"; result = service.getSongsByGenre(albumListExtra, size, 0, context, this); } - } else if("genres".equals(albumListType) || "genres-songs".equals(albumListType)) { + } else if ("genres".equals(albumListType) || "genres-songs".equals(albumListType)) { result = service.getSongsByGenre(albumListExtra, size, 0, context, this); - } else if(albumListType.indexOf(MainFragment.SONGS_LIST_PREFIX) != -1) { + } else if (albumListType.contains(MainFragment.SONGS_LIST_PREFIX)) { result = service.getSongList(albumListType, size, 0, context, this); } else { result = service.getAlbumList(albumListType, size, 0, refresh, context, this); @@ -433,58 +358,6 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section }.execute(); } - private abstract class LoadTask extends TabBackgroundTask> { - private boolean refresh; - - public LoadTask(boolean refresh) { - super(SelectDirectoryFragment.this); - this.refresh = refresh; - - currentTask = this; - } - - protected abstract MusicDirectory load(MusicService service) throws Exception; - - @Override - protected Pair doInBackground() throws Throwable { - MusicService musicService = MusicServiceFactory.getMusicService(context); - MusicDirectory dir = load(musicService); - - albums = dir.getChildren(true, false); - entries = dir.getChildren(); - - // This isn't really an artist if no albums on it! - if(albums.size() == 0) { - artist = false; - } - - return new Pair<>(dir, true); - } - - @Override - protected void done(Pair result) { - finishLoading(); - currentTask = null; - } - - @Override - public void updateCache(int changeCode) { - if(entryGridAdapter != null && changeCode == CachedMusicService.CACHE_UPDATE_LIST) { - entryGridAdapter.notifyDataSetChanged(); - } else if(changeCode == CachedMusicService.CACHE_UPDATE_METADATA) { - if(coverArtView != null && coverArtRep != null && !Util.equals(coverArtRep.getCoverArt(), coverArtId)) { - synchronized (coverArtRep) { - if (updateCoverArtTask != null && updateCoverArtTask.isRunning()) { - updateCoverArtTask.cancel(); - } - updateCoverArtTask = getImageLoader().loadImage(coverArtView, coverArtRep, false, true); - coverArtId = coverArtRep.getCoverArt(); - } - } - } - } - } - @Override public SectionAdapter getCurrentAdapter() { return entryGridAdapter; @@ -496,7 +369,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section @Override public int getSpanSize(int position) { int viewType = entryGridAdapter.getItemViewType(position); - if(viewType == EntryGridAdapter.VIEW_TYPE_SONG || viewType == EntryGridAdapter.VIEW_TYPE_HEADER || viewType == EntryInfiniteGridAdapter.VIEW_TYPE_LOADING) { + if (viewType == EntryGridAdapter.VIEW_TYPE_SONG || viewType == EntryGridAdapter.VIEW_TYPE_HEADER || viewType == EntryInfiniteGridAdapter.VIEW_TYPE_LOADING) { return gridLayoutManager.getSpanCount(); } else { return 1; @@ -507,19 +380,19 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section private void finishLoading() { boolean validData = !entries.isEmpty() || !albums.isEmpty(); - if(!validData) { + if (!validData) { setEmpty(true); } - if(validData) { + if (validData) { recyclerView.setVisibility(View.VISIBLE); } - if(albumListType == null) { + if (albumListType == null) { entryGridAdapter = new EntryGridAdapter(context, entries, getImageLoader(), largeAlbums); entryGridAdapter.setRemoveFromPlaylist(playlistId != null); } else { - if("alphabeticalByName".equals(albumListType)) { + if ("alphabeticalByName".equals(albumListType)) { entryGridAdapter = new AlphabeticalAlbumAdapter(context, entries, getImageLoader(), largeAlbums); } else { entryGridAdapter = new EntryInfiniteGridAdapter(context, entries, getImageLoader(), largeAlbums); @@ -530,10 +403,6 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section infiniteGridAdapter.setData(albumListType, albumListExtra, albumListSize); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - super.onScrollStateChanged(recyclerView, newState); - } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { @@ -542,15 +411,15 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); int totalItemCount = layoutManager.getItemCount(); int lastVisibleItem; - if(layoutManager instanceof GridLayoutManager) { + if (layoutManager instanceof GridLayoutManager) { lastVisibleItem = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition(); - } else if(layoutManager instanceof LinearLayoutManager) { + } else if (layoutManager instanceof LinearLayoutManager) { lastVisibleItem = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition(); } else { return; } - if(totalItemCount > 0 && lastVisibleItem >= totalItemCount - 2) { + if (totalItemCount > 0 && lastVisibleItem >= totalItemCount - 2) { infiniteGridAdapter.loadMore(); } } @@ -558,17 +427,17 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section } entryGridAdapter.setOnItemClickedListener(this); // Always show artist if this is not a artist we are viewing - if(!artist) { - entryGridAdapter.setShowArtist(true); + if (!artist) { + entryGridAdapter.setShowArtist(); } - if(topTracks) { - entryGridAdapter.setShowAlbum(true); + if (topTracks) { + entryGridAdapter.setShowAlbum(); } int scrollToPosition = -1; - if(lookupEntry != null) { - for(int i = 0; i < entries.size(); i++) { - if(lookupEntry.equals(entries.get(i).getTitle())) { + if (lookupEntry != null) { + for (int i = 0; i < entries.size(); i++) { + if (lookupEntry.equals(entries.get(i).getTitle())) { scrollToPosition = i; entryGridAdapter.addSelected(entries.get(i)); lookupEntry = null; @@ -581,7 +450,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section fastScroller.attachRecyclerView(recyclerView); context.supportInvalidateOptionsMenu(); - if(scrollToPosition != -1) { + if (scrollToPosition != -1) { recyclerView.scrollToPosition(scrollToPosition); } @@ -595,30 +464,31 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section @Override protected void playNow(final boolean shuffle, final boolean append, final boolean playNext) { List songs = getSelectedEntries(); - if(!songs.isEmpty()) { - download(songs, append, false, !append, playNext, shuffle); + if (!songs.isEmpty()) { + download(songs, append, !append, playNext, shuffle); entryGridAdapter.clearSelected(); } else { playAll(shuffle, append, playNext); } } + private void playAll(final boolean shuffle, final boolean append, final boolean playNext) { boolean hasSubFolders = albums != null && !albums.isEmpty(); if (hasSubFolders && id != null) { downloadRecursively(id, false, append, !append, shuffle, false, playNext); - } else if(hasSubFolders && albumListType != null) { + } else if (hasSubFolders && albumListType != null) { downloadRecursively(albums, shuffle, append, playNext); } else { - download(entries, append, false, !append, playNext, shuffle); + download(entries, append, !append, playNext, shuffle); } } private List getSelectedIndexes() { List selected = entryGridAdapter.getSelected(); - List indexes = new ArrayList(); + List indexes = new ArrayList<>(); - for(Entry entry: selected) { + for (Entry entry : selected) { indexes.add(entries.indexOf(entry)); } @@ -628,28 +498,29 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section @Override protected void downloadBackground(final boolean save) { List songs = getSelectedEntries(); - if(playlistId != null) { + if (playlistId != null) { songs = entries; } - if(songs.isEmpty()) { + if (songs.isEmpty()) { // Get both songs and albums - downloadRecursively(id, save, false, false, false, true); + downloadRecursively(id, save, false, false, false, true, false); } else { downloadBackground(save, songs); } } + @Override - protected void downloadBackground(final boolean save, final List entries) { + void downloadBackground(final boolean save, final List entries) { if (getDownloadService() == null) { return; } warnIfStorageUnavailable(); - RecursiveLoader onValid = new RecursiveLoader(context) { + new RecursiveLoader(context) { @Override protected Boolean doInBackground() throws Throwable { - getSongsRecursively(entries, true); + getSongsRecursively(entries); getDownloadService().downloadBackground(songs, save); return null; } @@ -662,16 +533,16 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section } @Override - protected void download(List entries, boolean append, boolean save, boolean autoplay, boolean playNext, boolean shuffle) { - download(entries, append, save, autoplay, playNext, shuffle, playlistName, playlistId); + void download(List entries, boolean append, boolean autoplay, boolean playNext, boolean shuffle) { + download(entries, append, autoplay, playNext, shuffle, playlistName, playlistId); } @Override protected void delete() { List songs = getSelectedEntries(); - if(songs.isEmpty()) { - for(Entry entry: entries) { - if(entry.isDirectory()) { + if (songs.isEmpty()) { + for (Entry entry : entries) { + if (entry.isDirectory()) { deleteRecursively(entry); } else { songs.add(entry); @@ -683,7 +554,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section } } - public void removeFromPlaylist(final String id, final String name, final List indexes) { + private void removeFromPlaylist(final String id, final String name, final List indexes) { new LoadingTask(context, true) { @Override protected Void doInBackground() throws Throwable { @@ -694,7 +565,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section @Override protected void done(Void result) { - for(Integer index: indexes) { + for (Integer index : indexes) { entryGridAdapter.removeAt(index); } Util.toast(context, context.getResources().getString(R.string.removed_playlist, indexes.size(), name)); @@ -714,113 +585,43 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section }.execute(); } - private void showTopTracks() { - SubsonicFragment fragment = new SelectDirectoryFragment(); - Bundle args = new Bundle(getArguments()); - args.putBoolean(Constants.INTENT_EXTRA_TOP_TRACKS, true); - fragment.setArguments(args); + private abstract class LoadTask extends TabBackgroundTask> { - replaceFragment(fragment, true); - } + public LoadTask() { + super(SelectDirectoryFragment.this); - private View createHeader() { - View header = LayoutInflater.from(context).inflate(R.layout.select_album_header, null, false); - - setupCoverArt(header); - setupTextDisplay(header); - - return header; - } - - private void setupCoverArt(View header) { - setupCoverArtImpl((RecyclingImageView) header.findViewById(R.id.select_album_art)); - } - private void setupCoverArtImpl(RecyclingImageView coverArtView) { - final ImageLoader imageLoader = getImageLoader(); - - if(entries.size() > 0) { - coverArtRep = null; - this.coverArtView = coverArtView; - for (int i = 0; (i < 3) && (coverArtRep == null || coverArtRep.getCoverArt() == null); i++) { - coverArtRep = entries.get(random.nextInt(entries.size())); - } - - coverArtView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (coverArtRep == null || coverArtRep.getCoverArt() == null) { - return; - } - - AlertDialog.Builder builder = new AlertDialog.Builder(context); - ImageView fullScreenView = new ImageView(context); - imageLoader.loadImage(fullScreenView, coverArtRep, true, true); - builder.setCancelable(true); - - AlertDialog imageDialog = builder.create(); - // Set view here with unecessary 0's to remove top/bottom border - imageDialog.setView(fullScreenView, 0, 0, 0, 0); - imageDialog.show(); - } - }); - synchronized (coverArtRep) { - coverArtId = coverArtRep.getCoverArt(); - updateCoverArtTask = imageLoader.loadImage(coverArtView, coverArtRep, false, true); - } + currentTask = this; } - coverArtView.setOnInvalidated(new RecyclingImageView.OnInvalidated() { - @Override - public void onInvalidated(RecyclingImageView imageView) { - setupCoverArtImpl(imageView); + protected abstract MusicDirectory load(MusicService service) throws Exception; + + @Override + protected Pair doInBackground() throws Throwable { + MusicService musicService = MusicServiceFactory.getMusicService(context); + MusicDirectory dir = load(musicService); + + albums = dir.getChildren(true, false); + entries = dir.getChildren(); + + // This isn't really an artist if no albums on it! + if (albums.size() == 0) { + artist = false; } - }); - } - private void setupTextDisplay(final View header) { - final TextView titleView = (TextView) header.findViewById(R.id.select_album_title); - if(playlistName != null) { - titleView.setText(playlistName); - } else if(name != null) { - titleView.setText(name); + + return new Pair<>(dir, true); } - int songCount = 0; - - Set artists = new HashSet(); - Set years = new HashSet(); - Integer totalDuration = 0; - for (Entry entry : entries) { - if (!entry.isDirectory()) { - songCount++; - if (entry.getArtist() != null) { - artists.add(entry.getArtist()); - } - if(entry.getYear() != null) { - years.add(entry.getYear()); - } - Integer duration = entry.getDuration(); - if(duration != null) { - totalDuration += duration; - } - } + @Override + protected void done(Pair result) { + finishLoading(); + currentTask = null; } - final TextView artistView = (TextView) header.findViewById(R.id.select_album_artist); - if (artists.size() == 1) { - String artistText = artists.iterator().next(); - if(years.size() == 1) { - artistText += " - " + years.iterator().next(); + @Override + public void updateCache(int changeCode) { + if (entryGridAdapter != null && changeCode == CachedMusicService.CACHE_UPDATE_LIST) { + entryGridAdapter.notifyDataSetChanged(); } - artistView.setText(artistText); - artistView.setVisibility(View.VISIBLE); - } else { - artistView.setVisibility(View.GONE); } - - TextView songCountView = (TextView) header.findViewById(R.id.select_album_song_count); - TextView songLengthView = (TextView) header.findViewById(R.id.select_album_song_length); - String s = context.getResources().getQuantityString(R.plurals.select_album_n_songs, songCount, songCount); - songCountView.setText(s.toUpperCase()); - songLengthView.setText(Util.formatDuration(totalDuration)); } } diff --git a/app/src/main/java/net/nullsum/audinaut/fragments/SelectGenreFragment.java b/app/src/main/java/net/nullsum/audinaut/fragments/SelectGenreFragment.java index 290cfc4..b1aa026 100644 --- a/app/src/main/java/net/nullsum/audinaut/fragments/SelectGenreFragment.java +++ b/app/src/main/java/net/nullsum/audinaut/fragments/SelectGenreFragment.java @@ -21,18 +21,17 @@ import android.view.MenuInflater; import android.view.MenuItem; import net.nullsum.audinaut.R; +import net.nullsum.audinaut.adapter.GenreAdapter; import net.nullsum.audinaut.adapter.SectionAdapter; import net.nullsum.audinaut.domain.Genre; import net.nullsum.audinaut.service.MusicService; import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.ProgressListener; -import net.nullsum.audinaut.adapter.GenreAdapter; import net.nullsum.audinaut.view.UpdateView; import java.util.List; public class SelectGenreFragment extends SelectRecyclerFragment { - private static final String TAG = SelectGenreFragment.class.getSimpleName(); @Override public int getOptionsMenu() { @@ -68,7 +67,8 @@ public class SelectGenreFragment extends SelectRecyclerFragment { } @Override - public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView updateView, Genre item) {} + public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView updateView, Genre item) { + } @Override public boolean onContextItemSelected(MenuItem menuItem, UpdateView updateView, Genre item) { diff --git a/app/src/main/java/net/nullsum/audinaut/fragments/SelectPlaylistFragment.java b/app/src/main/java/net/nullsum/audinaut/fragments/SelectPlaylistFragment.java index 5b0117b..cca30f6 100644 --- a/app/src/main/java/net/nullsum/audinaut/fragments/SelectPlaylistFragment.java +++ b/app/src/main/java/net/nullsum/audinaut/fragments/SelectPlaylistFragment.java @@ -1,10 +1,7 @@ package net.nullsum.audinaut.fragments; -import android.support.v7.app.AlertDialog; -import android.content.DialogInterface; -import android.content.res.Resources; import android.os.Bundle; -import android.support.v4.app.FragmentTransaction; +import android.support.v7.app.AlertDialog; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -13,30 +10,26 @@ import android.widget.CheckBox; import android.widget.EditText; import net.nullsum.audinaut.R; +import net.nullsum.audinaut.adapter.PlaylistAdapter; import net.nullsum.audinaut.adapter.SectionAdapter; -import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.domain.Playlist; -import net.nullsum.audinaut.service.DownloadFile; import net.nullsum.audinaut.service.MusicService; import net.nullsum.audinaut.service.MusicServiceFactory; import net.nullsum.audinaut.service.OfflineException; -import net.nullsum.audinaut.util.ProgressListener; -import net.nullsum.audinaut.util.SyncUtil; import net.nullsum.audinaut.util.CacheCleaner; import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.LoadingTask; +import net.nullsum.audinaut.util.ProgressListener; +import net.nullsum.audinaut.util.SyncUtil; import net.nullsum.audinaut.util.UserUtil; import net.nullsum.audinaut.util.Util; -import net.nullsum.audinaut.adapter.PlaylistAdapter; import net.nullsum.audinaut.view.UpdateView; import java.text.DateFormat; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; public class SelectPlaylistFragment extends SelectRecyclerFragment { - private static final String TAG = SelectPlaylistFragment.class.getSimpleName(); @Override public void onCreate(Bundle bundle) { @@ -50,11 +43,10 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment { public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView updateView, Playlist playlist) { if (Util.isOffline(context)) { menuInflater.inflate(R.menu.select_playlist_context_offline, menu); - } - else { + } else { menuInflater.inflate(R.menu.select_playlist_context, menu); - if(playlist.getPublic() != null && playlist.getPublic() == true && playlist.getId().indexOf(".m3u") == -1 && !UserUtil.getCurrentUsername(context).equals(playlist.getOwner())) { + if (playlist.getPublic() != null && playlist.getPublic() && !playlist.getId().contains(".m3u") && !UserUtil.getCurrentUsername(context).equals(playlist.getOwner())) { menu.removeItem(R.id.playlist_update_info); menu.removeItem(R.id.playlist_menu_delete); } @@ -67,11 +59,10 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment { public boolean onContextItemSelected(MenuItem menuItem, UpdateView updateView, Playlist playlist) { SubsonicFragment fragment; Bundle args; - FragmentTransaction trans; switch (menuItem.getItemId()) { case R.id.playlist_menu_download: - downloadPlaylist(playlist.getId(), playlist.getName(), false, true, false, false, true); + downloadPlaylist(playlist.getId(), playlist.getName()); break; case R.id.playlist_menu_play_now: fragment = new SelectDirectoryFragment(); @@ -118,8 +109,8 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment { List mine = new ArrayList<>(); String currentUsername = UserUtil.getCurrentUsername(context); - for(Playlist playlist: playlists) { - if(playlist.getOwner() == null || playlist.getOwner().equals(currentUsername)) { + for (Playlist playlist : playlists) { + if (playlist.getOwner() == null || playlist.getOwner().equals(currentUsername)) { mine.add(playlist); } } @@ -130,7 +121,7 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment { @Override public List getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception { List playlists = musicService.getPlaylists(refresh, context, listener); - if(!Util.isOffline(context) && refresh) { + if (!Util.isOffline(context) && refresh) { new CacheCleaner(context, getDownloadService()).cleanPlaylists(playlists); } return playlists; @@ -147,7 +138,7 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment { Bundle args = new Bundle(); args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_ID, playlist.getId()); args.putString(Constants.INTENT_EXTRA_NAME_PLAYLIST_NAME, playlist.getName()); - if((playlist.getOwner() != null && playlist.getOwner().equals(UserUtil.getCurrentUsername(context)) || playlist.getId().indexOf(".m3u") != -1)) { + if ((playlist.getOwner() != null && playlist.getOwner().equals(UserUtil.getCurrentUsername(context)) || playlist.getId().contains(".m3u"))) { args.putBoolean(Constants.INTENT_EXTRA_NAME_PLAYLIST_OWNER, true); } fragment.setArguments(args); @@ -158,7 +149,7 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment { @Override public void onFinishRefresh() { Bundle args = getArguments(); - if(args != null) { + if (args != null) { String playlistId = args.getString(Constants.INTENT_EXTRA_NAME_ID, null); if (playlistId != null && objects != null) { for (Playlist playlist : objects) { @@ -172,38 +163,33 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment { } private void deletePlaylist(final Playlist playlist) { - Util.confirmDialog(context, R.string.common_delete, playlist.getName(), new DialogInterface.OnClickListener() { + Util.confirmDialog(context, R.string.common_delete, playlist.getName(), (dialog, which) -> new LoadingTask(context, false) { @Override - public void onClick(DialogInterface dialog, int which) { - new LoadingTask(context, false) { - @Override - protected Void doInBackground() throws Throwable { - MusicService musicService = MusicServiceFactory.getMusicService(context); - musicService.deletePlaylist(playlist.getId(), context, null); - SyncUtil.removeSyncedPlaylist(context, playlist.getId()); - return null; - } - - @Override - protected void done(Void result) { - adapter.removeItem(playlist); - Util.toast(context, context.getResources().getString(R.string.menu_deleted_playlist, playlist.getName())); - } - - @Override - protected void error(Throwable error) { - String msg; - if (error instanceof OfflineException) { - msg = getErrorMessage(error); - } else { - msg = context.getResources().getString(R.string.menu_deleted_playlist_error, playlist.getName()) + " " + getErrorMessage(error); - } - - Util.toast(context, msg, false); - } - }.execute(); + protected Void doInBackground() throws Throwable { + MusicService musicService = MusicServiceFactory.getMusicService(context); + musicService.deletePlaylist(playlist.getId(), context, null); + SyncUtil.removeSyncedPlaylist(context, playlist.getId()); + return null; } - }); + + @Override + protected void done(Void result) { + adapter.removeItem(playlist); + Util.toast(context, context.getResources().getString(R.string.menu_deleted_playlist, playlist.getName())); + } + + @Override + protected void error(Throwable error) { + String msg; + if (error instanceof OfflineException) { + msg = getErrorMessage(error); + } else { + msg = context.getResources().getString(R.string.menu_deleted_playlist_error, playlist.getName()) + " " + getErrorMessage(error); + } + + Util.toast(context, msg, false); + } + }.execute()); } private void displayPlaylistInfo(final Playlist playlist) { @@ -213,12 +199,12 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment { headers.add(R.string.details_title); details.add(playlist.getName()); - if(playlist.getOwner() != null) { + if (playlist.getOwner() != null) { headers.add(R.string.details_owner); details.add(playlist.getOwner()); } - if(playlist.getComment() != null) { + if (playlist.getComment() != null) { headers.add(R.string.details_comments); details.add(playlist.getComment()); } @@ -226,23 +212,23 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment { headers.add(R.string.details_song_count); details.add(playlist.getSongCount()); - if(playlist.getDuration() != null) { + if (playlist.getDuration() != null) { headers.add(R.string.details_length); details.add(Util.formatDuration(playlist.getDuration())); } - if(playlist.getPublic() != null) { + if (playlist.getPublic() != null) { headers.add(R.string.details_public); details.add(Util.formatBoolean(context, playlist.getPublic())); } - if(playlist.getCreated() != null) { + if (playlist.getCreated() != null) { headers.add(R.string.details_created); DateFormat dateFormat = DateFormat.getDateInstance(); details.add(dateFormat.format(playlist.getCreated())); } - if(playlist.getChanged() != null) { + if (playlist.getChanged() != null) { headers.add(R.string.details_updated); DateFormat dateFormat = DateFormat.getDateInstance(); @@ -254,93 +240,59 @@ public class SelectPlaylistFragment extends SelectRecyclerFragment { private void updatePlaylistInfo(final Playlist playlist) { View dialogView = context.getLayoutInflater().inflate(R.layout.update_playlist, null); - final EditText nameBox = (EditText)dialogView.findViewById(R.id.get_playlist_name); - final EditText commentBox = (EditText)dialogView.findViewById(R.id.get_playlist_comment); - final CheckBox publicBox = (CheckBox)dialogView.findViewById(R.id.get_playlist_public); + final EditText nameBox = dialogView.findViewById(R.id.get_playlist_name); + final EditText commentBox = dialogView.findViewById(R.id.get_playlist_comment); + final CheckBox publicBox = dialogView.findViewById(R.id.get_playlist_public); nameBox.setText(playlist.getName()); commentBox.setText(playlist.getComment()); Boolean pub = playlist.getPublic(); - if(pub == null) { + if (pub == null) { publicBox.setEnabled(false); } else { publicBox.setChecked(pub); } new AlertDialog.Builder(context) - .setIcon(android.R.drawable.ic_dialog_alert) - .setTitle(R.string.playlist_update_info) - .setView(dialogView) - .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - new LoadingTask(context, false) { - @Override - protected Void doInBackground() throws Throwable { - String name = nameBox.getText().toString(); - String comment = commentBox.getText().toString(); - boolean isPublic = publicBox.isChecked(); + .setIcon(android.R.drawable.ic_dialog_alert) + .setTitle(R.string.playlist_update_info) + .setView(dialogView) + .setPositiveButton(R.string.common_ok, (dialog, which) -> new LoadingTask(context, false) { + @Override + protected Void doInBackground() throws Throwable { + String name = nameBox.getText().toString(); + String comment = commentBox.getText().toString(); + boolean isPublic = publicBox.isChecked(); - MusicService musicService = MusicServiceFactory.getMusicService(context); - musicService.updatePlaylist(playlist.getId(), name, comment, isPublic, context, null); + MusicService musicService = MusicServiceFactory.getMusicService(context); + musicService.updatePlaylist(playlist.getId(), name, comment, isPublic, context, null); - playlist.setName(name); - playlist.setComment(comment); - playlist.setPublic(isPublic); + playlist.setName(name); + playlist.setComment(comment); + playlist.setPublic(isPublic); - return null; + return null; + } + + @Override + protected void done(Void result) { + Util.toast(context, context.getResources().getString(R.string.playlist_updated_info, playlist.getName())); + } + + @Override + protected void error(Throwable error) { + String msg; + if (error instanceof OfflineException) { + msg = getErrorMessage(error); + } else { + msg = context.getResources().getString(R.string.playlist_updated_info_error, playlist.getName()) + " " + getErrorMessage(error); } - @Override - protected void done(Void result) { - Util.toast(context, context.getResources().getString(R.string.playlist_updated_info, playlist.getName())); - } - - @Override - protected void error(Throwable error) { - String msg; - if (error instanceof OfflineException) { - msg = getErrorMessage(error); - } else { - msg = context.getResources().getString(R.string.playlist_updated_info_error, playlist.getName()) + " " + getErrorMessage(error); - } - - Util.toast(context, msg, false); - } - }.execute(); - } - - }) - .setNegativeButton(R.string.common_cancel, null) - .show(); + Util.toast(context, msg, false); + } + }.execute()) + .setNegativeButton(R.string.common_cancel, null) + .show(); } - private void syncPlaylist(Playlist playlist) { - SyncUtil.addSyncedPlaylist(context, playlist.getId()); - downloadPlaylist(playlist.getId(), playlist.getName(), true, true, false, false, true); - } - - private void stopSyncPlaylist(final Playlist playlist) { - SyncUtil.removeSyncedPlaylist(context, playlist.getId()); - - new LoadingTask(context, false) { - @Override - protected Void doInBackground() throws Throwable { - // Unpin all of the songs in playlist - MusicService musicService = MusicServiceFactory.getMusicService(context); - MusicDirectory root = musicService.getPlaylist(true, playlist.getId(), playlist.getName(), context, this); - for(MusicDirectory.Entry entry: root.getChildren()) { - DownloadFile file = new DownloadFile(context, entry, false); - file.unpin(); - } - - return null; - } - - @Override - protected void done(Void result) { - - } - }.execute(); - } } diff --git a/app/src/main/java/net/nullsum/audinaut/fragments/SelectRecyclerFragment.java b/app/src/main/java/net/nullsum/audinaut/fragments/SelectRecyclerFragment.java index 8f1dbdb..1434d9b 100644 --- a/app/src/main/java/net/nullsum/audinaut/fragments/SelectRecyclerFragment.java +++ b/app/src/main/java/net/nullsum/audinaut/fragments/SelectRecyclerFragment.java @@ -15,27 +15,16 @@ package net.nullsum.audinaut.fragments; -import android.app.SearchManager; -import android.app.SearchableInfo; -import android.content.Context; import android.os.Bundle; -import android.support.v4.view.MenuItemCompat; -import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.SearchView; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; -import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - import net.nullsum.audinaut.R; import net.nullsum.audinaut.adapter.SectionAdapter; import net.nullsum.audinaut.service.MusicService; @@ -45,23 +34,27 @@ import net.nullsum.audinaut.util.ProgressListener; import net.nullsum.audinaut.util.TabBackgroundTask; import net.nullsum.audinaut.view.FastScroller; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + public abstract class SelectRecyclerFragment extends SubsonicFragment implements SectionAdapter.OnItemClickedListener { private static final String TAG = SelectRecyclerFragment.class.getSimpleName(); - protected RecyclerView recyclerView; - protected FastScroller fastScroller; - protected SectionAdapter adapter; - protected UpdateTask currentTask; - protected List objects; - protected boolean serialize = true; - protected boolean largeAlbums = false; - protected boolean pullToRefresh = true; - protected boolean backgroundUpdate = true; + RecyclerView recyclerView; + SectionAdapter adapter; + List objects; + boolean serialize = true; + boolean largeAlbums = false; + boolean pullToRefresh = true; + boolean backgroundUpdate = true; + private FastScroller fastScroller; + private UpdateTask currentTask; @Override public void onCreate(Bundle bundle) { super.onCreate(bundle); - if(bundle != null && serialize) { + if (bundle != null && serialize) { objects = (List) bundle.getSerializable(Constants.FRAGMENT_LIST); } } @@ -69,7 +62,7 @@ public abstract class SelectRecyclerFragment extends SubsonicFragment impleme @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - if(serialize) { + if (serialize) { outState.putSerializable(Constants.FRAGMENT_LIST, (Serializable) objects); } } @@ -78,20 +71,20 @@ public abstract class SelectRecyclerFragment extends SubsonicFragment impleme public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { rootView = inflater.inflate(R.layout.abstract_recycler_fragment, container, false); - refreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.refresh_layout); + refreshLayout = rootView.findViewById(R.id.refresh_layout); refreshLayout.setOnRefreshListener(this); - recyclerView = (RecyclerView) rootView.findViewById(R.id.fragment_recycler); - fastScroller = (FastScroller) rootView.findViewById(R.id.fragment_fast_scroller); + recyclerView = rootView.findViewById(R.id.fragment_recycler); + fastScroller = rootView.findViewById(R.id.fragment_fast_scroller); setupLayoutManager(); - if(pullToRefresh) { + if (pullToRefresh) { setupScrollList(recyclerView); } else { refreshLayout.setEnabled(false); } - if(objects == null) { + if (objects == null) { refresh(false); } else { recyclerView.setAdapter(adapter = getAdapter(objects)); @@ -102,7 +95,7 @@ public abstract class SelectRecyclerFragment extends SubsonicFragment impleme @Override public void onCreateOptionsMenu(Menu menu, MenuInflater menuInflater) { - if(!primaryFragment) { + if (!primaryFragment) { return; } @@ -110,44 +103,39 @@ public abstract class SelectRecyclerFragment extends SubsonicFragment impleme onFinishSetupOptionsMenu(menu); } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - return super.onOptionsItemSelected(item); - } - @Override public void setIsOnlyVisible(boolean isOnlyVisible) { boolean update = this.isOnlyVisible != isOnlyVisible; super.setIsOnlyVisible(isOnlyVisible); - if(update && adapter != null) { + if (update && adapter != null) { RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); - if(layoutManager instanceof GridLayoutManager) { + if (layoutManager instanceof GridLayoutManager) { ((GridLayoutManager) layoutManager).setSpanCount(getRecyclerColumnCount()); } } } @Override - protected void refresh(final boolean refresh) { + void refresh(final boolean refresh) { int titleRes = getTitleResource(); - if(titleRes != 0) { + if (titleRes != 0) { setTitle(getTitleResource()); } - if(backgroundUpdate) { + if (backgroundUpdate) { recyclerView.setVisibility(View.GONE); } // Cancel current running task before starting another one - if(currentTask != null) { + if (currentTask != null) { currentTask.cancel(); } currentTask = new UpdateTask(this, refresh); - if(backgroundUpdate) { + if (backgroundUpdate) { currentTask.execute(); } else { - objects = new ArrayList(); + objects = new ArrayList<>(); try { objects = getObjects(null, refresh, null); @@ -167,17 +155,20 @@ public abstract class SelectRecyclerFragment extends SubsonicFragment impleme setupLayoutManager(recyclerView, largeAlbums); } - public abstract int getOptionsMenu(); - public abstract SectionAdapter getAdapter(List objs); - public abstract List getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception; - public abstract int getTitleResource(); + protected abstract int getOptionsMenu(); - public void onFinishRefresh() { + protected abstract SectionAdapter getAdapter(List objs); + + protected abstract List getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception; + + protected abstract int getTitleResource(); + + void onFinishRefresh() { } private class UpdateTask extends TabBackgroundTask> { - private boolean refresh; + private final boolean refresh; public UpdateTask(SubsonicFragment fragment, boolean refresh) { super(fragment); @@ -188,7 +179,7 @@ public abstract class SelectRecyclerFragment extends SubsonicFragment impleme public List doInBackground() throws Exception { MusicService musicService = MusicServiceFactory.getMusicService(context); - objects = new ArrayList(); + objects = new ArrayList<>(); try { objects = getObjects(musicService, refresh, this); @@ -203,7 +194,7 @@ public abstract class SelectRecyclerFragment extends SubsonicFragment impleme public void done(List result) { if (result != null && !result.isEmpty()) { recyclerView.setAdapter(adapter = getAdapter(result)); - if(!fastScroller.isAttached()) { + if (!fastScroller.isAttached()) { fastScroller.attachRecyclerView(recyclerView); } diff --git a/app/src/main/java/net/nullsum/audinaut/fragments/SelectYearFragment.java b/app/src/main/java/net/nullsum/audinaut/fragments/SelectYearFragment.java index 57e023c..e1b9b25 100644 --- a/app/src/main/java/net/nullsum/audinaut/fragments/SelectYearFragment.java +++ b/app/src/main/java/net/nullsum/audinaut/fragments/SelectYearFragment.java @@ -20,9 +20,6 @@ import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; -import java.util.ArrayList; -import java.util.List; - import net.nullsum.audinaut.R; import net.nullsum.audinaut.adapter.BasicListAdapter; import net.nullsum.audinaut.adapter.SectionAdapter; @@ -31,6 +28,9 @@ import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.ProgressListener; import net.nullsum.audinaut.view.UpdateView; +import java.util.ArrayList; +import java.util.List; + public class SelectYearFragment extends SelectRecyclerFragment { public SelectYearFragment() { @@ -53,7 +53,7 @@ public class SelectYearFragment extends SelectRecyclerFragment { @Override public List getObjects(MusicService musicService, boolean refresh, ProgressListener listener) throws Exception { List decades = new ArrayList<>(); - for(int i = 2010; i >= 1800; i -= 10) { + for (int i = 2010; i >= 1800; i -= 10) { decades.add(String.valueOf(i)); } @@ -79,7 +79,8 @@ public class SelectYearFragment extends SelectRecyclerFragment { } @Override - public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView updateView, String item) {} + public void onCreateContextMenu(Menu menu, MenuInflater menuInflater, UpdateView updateView, String item) { + } @Override public boolean onContextItemSelected(MenuItem menuItem, UpdateView updateView, String item) { diff --git a/app/src/main/java/net/nullsum/audinaut/fragments/SettingsFragment.java b/app/src/main/java/net/nullsum/audinaut/fragments/SettingsFragment.java index 9f37d22..356747f 100644 --- a/app/src/main/java/net/nullsum/audinaut/fragments/SettingsFragment.java +++ b/app/src/main/java/net/nullsum/audinaut/fragments/SettingsFragment.java @@ -16,9 +16,8 @@ package net.nullsum.audinaut.fragments; import android.accounts.Account; +import android.app.backup.BackupManager; import android.content.ContentResolver; -import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; @@ -31,21 +30,11 @@ import android.preference.PreferenceCategory; import android.preference.PreferenceScreen; import android.text.InputType; import android.util.Log; -import android.view.LayoutInflater; -import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; -import java.io.File; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.net.URL; -import java.text.DecimalFormat; -import java.util.LinkedHashMap; -import java.util.Map; - import net.nullsum.audinaut.R; import net.nullsum.audinaut.service.DownloadService; import net.nullsum.audinaut.service.HeadphoneListenerService; @@ -59,10 +48,16 @@ import net.nullsum.audinaut.util.Util; import net.nullsum.audinaut.view.CacheLocationPreference; import net.nullsum.audinaut.view.ErrorDialog; +import java.io.File; +import java.net.URL; +import java.text.DecimalFormat; +import java.util.LinkedHashMap; +import java.util.Map; + public class SettingsFragment extends PreferenceCompatFragment implements SharedPreferences.OnSharedPreferenceChangeListener { private final static String TAG = SettingsFragment.class.getSimpleName(); - private final Map serverSettings = new LinkedHashMap(); + private final Map serverSettings = new LinkedHashMap<>(); private boolean testingConnection; private ListPreference theme; private ListPreference maxBitrateWifi; @@ -74,7 +69,6 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared private ListPreference keepPlayedCount; private ListPreference tempLoss; private ListPreference pauseDisconnect; - private Preference addServerPreference; private PreferenceCategory serversCategory; private ListPreference songPressAction; private ListPreference syncInterval; @@ -122,17 +116,17 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared Bundle args = new Bundle(); int xml = 0; - if("appearance".equals(name)) { + if ("appearance".equals(name)) { xml = R.xml.settings_appearance; - } else if("cache".equals(name)) { + } else if ("cache".equals(name)) { xml = R.xml.settings_cache; - } else if("playback".equals(name)) { + } else if ("playback".equals(name)) { xml = R.xml.settings_playback; - } else if("servers".equals(name)) { + } else if ("servers".equals(name)) { xml = R.xml.settings_servers; } - if(xml != 0) { + if (xml != 0) { args.putInt(Constants.INTENT_EXTRA_FRAGMENT_TYPE, xml); newFragment.setArguments(args); replaceFragment(newFragment); @@ -142,7 +136,7 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { // Random error I have no idea how to reproduce - if(sharedPreferences == null) { + if (sharedPreferences == null) { return; } @@ -150,25 +144,22 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared if (Constants.PREFERENCES_KEY_HIDE_MEDIA.equals(key)) { setHideMedia(sharedPreferences.getBoolean(key, true)); - } - else if (Constants.PREFERENCES_KEY_MEDIA_BUTTONS.equals(key)) { + } else if (Constants.PREFERENCES_KEY_MEDIA_BUTTONS.equals(key)) { setMediaButtonsEnabled(sharedPreferences.getBoolean(key, true)); - } - else if (Constants.PREFERENCES_KEY_CACHE_LOCATION.equals(key)) { + } else if (Constants.PREFERENCES_KEY_CACHE_LOCATION.equals(key)) { setCacheLocation(sharedPreferences.getString(key, "")); - } - else if(Constants.PREFERENCES_KEY_SYNC_MOST_RECENT.equals(key)) { + } else if (Constants.PREFERENCES_KEY_SYNC_MOST_RECENT.equals(key)) { SyncUtil.removeMostRecentSyncFiles(context); - } else if(Constants.PREFERENCES_KEY_REPLAY_GAIN.equals(key) || Constants.PREFERENCES_KEY_REPLAY_GAIN_BUMP.equals(key) || Constants.PREFERENCES_KEY_REPLAY_GAIN_UNTAGGED.equals(key)) { + } else if (Constants.PREFERENCES_KEY_REPLAY_GAIN.equals(key) || Constants.PREFERENCES_KEY_REPLAY_GAIN_BUMP.equals(key) || Constants.PREFERENCES_KEY_REPLAY_GAIN_UNTAGGED.equals(key)) { DownloadService downloadService = DownloadService.getInstance(); - if(downloadService != null) { + if (downloadService != null) { downloadService.reapplyVolume(); } - } else if(Constants.PREFERENCES_KEY_START_ON_HEADPHONES.equals(key)) { + } else if (Constants.PREFERENCES_KEY_START_ON_HEADPHONES.equals(key)) { Intent serviceIntent = new Intent(); serviceIntent.setClassName(context.getPackageName(), HeadphoneListenerService.class.getName()); - if(sharedPreferences.getBoolean(key, false)) { + if (sharedPreferences.getBoolean(key, false)) { context.startService(serviceIntent); } else { context.stopService(serviceIntent); @@ -199,7 +190,7 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared tempLoss = (ListPreference) this.findPreference(Constants.PREFERENCES_KEY_TEMP_LOSS); pauseDisconnect = (ListPreference) this.findPreference(Constants.PREFERENCES_KEY_PAUSE_DISCONNECT); serversCategory = (PreferenceCategory) this.findPreference(Constants.PREFERENCES_KEY_SERVER_KEY); - addServerPreference = this.findPreference(Constants.PREFERENCES_KEY_SERVER_ADD); + Preference addServerPreference = this.findPreference(Constants.PREFERENCES_KEY_SERVER_ADD); songPressAction = (ListPreference) this.findPreference(Constants.PREFERENCES_KEY_SONG_PRESS_ACTION); syncInterval = (ListPreference) this.findPreference(Constants.PREFERENCES_KEY_SYNC_INTERVAL); syncEnabled = (CheckBoxPreference) this.findPreference(Constants.PREFERENCES_KEY_SYNC_ENABLED); @@ -215,86 +206,69 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared settings = Util.getPreferences(context); serverCount = settings.getInt(Constants.PREFERENCES_KEY_SERVER_COUNT, 1); - if(cacheSize != null) { - this.findPreference("clearCache").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - Util.confirmDialog(context, R.string.common_delete, R.string.common_confirm_message_cache, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - new LoadingTask(context, false) { - @Override - protected Void doInBackground() throws Throwable { - FileUtil.deleteMusicDirectory(context); - FileUtil.deleteSerializedCache(context); - FileUtil.deleteArtworkCache(context); - return null; - } + if (cacheSize != null) { + this.findPreference("clearCache").setOnPreferenceClickListener(preference -> { + Util.confirmDialog(context, (dialog, which) -> new LoadingTask(context, false) { + @Override + protected Void doInBackground() throws Throwable { + FileUtil.deleteMusicDirectory(context); + FileUtil.deleteSerializedCache(context); + FileUtil.deleteArtworkCache(context); + return null; + } - @Override - protected void done(Void result) { - Util.toast(context, R.string.settings_cache_clear_complete); - } + @Override + protected void done(Void result) { + Util.toast(context, R.string.settings_cache_clear_complete); + } - @Override - protected void error(Throwable error) { - Util.toast(context, getErrorMessage(error), false); - } - }.execute(); - } - }); - return false; - } + @Override + protected void error(Throwable error) { + Util.toast(context, getErrorMessage(error), false); + } + }.execute()); + return false; }); } - if(syncEnabled != null) { - this.findPreference(Constants.PREFERENCES_KEY_SYNC_ENABLED).setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - Boolean syncEnabled = (Boolean) newValue; + if (syncEnabled != null) { + this.findPreference(Constants.PREFERENCES_KEY_SYNC_ENABLED).setOnPreferenceChangeListener((preference, newValue) -> { + Boolean syncEnabled = (Boolean) newValue; - Account account = new Account(Constants.SYNC_ACCOUNT_NAME, Constants.SYNC_ACCOUNT_TYPE); - ContentResolver.setSyncAutomatically(account, Constants.SYNC_ACCOUNT_PLAYLIST_AUTHORITY, syncEnabled); + Account account = new Account(Constants.SYNC_ACCOUNT_NAME, Constants.SYNC_ACCOUNT_TYPE); + ContentResolver.setSyncAutomatically(account, Constants.SYNC_ACCOUNT_PLAYLIST_AUTHORITY, syncEnabled); - return true; - } + return true; }); - syncInterval.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - Integer syncInterval = Integer.parseInt(((String) newValue)); + syncInterval.setOnPreferenceChangeListener((preference, newValue) -> { + Integer syncInterval = Integer.parseInt(((String) newValue)); - Account account = new Account(Constants.SYNC_ACCOUNT_NAME, Constants.SYNC_ACCOUNT_TYPE); - ContentResolver.addPeriodicSync(account, Constants.SYNC_ACCOUNT_PLAYLIST_AUTHORITY, new Bundle(), 60L * syncInterval); + Account account = new Account(Constants.SYNC_ACCOUNT_NAME, Constants.SYNC_ACCOUNT_TYPE); + ContentResolver.addPeriodicSync(account, Constants.SYNC_ACCOUNT_PLAYLIST_AUTHORITY, new Bundle(), 60L * syncInterval); - return true; - } + return true; }); } - if(serversCategory != null) { - addServerPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - serverCount++; - int instance = serverCount; - serversCategory.addPreference(addServer(serverCount)); + if (serversCategory != null) { + addServerPreference.setOnPreferenceClickListener(preference -> { + serverCount++; + int instance = serverCount; + serversCategory.addPreference(addServer(serverCount)); - SharedPreferences.Editor editor = settings.edit(); - editor.putInt(Constants.PREFERENCES_KEY_SERVER_COUNT, serverCount); - // Reset set folder ID - editor.putString(Constants.PREFERENCES_KEY_MUSIC_FOLDER_ID + instance, null); - editor.putString(Constants.PREFERENCES_KEY_SERVER_URL + instance, "http://yourhost"); - editor.putString(Constants.PREFERENCES_KEY_SERVER_NAME + instance, getResources().getString(R.string.settings_server_unused)); - editor.apply(); + SharedPreferences.Editor editor = settings.edit(); + editor.putInt(Constants.PREFERENCES_KEY_SERVER_COUNT, serverCount); + // Reset set folder ID + editor.putString(Constants.PREFERENCES_KEY_MUSIC_FOLDER_ID + instance, null); + editor.putString(Constants.PREFERENCES_KEY_SERVER_URL + instance, "http://yourhost"); + editor.putString(Constants.PREFERENCES_KEY_SERVER_NAME + instance, getResources().getString(R.string.settings_server_unused)); + editor.apply(); - ServerSettings ss = new ServerSettings(instance); - serverSettings.put(String.valueOf(instance), ss); - ss.update(); + ServerSettings ss = new ServerSettings(instance); + serverSettings.put(String.valueOf(instance), ss); + ss.update(); - return true; - } + return true; }); serversCategory.setOrderingAsAdded(false); @@ -311,18 +285,8 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared } private void scheduleBackup() { - try { - Class managerClass = Class.forName("android.app.backup.BackupManager"); - Constructor managerConstructor = managerClass.getConstructor(Context.class); - Object manager = managerConstructor.newInstance(context); - Method m = managerClass.getMethod("dataChanged"); - m.invoke(manager); - } catch(ClassNotFoundException e) { - Log.e(TAG, "No backup manager found"); - } catch(Throwable t) { - Log.e(TAG, "Scheduling backup failed " + t); - t.printStackTrace(); - } + BackupManager backupManager = new BackupManager(context); + backupManager.dataChanged(); } private void update() { @@ -330,11 +294,11 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared return; } - if(theme != null) { + if (theme != null) { theme.setSummary(theme.getEntry()); } - if(cacheSize != null) { + if (cacheSize != null) { maxBitrateWifi.setSummary(maxBitrateWifi.getEntry()); maxBitrateMobile.setSummary(maxBitrateMobile.getEntry()); networkTimeout.setSummary(networkTimeout.getEntry()); @@ -343,24 +307,24 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared preloadCountMobile.setSummary(preloadCountMobile.getEntry()); try { - if(megabyteFromat == null) { + if (megabyteFromat == null) { megabyteFromat = new DecimalFormat(getResources().getString(R.string.util_bytes_format_megabyte)); } cacheSize.setSummary(megabyteFromat.format((double) Integer.parseInt(cacheSize.getText())).replace(".00", "")); - } catch(Exception e) { + } catch (Exception e) { Log.e(TAG, "Failed to format cache size", e); cacheSize.setSummary(cacheSize.getText()); } } - if(keepPlayedCount != null) { + if (keepPlayedCount != null) { keepPlayedCount.setSummary(keepPlayedCount.getEntry()); tempLoss.setSummary(tempLoss.getEntry()); pauseDisconnect.setSummary(pauseDisconnect.getEntry()); songPressAction.setSummary(songPressAction.getEntry()); - if(replayGain.isChecked()) { + if (replayGain.isChecked()) { replayGainType.setEnabled(true); replayGainBump.setEnabled(true); replayGainUntagged.setEnabled(true); @@ -372,18 +336,18 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared replayGainType.setSummary(replayGainType.getEntry()); } - if(syncEnabled != null) { + if (syncEnabled != null) { syncInterval.setSummary(syncInterval.getEntry()); - if(syncEnabled.isChecked()) { - if(!syncInterval.isEnabled()) { + if (syncEnabled.isChecked()) { + if (!syncInterval.isEnabled()) { syncInterval.setEnabled(true); syncWifi.setEnabled(true); syncNotification.setEnabled(true); syncMostRecent.setEnabled(true); } } else { - if(syncInterval.isEnabled()) { + if (syncInterval.isEnabled()) { syncInterval.setEnabled(false); syncWifi.setEnabled(false); syncNotification.setEnabled(false); @@ -396,9 +360,10 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared ss.update(); } } - public void checkForRemoved() { + + private void checkForRemoved() { for (ServerSettings ss : serverSettings.values()) { - if(!ss.update()) { + if (!ss.update()) { serversCategory.removePreference(ss.getScreen()); serverCount--; } @@ -410,18 +375,15 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared screen.setKey(Constants.PREFERENCES_KEY_SERVER_KEY + instance); screen.setOrder(instance); - screen.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - SettingsFragment newFragment = new SettingsFragment(); + screen.setOnPreferenceClickListener(preference -> { + SettingsFragment newFragment = new SettingsFragment(); - Bundle args = new Bundle(); - args.putInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, instance); - newFragment.setArguments(args); + Bundle args = new Bundle(); + args.putInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, instance); + newFragment.setArguments(args); - replaceFragment(newFragment); - return false; - } + replaceFragment(newFragment); + return false; }); return screen; @@ -466,12 +428,7 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared Button defaultButton = new Button(getContext()); defaultButton.setText(internalSSIDDisplay); - defaultButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - editText.setText(internalSSID); - } - }); + defaultButton.setOnClickListener(v -> editText.setText(internalSSID)); root.addView(defaultButton); } }; @@ -502,12 +459,9 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared serverOpenBrowser.setKey(Constants.PREFERENCES_KEY_OPEN_BROWSER); serverOpenBrowser.setPersistent(false); serverOpenBrowser.setTitle(R.string.settings_server_open_browser); - serverOpenBrowser.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - openInBrowser(instance); - return true; - } + serverOpenBrowser.setOnPreferenceClickListener(preference -> { + openInBrowser(instance); + return true; }); Preference serverRemoveServerPreference = new Preference(context); @@ -515,53 +469,44 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared serverRemoveServerPreference.setPersistent(false); serverRemoveServerPreference.setTitle(R.string.settings_servers_remove); - serverRemoveServerPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - Util.confirmDialog(context, R.string.common_delete, screen.getTitle().toString(), new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - // Reset values to null so when we ask for them again they are new - serverNamePreference.setText(null); - serverUrlPreference.setText(null); - serverUsernamePreference.setText(null); - serverPasswordPreference.setText(null); + serverRemoveServerPreference.setOnPreferenceClickListener(preference -> { + Util.confirmDialog(context, R.string.common_delete, screen.getTitle().toString(), (dialog, which) -> { + // Reset values to null so when we ask for them again they are new + serverNamePreference.setText(null); + serverUrlPreference.setText(null); + serverUsernamePreference.setText(null); + serverPasswordPreference.setText(null); - // Don't use Util.getActiveServer since it is 0 if offline - int activeServer = Util.getPreferences(context).getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1); - for (int i = instance; i <= serverCount; i++) { - Util.removeInstanceName(context, i, activeServer); - } + // Don't use Util.getActiveServer since it is 0 if offline + int activeServer = Util.getPreferences(context).getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1); + for (int i = instance; i <= serverCount; i++) { + Util.removeInstanceName(context, i, activeServer); + } - serverCount--; - SharedPreferences.Editor editor = settings.edit(); - editor.putInt(Constants.PREFERENCES_KEY_SERVER_COUNT, serverCount); - editor.apply(); + serverCount--; + SharedPreferences.Editor editor = settings.edit(); + editor.putInt(Constants.PREFERENCES_KEY_SERVER_COUNT, serverCount); + editor.apply(); - removeCurrent(); + removeCurrent(); - SubsonicFragment parentFragment = context.getCurrentFragment(); - if(parentFragment instanceof SettingsFragment) { - SettingsFragment serverSelectionFragment = (SettingsFragment) parentFragment; - serverSelectionFragment.checkForRemoved(); - } - } - }); + SubsonicFragment parentFragment = context.getCurrentFragment(); + if (parentFragment instanceof SettingsFragment) { + SettingsFragment serverSelectionFragment = (SettingsFragment) parentFragment; + serverSelectionFragment.checkForRemoved(); + } + }); - return true; - } + return true; }); Preference serverTestConnectionPreference = new Preference(context); serverTestConnectionPreference.setKey(Constants.PREFERENCES_KEY_TEST_CONNECTION + instance); serverTestConnectionPreference.setPersistent(false); serverTestConnectionPreference.setTitle(R.string.settings_test_connection_title); - serverTestConnectionPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - testConnection(instance); - return false; - } + serverTestConnectionPreference.setOnPreferenceClickListener(preference -> { + testConnection(instance); + return false; }); screen.addPreference(serverNamePreference); @@ -585,22 +530,22 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared if (!nomediaDir.createNewFile()) { Log.w(TAG, "Failed to create " + nomediaDir); } - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to create " + nomediaDir, e); } try { - if(!musicNoMedia.createNewFile()) { + if (!musicNoMedia.createNewFile()) { Log.w(TAG, "Failed to create " + musicNoMedia); } - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to create " + musicNoMedia, e); } } else if (!hide && nomediaDir.exists()) { if (!nomediaDir.delete()) { Log.w(TAG, "Failed to delete " + nomediaDir); } - if(!musicNoMedia.delete()) { + if (!musicNoMedia.delete()) { Log.w(TAG, "Failed to delete " + musicNoMedia); } } @@ -628,7 +573,7 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared editor.putString(Constants.PREFERENCES_KEY_CACHE_LOCATION, defaultPath); editor.apply(); - if(cacheLocation != null) { + if (cacheLocation != null) { cacheLocation.setSummary(defaultPath); cacheLocation.setText(defaultPath); } @@ -646,7 +591,7 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared @Override protected Boolean doInBackground() throws Throwable { - updateProgress(R.string.settings_testing_connection); + updateProgress(); previousInstance = Util.getActiveServer(context); testingConnection = true; @@ -685,8 +630,8 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared private void openInBrowser(final int instance) { SharedPreferences prefs = Util.getPreferences(context); String url = prefs.getString(Constants.PREFERENCES_KEY_SERVER_URL + instance, null); - if(url == null) { - new ErrorDialog(context, R.string.settings_invalid_url, false); + if (url == null) { + new ErrorDialog(context, R.string.settings_invalid_url); return; } Uri uriServer = Uri.parse(url); @@ -696,13 +641,13 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared } private class ServerSettings { - private int instance; - private EditTextPreference serverName; - private EditTextPreference serverUrl; - private EditTextPreference serverLocalNetworkSSID; - private EditTextPreference serverInternalUrl; - private EditTextPreference username; - private PreferenceScreen screen; + private final int instance; + private final EditTextPreference serverName; + private final EditTextPreference serverUrl; + private final EditTextPreference serverLocalNetworkSSID; + private final EditTextPreference serverInternalUrl; + private final EditTextPreference username; + private final PreferenceScreen screen; private ServerSettings(int instance) { this.instance = instance; @@ -713,55 +658,46 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared serverInternalUrl = (EditTextPreference) SettingsFragment.this.findPreference(Constants.PREFERENCES_KEY_SERVER_INTERNAL_URL + instance); username = (EditTextPreference) SettingsFragment.this.findPreference(Constants.PREFERENCES_KEY_USERNAME + instance); - if(serverName != null) { - serverUrl.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object value) { - try { - String url = (String) value; - new URL(url); - if (url.contains(" ") || url.contains("@") || url.contains("_")) { - throw new Exception(); - } - } catch (Exception x) { - new ErrorDialog(context, R.string.settings_invalid_url, false); - return false; + if (serverName != null) { + serverUrl.setOnPreferenceChangeListener((preference, value) -> { + try { + String url = (String) value; + new URL(url); + if (url.contains(" ") || url.contains("@") || url.contains("_")) { + throw new Exception(); } - return true; + } catch (Exception x) { + new ErrorDialog(context, R.string.settings_invalid_url); + return false; } + return true; }); - serverInternalUrl.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object value) { - try { - String url = (String) value; - // Allow blank internal IP address - if ("".equals(url) || url == null) { - return true; - } - - new URL(url); - if (url.contains(" ") || url.contains("@") || url.contains("_")) { - throw new Exception(); - } - } catch (Exception x) { - new ErrorDialog(context, R.string.settings_invalid_url, false); - return false; + serverInternalUrl.setOnPreferenceChangeListener((preference, value) -> { + try { + String url = (String) value; + // Allow blank internal IP address + if ("".equals(url) || url == null) { + return true; } - return true; + + new URL(url); + if (url.contains(" ") || url.contains("@") || url.contains("_")) { + throw new Exception(); + } + } catch (Exception x) { + new ErrorDialog(context, R.string.settings_invalid_url); + return false; } + return true; }); - username.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object value) { - String username = (String) value; - if (username == null || !username.equals(username.trim())) { - new ErrorDialog(context, R.string.settings_invalid_username, false); - return false; - } - return true; + username.setOnPreferenceChangeListener((preference, value) -> { + String username = (String) value; + if (username == null || !username.equals(username.trim())) { + new ErrorDialog(context, R.string.settings_invalid_username); + return false; } + return true; }); } } @@ -773,7 +709,7 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared public boolean update() { SharedPreferences prefs = Util.getPreferences(context); - if(prefs.contains(Constants.PREFERENCES_KEY_SERVER_NAME + instance)) { + if (prefs.contains(Constants.PREFERENCES_KEY_SERVER_NAME + instance)) { if (serverName != null) { serverName.setSummary(serverName.getText()); serverUrl.setSummary(serverUrl.getText()); diff --git a/app/src/main/java/net/nullsum/audinaut/fragments/SubsonicFragment.java b/app/src/main/java/net/nullsum/audinaut/fragments/SubsonicFragment.java index 742ce71..55d150f 100644 --- a/app/src/main/java/net/nullsum/audinaut/fragments/SubsonicFragment.java +++ b/app/src/main/java/net/nullsum/audinaut/fragments/SubsonicFragment.java @@ -21,21 +21,15 @@ package net.nullsum.audinaut.fragments; import android.app.Activity; import android.app.SearchManager; import android.app.SearchableInfo; -import android.support.v4.view.MenuItemCompat; -import android.support.v7.app.AlertDialog; import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; import android.media.MediaMetadataRetriever; -import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.os.StatFs; import android.support.v4.app.Fragment; +import android.support.v4.view.MenuItemCompat; import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.app.AlertDialog; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; @@ -47,15 +41,14 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.widget.AbsListView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.TextView; + import net.nullsum.audinaut.R; import net.nullsum.audinaut.activity.SubsonicActivity; -import net.nullsum.audinaut.activity.SubsonicFragmentActivity; import net.nullsum.audinaut.adapter.SectionAdapter; import net.nullsum.audinaut.domain.Artist; import net.nullsum.audinaut.domain.Genre; @@ -70,59 +63,50 @@ import net.nullsum.audinaut.service.OfflineException; import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.FileUtil; import net.nullsum.audinaut.util.ImageLoader; +import net.nullsum.audinaut.util.LoadingTask; import net.nullsum.audinaut.util.MenuUtil; import net.nullsum.audinaut.util.ProgressListener; import net.nullsum.audinaut.util.SilentBackgroundTask; -import net.nullsum.audinaut.util.LoadingTask; import net.nullsum.audinaut.util.SongDBHandler; -import net.nullsum.audinaut.util.UpdateHelper; import net.nullsum.audinaut.util.UserUtil; import net.nullsum.audinaut.util.Util; -import net.nullsum.audinaut.view.AlbumView; -import net.nullsum.audinaut.view.ArtistEntryView; -import net.nullsum.audinaut.view.ArtistView; import net.nullsum.audinaut.view.GridSpacingDecoration; import net.nullsum.audinaut.view.PlaylistSongView; -import net.nullsum.audinaut.view.SongView; import net.nullsum.audinaut.view.UpdateView; import java.io.File; import java.text.DateFormat; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Random; import static net.nullsum.audinaut.domain.MusicDirectory.Entry; public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener { private static final String TAG = SubsonicFragment.class.getSimpleName(); private static int TAG_INC = 10; + SubsonicActivity context; + CharSequence title = null; + CharSequence subtitle = null; + View rootView; + boolean primaryFragment = false; + boolean secondaryFragment = false; + boolean isOnlyVisible = true; + boolean alwaysFullscreen = false; + boolean alwaysStartFullscreen = false; + boolean invalidated = false; + GestureDetector gestureScanner; + boolean artist = false; + SwipeRefreshLayout refreshLayout; + MenuItem searchItem; + private boolean artistOverride = false; + private boolean firstRun; + private SearchView searchView; private int tag; - protected SubsonicActivity context; - protected CharSequence title = null; - protected CharSequence subtitle = null; - protected View rootView; - protected boolean primaryFragment = false; - protected boolean secondaryFragment = false; - protected boolean isOnlyVisible = true; - protected boolean alwaysFullscreen = false; - protected boolean alwaysStartFullscreen = false; - protected boolean invalidated = false; - protected static Random random = new Random(); - protected GestureDetector gestureScanner; - protected boolean artist = false; - protected boolean artistOverride = false; - protected SwipeRefreshLayout refreshLayout; - protected boolean firstRun; - protected MenuItem searchItem; - protected SearchView searchView; - public SubsonicFragment() { super(); tag = TAG_INC++; @@ -132,9 +116,9 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR public void onCreate(Bundle bundle) { super.onCreate(bundle); - if(bundle != null) { + if (bundle != null) { String name = bundle.getString(Constants.FRAGMENT_NAME); - if(name != null) { + if (name != null) { title = name; } } @@ -144,7 +128,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - if(title != null) { + if (title != null) { outState.putString(Constants.FRAGMENT_NAME, title.toString()); } } @@ -152,48 +136,38 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR @Override public void onResume() { super.onResume(); - if(firstRun) { + if (firstRun) { firstRun = false; } else { UpdateView.triggerUpdate(); } } - @Override - public void onDestroy() { - super.onDestroy(); - } - @Override public void onAttach(Activity activity) { super.onAttach(activity); - context = (SubsonicActivity)activity; + context = (SubsonicActivity) activity; } public void setContext(SubsonicActivity context) { this.context = context; } - protected void onFinishSetupOptionsMenu(final Menu menu) { + void onFinishSetupOptionsMenu(final Menu menu) { searchItem = menu.findItem(R.id.menu_global_search); - if(searchItem != null) { + if (searchItem != null) { searchView = (SearchView) MenuItemCompat.getActionView(searchItem); SearchManager searchManager = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE); SearchableInfo searchableInfo = searchManager.getSearchableInfo(context.getComponentName()); - if(searchableInfo == null) { + if (searchableInfo == null) { Log.w(TAG, "Failed to get SearchableInfo"); } else { searchView.setSearchableInfo(searchableInfo); } String currentQuery = getCurrentQuery(); - if(currentQuery != null) { - searchView.setOnSearchClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - searchView.setQuery(getCurrentQuery(), false); - } - }); + if (currentQuery != null) { + searchView.setOnSearchClickListener(v -> searchView.setQuery(getCurrentQuery(), false)); } } } @@ -241,37 +215,34 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR return false; } - public void onCreateContextMenuSupport(Menu menu, MenuInflater menuInflater, UpdateView updateView, Object selected) { - if(selected instanceof Entry) { + void onCreateContextMenuSupport(Menu menu, MenuInflater menuInflater, UpdateView updateView, Object selected) { + if (selected instanceof Entry) { Entry entry = (Entry) selected; if (entry.isDirectory()) { - if(Util.isOffline(context)) { + if (Util.isOffline(context)) { menuInflater.inflate(R.menu.select_album_context_offline, menu); - } - else { + } else { menuInflater.inflate(R.menu.select_album_context, menu); } } else { - if(Util.isOffline(context)) { + if (Util.isOffline(context)) { menuInflater.inflate(R.menu.select_song_context_offline, menu); - } - else { + } else { menuInflater.inflate(R.menu.select_song_context, menu); String songPressAction = Util.getSongPressAction(context); - if(!"next".equals(songPressAction) && !"last".equals(songPressAction)) { + if (!"next".equals(songPressAction) && !"last".equals(songPressAction)) { menu.setGroupVisible(R.id.hide_play_now, false); } } } - if(!isShowArtistEnabled() || (!Util.isTagBrowsing(context) && entry.getParent() == null) || (Util.isTagBrowsing(context) && entry.getArtistId() == null)) { + if (!isShowArtistEnabled() || (entry.getArtistId() == null)) { menu.setGroupVisible(R.id.hide_show_artist, false); } - } else if(selected instanceof Artist) { - Artist artist = (Artist) selected; - if(Util.isOffline(context)) { + } else if (selected instanceof Artist) { + if (Util.isOffline(context)) { menuInflater.inflate(R.menu.select_artist_context_offline, menu); } else { menuInflater.inflate(R.menu.select_artist_context, menu); @@ -281,60 +252,60 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR MenuUtil.hideMenuItems(context, menu, updateView); } - protected void recreateContextMenu(Menu menu) { - List menuItems = new ArrayList(); - for(int i = 0; i < menu.size(); i++) { + void recreateContextMenu(Menu menu) { + List menuItems = new ArrayList<>(); + for (int i = 0; i < menu.size(); i++) { MenuItem item = menu.getItem(i); - if(item.isVisible()) { + if (item.isVisible()) { menuItems.add(item); } } menu.clear(); - for(int i = 0; i < menuItems.size(); i++) { + for (int i = 0; i < menuItems.size(); i++) { MenuItem item = menuItems.get(i); menu.add(tag, item.getItemId(), Menu.NONE, item.getTitle()); } } // For reverting specific removals: https://github.com/daneren2005/Subsonic/commit/fbd1a68042dfc3601eaa0a9e37b3957bbdd51420 - public boolean onContextItemSelected(MenuItem menuItem, Object selectedItem) { + boolean onContextItemSelected(MenuItem menuItem, Object selectedItem) { Artist artist = selectedItem instanceof Artist ? (Artist) selectedItem : null; Entry entry = selectedItem instanceof Entry ? (Entry) selectedItem : null; - if(selectedItem instanceof DownloadFile) { + if (selectedItem instanceof DownloadFile) { entry = ((DownloadFile) selectedItem).getSong(); } - List songs = new ArrayList(1); + List songs = new ArrayList<>(1); songs.add(entry); switch (menuItem.getItemId()) { case R.id.artist_menu_play_now: - downloadRecursively(artist.getId(), false, false, true, false, false); + downloadRecursively(artist.getId(), false, false, true, false, false, false); break; case R.id.artist_menu_play_shuffled: - downloadRecursively(artist.getId(), false, false, true, true, false); + downloadRecursively(artist.getId(), false, false, true, true, false, false); break; case R.id.artist_menu_play_next: downloadRecursively(artist.getId(), false, true, false, false, false, true); break; case R.id.artist_menu_play_last: - downloadRecursively(artist.getId(), false, true, false, false, false); + downloadRecursively(artist.getId(), false, true, false, false, false, false); break; case R.id.artist_menu_download: - downloadRecursively(artist.getId(), false, true, false, false, true); + downloadRecursively(artist.getId(), false, true, false, false, true, false); break; case R.id.artist_menu_pin: - downloadRecursively(artist.getId(), true, true, false, false, true); + downloadRecursively(artist.getId(), true, true, false, false, true, false); break; case R.id.artist_menu_delete: deleteRecursively(artist); break; case R.id.album_menu_play_now: artistOverride = true; - downloadRecursively(entry.getId(), false, false, true, false, false); + downloadRecursively(entry.getId(), false, false, true, false, false, false); break; case R.id.album_menu_play_shuffled: artistOverride = true; - downloadRecursively(entry.getId(), false, false, true, true, false); + downloadRecursively(entry.getId(), false, false, true, true, false, false); break; case R.id.album_menu_play_next: artistOverride = true; @@ -342,15 +313,15 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR break; case R.id.album_menu_play_last: artistOverride = true; - downloadRecursively(entry.getId(), false, true, false, false, false); + downloadRecursively(entry.getId(), false, true, false, false, false, false); break; case R.id.album_menu_download: artistOverride = true; - downloadRecursively(entry.getId(), false, true, false, false, true); + downloadRecursively(entry.getId(), false, true, false, false, true, false); break; case R.id.album_menu_pin: artistOverride = true; - downloadRecursively(entry.getId(), true, true, false, false, true); + downloadRecursively(entry.getId(), true, true, false, false, true, false); break; case R.id.album_menu_delete: deleteRecursively(entry); @@ -398,16 +369,11 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR return true; } - public void replaceFragment(SubsonicFragment fragment) { - replaceFragment(fragment, true); + void replaceFragment(SubsonicFragment fragment) { + context.replaceFragment(fragment, fragment.getSupportTag(), secondaryFragment); } - public void replaceFragment(SubsonicFragment fragment, boolean replaceCurrent) { - context.replaceFragment(fragment, fragment.getSupportTag(), secondaryFragment && replaceCurrent); - } - public void replaceExistingFragment(SubsonicFragment fragment) { - context.replaceExistingFragment(fragment, fragment.getSupportTag()); - } - public void removeCurrent() { + + void removeCurrent() { context.removeCurrent(); } @@ -415,44 +381,51 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR return rootView.getId(); } - public void setSupportTag(int tag) { this.tag = tag; } - public void setSupportTag(String tag) { this.tag = Integer.parseInt(tag); } public int getSupportTag() { return tag; } + public void setSupportTag(String tag) { + this.tag = Integer.parseInt(tag); + } + public void setPrimaryFragment(boolean primary) { primaryFragment = primary; - if(primary) { - if(context != null && title != null) { + if (primary) { + if (context != null && title != null) { context.setTitle(title); context.setSubtitle(subtitle); } - if(invalidated) { + if (invalidated) { invalidated = false; refresh(false); } } } + public void setPrimaryFragment(boolean primary, boolean secondary) { setPrimaryFragment(primary); secondaryFragment = secondary; } + public void setSecondaryFragment(boolean secondary) { secondaryFragment = secondary; } + public void setIsOnlyVisible(boolean isOnlyVisible) { this.isOnlyVisible = isOnlyVisible; } + public boolean isAlwaysFullscreen() { return alwaysFullscreen; } + public boolean isAlwaysStartFullscreen() { return alwaysStartFullscreen; } public void invalidate() { - if(primaryFragment) { + if (primaryFragment) { refresh(true); } else { invalidated = true; @@ -463,10 +436,11 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR return context != null ? context.getDownloadService() : null; } - protected void refresh() { + private void refresh() { refresh(true); } - protected void refresh(boolean refresh) { + + void refresh(boolean refresh) { } @@ -481,7 +455,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR if (view != null) { view.setVisibility(visible ? View.VISIBLE : View.GONE); - if(visible) { + if (visible) { View progress = rootView.findViewById(R.id.tab_progress_spinner); progress.setVisibility(View.VISIBLE); } @@ -489,77 +463,55 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } public void updateProgress(String message) { - TextView view = (TextView) rootView.findViewById(R.id.tab_progress_message); + TextView view = rootView.findViewById(R.id.tab_progress_message); if (view != null) { view.setText(message); } } - public void setEmpty(boolean empty) { + void setEmpty(boolean empty) { View view = rootView.findViewById(R.id.tab_progress); - if(empty) { + if (empty) { view.setVisibility(View.VISIBLE); View progress = view.findViewById(R.id.tab_progress_spinner); progress.setVisibility(View.GONE); - TextView text = (TextView) view.findViewById(R.id.tab_progress_message); + TextView text = view.findViewById(R.id.tab_progress_message); text.setText(R.string.common_empty); } else { view.setVisibility(View.GONE); } } - protected synchronized ImageLoader getImageLoader() { + synchronized ImageLoader getImageLoader() { return context.getImageLoader(); } - public synchronized static ImageLoader getStaticImageLoader(Context context) { - return SubsonicActivity.getStaticImageLoader(context); - } - public void setTitle(CharSequence title) { + void setTitle(CharSequence title) { this.title = title; context.setTitle(title); } - public void setTitle(int title) { - this.title = context.getResources().getString(title); - context.setTitle(this.title); - } - public void setSubtitle(CharSequence title) { + + void setSubtitle(CharSequence title) { this.subtitle = title; context.setSubtitle(title); } + public CharSequence getTitle() { return this.title; } - protected void setupScrollList(final AbsListView listView) { - if(!context.isTouchscreen()) { - refreshLayout.setEnabled(false); - } else { - listView.setOnScrollListener(new AbsListView.OnScrollListener() { - @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - } - - @Override - public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { - int topRowVerticalPosition = (listView.getChildCount() == 0) ? 0 : listView.getChildAt(0).getTop(); - refreshLayout.setEnabled(topRowVerticalPosition >= 0 && listView.getFirstVisiblePosition() == 0); - } - }); - } + void setTitle(int title) { + this.title = context.getResources().getString(title); + context.setTitle(this.title); } - protected void setupScrollList(final RecyclerView recyclerView) { - if(!context.isTouchscreen()) { + + void setupScrollList(final RecyclerView recyclerView) { + if (!context.isTouchscreen()) { refreshLayout.setEnabled(false); } else { recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - super.onScrollStateChanged(recyclerView, newState); - } - @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { refreshLayout.setEnabled(!recyclerView.canScrollVertically(-1)); @@ -568,41 +520,45 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } } - public void setupLayoutManager(RecyclerView recyclerView, boolean largeAlbums) { + void setupLayoutManager(RecyclerView recyclerView, boolean largeAlbums) { recyclerView.setLayoutManager(getLayoutManager(recyclerView, largeAlbums)); } - public RecyclerView.LayoutManager getLayoutManager(RecyclerView recyclerView, boolean largeCells) { - if(largeCells) { + + private RecyclerView.LayoutManager getLayoutManager(RecyclerView recyclerView, boolean largeCells) { + if (largeCells) { return getGridLayoutManager(recyclerView); } else { return getLinearLayoutManager(); } } - public GridLayoutManager getGridLayoutManager(RecyclerView recyclerView) { + + private GridLayoutManager getGridLayoutManager(RecyclerView recyclerView) { final int columns = getRecyclerColumnCount(); GridLayoutManager gridLayoutManager = new GridLayoutManager(context, columns); GridLayoutManager.SpanSizeLookup spanSizeLookup = getSpanSizeLookup(gridLayoutManager); - if(spanSizeLookup != null) { + if (spanSizeLookup != null) { gridLayoutManager.setSpanSizeLookup(spanSizeLookup); } RecyclerView.ItemDecoration itemDecoration = getItemDecoration(); - if(itemDecoration != null) { + if (itemDecoration != null) { recyclerView.addItemDecoration(itemDecoration); } return gridLayoutManager; } - public LinearLayoutManager getLinearLayoutManager() { + + private LinearLayoutManager getLinearLayoutManager() { LinearLayoutManager layoutManager = new LinearLayoutManager(context); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); return layoutManager; } - public GridLayoutManager.SpanSizeLookup getSpanSizeLookup(final GridLayoutManager gridLayoutManager) { + + GridLayoutManager.SpanSizeLookup getSpanSizeLookup(final GridLayoutManager gridLayoutManager) { return new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { SectionAdapter adapter = getCurrentAdapter(); - if(adapter != null) { + if (adapter != null) { int viewType = adapter.getItemViewType(position); if (viewType == SectionAdapter.VIEW_TYPE_HEADER) { return gridLayoutManager.getSpanCount(); @@ -615,37 +571,39 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } }; } - public RecyclerView.ItemDecoration getItemDecoration() { + + private RecyclerView.ItemDecoration getItemDecoration() { return new GridSpacingDecoration(); } - public int getRecyclerColumnCount() { - if(isOnlyVisible) { + + int getRecyclerColumnCount() { + if (isOnlyVisible) { return context.getResources().getInteger(R.integer.Grid_FullScreen_Columns); } else { return context.getResources().getInteger(R.integer.Grid_Columns); } } - protected void warnIfStorageUnavailable() { + void warnIfStorageUnavailable() { if (!Util.isExternalStoragePresent()) { Util.toast(context, R.string.select_album_no_sdcard); } try { StatFs stat = new StatFs(FileUtil.getMusicDirectory(context).getPath()); - long bytesAvailableFs = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize(); + long bytesAvailableFs = stat.getAvailableBlocksLong() * stat.getBlockSizeLong(); if (bytesAvailableFs < 50000000L) { Util.toast(context, context.getResources().getString(R.string.select_album_no_room, Util.formatBytes(bytesAvailableFs))); } - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Error while checking storage space for music directory", e); } } - protected void onShuffleRequested() { - if(Util.isOffline(context)) { + private void onShuffleRequested() { + if (Util.isOffline(context)) { DownloadService downloadService = getDownloadService(); - if(downloadService == null) { + if (downloadService == null) { return; } downloadService.clear(); @@ -655,17 +613,17 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } View dialogView = context.getLayoutInflater().inflate(R.layout.shuffle_dialog, null); - final EditText startYearBox = (EditText)dialogView.findViewById(R.id.start_year); - final EditText endYearBox = (EditText)dialogView.findViewById(R.id.end_year); - final EditText genreBox = (EditText)dialogView.findViewById(R.id.genre); - final Button genreCombo = (Button)dialogView.findViewById(R.id.genre_combo); + final EditText startYearBox = dialogView.findViewById(R.id.start_year); + final EditText endYearBox = dialogView.findViewById(R.id.end_year); + final EditText genreBox = dialogView.findViewById(R.id.genre); + final Button genreCombo = dialogView.findViewById(R.id.genre_combo); final SharedPreferences prefs = Util.getPreferences(context); final String oldStartYear = prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, ""); final String oldEndYear = prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, ""); final String oldGenre = prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, ""); - boolean _useCombo = false; + boolean _useCombo; genreBox.setVisibility(View.GONE); genreCombo.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { @@ -678,23 +636,21 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR @Override protected void done(final List genres) { - List names = new ArrayList(); + List names = new ArrayList<>(); String blank = context.getResources().getString(R.string.select_genre_blank); names.add(blank); - for(Genre genre: genres) { + for (Genre genre : genres) { names.add(genre.getName()); } final List finalNames = names; AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.shuffle_pick_genre) - .setItems(names.toArray(new CharSequence[names.size()]), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - if(which == 0) { - genreCombo.setText(""); - } else { - genreCombo.setText(finalNames.get(which)); - } + .setItems(names.toArray(new CharSequence[names.size()]), (dialog, which) -> { + if (which == 0) { + genreCombo.setText(""); + } else { + genreCombo.setText(finalNames.get(which)); } }); AlertDialog dialog = builder.create(); @@ -726,74 +682,69 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.shuffle_title) .setView(dialogView) - .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - String genre; - if (useCombo) { - genre = genreCombo.getText().toString(); - } else { - genre = genreBox.getText().toString(); - } - String startYear = startYearBox.getText().toString(); - String endYear = endYearBox.getText().toString(); - - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, startYear); - editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, endYear); - editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, genre); - editor.apply(); - - DownloadService downloadService = getDownloadService(); - if (downloadService == null) { - return; - } - - downloadService.clear(); - downloadService.setShufflePlayEnabled(true); - context.openNowPlaying(); + .setPositiveButton(R.string.common_ok, (dialog, id) -> { + String genre; + if (useCombo) { + genre = genreCombo.getText().toString(); + } else { + genre = genreBox.getText().toString(); } + String startYear = startYearBox.getText().toString(); + String endYear = endYearBox.getText().toString(); + + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, startYear); + editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, endYear); + editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, genre); + editor.apply(); + + DownloadService downloadService = getDownloadService(); + if (downloadService == null) { + return; + } + + downloadService.clear(); + downloadService.setShufflePlayEnabled(true); + context.openNowPlaying(); }) .setNegativeButton(R.string.common_cancel, null); AlertDialog dialog = builder.create(); dialog.show(); } - protected void downloadRecursively(final String id, final boolean save, final boolean append, final boolean autoplay, final boolean shuffle, final boolean background) { - downloadRecursively(id, "", true, save, append, autoplay, shuffle, background); - } - protected void downloadRecursively(final String id, final boolean save, final boolean append, final boolean autoplay, final boolean shuffle, final boolean background, final boolean playNext) { + void downloadRecursively(final String id, final boolean save, final boolean append, final boolean autoplay, final boolean shuffle, final boolean background, final boolean playNext) { downloadRecursively(id, "", true, save, append, autoplay, shuffle, background, playNext); } - protected void downloadPlaylist(final String id, final String name, final boolean save, final boolean append, final boolean autoplay, final boolean shuffle, final boolean background) { - downloadRecursively(id, name, false, save, append, autoplay, shuffle, background); + + void downloadPlaylist(final String id, final String name) { + downloadRecursively(id, name); } - protected void downloadRecursively(final String id, final String name, final boolean isDirectory, final boolean save, final boolean append, final boolean autoplay, final boolean shuffle, final boolean background) { - downloadRecursively(id, name, isDirectory, save, append, autoplay, shuffle, background, false); + private void downloadRecursively(final String id, final String name) { + downloadRecursively(id, name, false, false, true, false, false, true, false); } - protected void downloadRecursively(final String id, final String name, final boolean isDirectory, final boolean save, final boolean append, final boolean autoplay, final boolean shuffle, final boolean background, final boolean playNext) { + private void downloadRecursively(final String id, final String name, final boolean isDirectory, final boolean save, final boolean append, final boolean autoplay, final boolean shuffle, final boolean background, final boolean playNext) { new RecursiveLoader(context) { @Override protected Boolean doInBackground() throws Throwable { musicService = MusicServiceFactory.getMusicService(context); MusicDirectory root; - if(isDirectory && id != null) { + if (isDirectory && id != null) { root = getMusicDirectory(id, name, false, musicService, this); } else { root = musicService.getPlaylist(true, id, name, context, this); } boolean shuffleByAlbum = Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_SHUFFLE_BY_ALBUM, true); - if(shuffle && shuffleByAlbum) { + if (shuffle && shuffleByAlbum) { Collections.shuffle(root.getChildren()); } - songs = new LinkedList(); + songs = new LinkedList<>(); getSongsRecursively(root, songs); - if(shuffle && !shuffleByAlbum) { + if (shuffle && !shuffleByAlbum) { Collections.shuffle(songs); } @@ -801,7 +752,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR boolean transition = false; if (!songs.isEmpty() && downloadService != null) { // Conditions for a standard play now operation - if(!append && !save && autoplay && !playNext && !shuffle && !background) { + if (!append && !save && autoplay && !playNext && !shuffle && !background) { playNowOverride = true; return false; } @@ -809,13 +760,12 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR if (!append && !background) { downloadService.clear(); } - if(!background) { + if (!background) { downloadService.download(songs, save, autoplay, playNext, false); - if(!append) { + if (!append) { transition = true; } - } - else { + } else { downloadService.downloadBackground(songs, save); } } @@ -826,17 +776,17 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR }.execute(); } - protected void downloadRecursively(final List albums, final boolean shuffle, final boolean append, final boolean playNext) { + void downloadRecursively(final List albums, final boolean shuffle, final boolean append, final boolean playNext) { new RecursiveLoader(context) { @Override protected Boolean doInBackground() throws Throwable { musicService = MusicServiceFactory.getMusicService(context); - if(shuffle) { + if (shuffle) { Collections.shuffle(albums); } - songs = new LinkedList(); + songs = new LinkedList<>(); MusicDirectory root = new MusicDirectory(); root.addChildren(albums); getSongsRecursively(root, songs); @@ -845,7 +795,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR boolean transition = false; if (!songs.isEmpty() && downloadService != null) { // Conditions for a standard play now operation - if(!append && !shuffle) { + if (!append && !shuffle) { playNowOverride = true; return false; } @@ -855,7 +805,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } downloadService.download(songs, false, true, playNext, false); - if(!append) { + if (!append) { transition = true; } } @@ -866,12 +816,13 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR }.execute(); } - protected MusicDirectory getMusicDirectory(String id, String name, boolean refresh, MusicService service, ProgressListener listener) throws Exception { + MusicDirectory getMusicDirectory(String id, String name, boolean refresh, MusicService service, ProgressListener listener) throws Exception { return getMusicDirectory(id, name, refresh, false, service, listener); } - protected MusicDirectory getMusicDirectory(String id, String name, boolean refresh, boolean forceArtist, MusicService service, ProgressListener listener) throws Exception { - if(Util.isTagBrowsing(context) && !Util.isOffline(context)) { - if(artist && !artistOverride || forceArtist) { + + MusicDirectory getMusicDirectory(String id, String name, boolean refresh, boolean forceArtist, MusicService service, ProgressListener listener) throws Exception { + if (!Util.isOffline(context)) { + if (artist && !artistOverride || forceArtist) { return service.getArtist(id, name, refresh, context, listener); } else { return service.getAlbum(id, name, refresh, context, listener); @@ -881,16 +832,16 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } } - protected void addToPlaylist(final List songs) { + private void addToPlaylist(final List songs) { Iterator it = songs.iterator(); - while(it.hasNext()) { + while (it.hasNext()) { Entry entry = it.next(); - if(entry.isDirectory()) { + if (entry.isDirectory()) { it.remove(); } } - if(songs.isEmpty()) { + if (songs.isEmpty()) { Util.toast(context, "No songs selected"); return; } @@ -899,14 +850,14 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR @Override protected List doInBackground() throws Throwable { MusicService musicService = MusicServiceFactory.getMusicService(context); - List playlists = new ArrayList(); + List playlists = new ArrayList<>(); playlists.addAll(musicService.getPlaylists(false, context, this)); // Iterate through and remove all non owned public playlists Iterator it = playlists.iterator(); - while(it.hasNext()) { + while (it.hasNext()) { Playlist playlist = it.next(); - if(playlist.getPublic() == true && playlist.getId().indexOf(".m3u") == -1 && !UserUtil.getCurrentUsername(context).equals(playlist.getOwner())) { + if (playlist.getPublic() && !playlist.getId().contains(".m3u") && !UserUtil.getCurrentUsername(context).equals(playlist.getOwner())) { it.remove(); } } @@ -926,10 +877,10 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR // Create new if not getting a convert view to use PlaylistSongView view; - if(convertView instanceof PlaylistSongView) { + if (convertView instanceof PlaylistSongView) { view = (PlaylistSongView) convertView; } else { - view = new PlaylistSongView(context); + view = new PlaylistSongView(context); } view.setObject(playlist, songs); @@ -940,13 +891,11 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.playlist_add_to) - .setAdapter(playlistAdapter, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - if (which > 0) { - addToPlaylist(playlists.get(which), songs); - } else { - createNewPlaylist(songs, false); - } + .setAdapter(playlistAdapter, (dialog, which) -> { + if (which > 0) { + addToPlaylist(playlists.get(which), songs); + } else { + createNewPlaylist(songs, false); } }); AlertDialog dialog = builder.create(); @@ -995,20 +944,20 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR }.execute(); } - protected void createNewPlaylist(final List songs, final boolean getSuggestion) { + void createNewPlaylist(final List songs, final boolean getSuggestion) { View layout = context.getLayoutInflater().inflate(R.layout.save_playlist, null); - final EditText playlistNameView = (EditText) layout.findViewById(R.id.save_playlist_name); - final CheckBox overwriteCheckBox = (CheckBox) layout.findViewById(R.id.save_playlist_overwrite); - if(getSuggestion) { + final EditText playlistNameView = layout.findViewById(R.id.save_playlist_name); + final CheckBox overwriteCheckBox = layout.findViewById(R.id.save_playlist_overwrite); + if (getSuggestion) { String playlistName = (getDownloadService() != null) ? getDownloadService().getSuggestedPlaylistName() : null; if (playlistName != null) { playlistNameView.setText(playlistName); try { - if(Integer.parseInt(getDownloadService().getSuggestedPlaylistId()) != -1) { + if (Integer.parseInt(getDownloadService().getSuggestedPlaylistId()) != -1) { overwriteCheckBox.setChecked(true); overwriteCheckBox.setVisibility(View.VISIBLE); } - } catch(Exception e) { + } catch (Exception e) { Log.i(TAG, "Playlist id isn't a integer, probably MusicCabinet"); } } else { @@ -1016,42 +965,36 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR playlistNameView.setText(dateFormat.format(new Date())); } } else { - DateFormat dateFormat = DateFormat.getDateInstance(); playlistNameView.setText(dateFormat.format(new Date())); + DateFormat dateFormat = DateFormat.getDateInstance(); + playlistNameView.setText(dateFormat.format(new Date())); } AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.download_playlist_title) .setMessage(R.string.download_playlist_name) .setView(layout) - .setPositiveButton(R.string.common_save, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - String playlistName = String.valueOf(playlistNameView.getText()); - if(overwriteCheckBox.isChecked()) { - overwritePlaylist(songs, playlistName, getDownloadService().getSuggestedPlaylistId()); - } else { - createNewPlaylist(songs, playlistName); + .setPositiveButton(R.string.common_save, (dialog, id) -> { + String playlistName = String.valueOf(playlistNameView.getText()); + if (overwriteCheckBox.isChecked()) { + overwritePlaylist(songs, playlistName, getDownloadService().getSuggestedPlaylistId()); + } else { + createNewPlaylist(songs, playlistName); - if(getSuggestion) { - DownloadService downloadService = getDownloadService(); - if(downloadService != null) { - downloadService.setSuggestedPlaylistName(playlistName, null); - } + if (getSuggestion) { + DownloadService downloadService = getDownloadService(); + if (downloadService != null) { + downloadService.setSuggestedPlaylistName(playlistName, null); } } } }) - .setNegativeButton(R.string.common_cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - } - }) + .setNegativeButton(R.string.common_cancel, (dialog, id) -> dialog.cancel()) .setCancelable(true); AlertDialog dialog = builder.create(); dialog.show(); } + private void createNewPlaylist(final List songs, final String name) { new SilentBackgroundTask(context) { @Override @@ -1073,6 +1016,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } }.execute(); } + private void overwritePlaylist(final List songs, final String name, final String id) { new SilentBackgroundTask(context) { @Override @@ -1103,16 +1047,16 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR }.execute(); } - public void displaySongInfo(final Entry song) { + void displaySongInfo(final Entry song) { Integer duration = null; Integer bitrate = null; String format = null; long size = 0; - if(!song.isDirectory()) { + if (!song.isDirectory()) { try { DownloadFile downloadFile = new DownloadFile(context, song, false); File file = downloadFile.getCompleteFile(); - if(file.exists()) { + if (file.exists()) { MediaMetadataRetriever metadata = new MediaMetadataRetriever(); metadata.setDataSource(file.getAbsolutePath()); @@ -1122,7 +1066,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR size = file.length(); // If no duration try to read bitrate tag - if(duration == null) { + if (duration == null) { tmp = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE); bitrate = Integer.parseInt((tmp != null) ? tmp : "0") / 1000; } else { @@ -1131,88 +1075,88 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR bitrate = (int) (size / duration) / 1000 * 8; } - if(Util.isOffline(context)) { + if (Util.isOffline(context)) { song.setGenre(metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE)); String year = metadata.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR); song.setYear(Integer.parseInt((year != null) ? year : "0")); } } - } catch(Exception e) { + } catch (Exception e) { Log.i(TAG, "Device doesn't properly support MediaMetadataRetreiver"); } } - if(duration == null) { + if (duration == null) { duration = song.getDuration(); } List headers = new ArrayList<>(); List details = new ArrayList<>(); - if(!song.isDirectory()) { + if (!song.isDirectory()) { headers.add(R.string.details_title); details.add(song.getTitle()); } - if(song.getArtist() != null && !"".equals(song.getArtist())) { + if (song.getArtist() != null && !"".equals(song.getArtist())) { headers.add(R.string.details_artist); details.add(song.getArtist()); } - if(song.getAlbum() != null && !"".equals(song.getAlbum())) { + if (song.getAlbum() != null && !"".equals(song.getAlbum())) { headers.add(R.string.details_album); details.add(song.getAlbum()); } - if(song.getTrack() != null && song.getTrack() != 0) { + if (song.getTrack() != null && song.getTrack() != 0) { headers.add(R.string.details_track); details.add(Integer.toString(song.getTrack())); } - if(song.getGenre() != null && !"".equals(song.getGenre())) { + if (song.getGenre() != null && !"".equals(song.getGenre())) { headers.add(R.string.details_genre); details.add(song.getGenre()); } - if(song.getYear() != null && song.getYear() != 0) { + if (song.getYear() != null && song.getYear() != 0) { headers.add(R.string.details_year); details.add(Integer.toString(song.getYear())); } - if(!Util.isOffline(context) && song.getSuffix() != null) { + if (!Util.isOffline(context) && song.getSuffix() != null) { headers.add(R.string.details_server_format); details.add(song.getSuffix()); - if(song.getBitRate() != null && song.getBitRate() != 0) { + if (song.getBitRate() != null && song.getBitRate() != 0) { headers.add(R.string.details_server_bitrate); details.add(song.getBitRate() + " kbps"); } } - if(format != null && !"".equals(format)) { + if (format != null && !"".equals(format)) { headers.add(R.string.details_cached_format); details.add(format); } - if(bitrate != null && bitrate != 0) { + if (bitrate != null && bitrate != 0) { headers.add(R.string.details_cached_bitrate); details.add(bitrate + " kbps"); } - if(size != 0) { + if (size != 0) { headers.add(R.string.details_size); details.add(Util.formatLocalizedBytes(size, context)); } - if(duration != null && duration != 0) { + if (duration != null && duration != 0) { headers.add(R.string.details_length); details.add(Util.formatDuration(duration)); } try { Long[] dates = SongDBHandler.getHandler(context).getLastPlayed(song); - if(dates != null && dates[0] != null && dates[0] > 0) { + if (dates != null && dates[0] != null && dates[0] > 0) { headers.add(R.string.details_last_played); Date date = new Date((dates[1] != null && dates[1] > dates[0]) ? dates[1] : dates[0]); DateFormat dateFormat = DateFormat.getDateInstance(); details.add(dateFormat.format(date)); } - } catch(Exception e) { + } catch (Exception e) { Log.e(TAG, "Failed to get last played", e); } int title; - if(song.isDirectory()) { + if (song.isDirectory()) { title = R.string.details_title_album; } else { title = R.string.details_title_song; @@ -1221,21 +1165,16 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } - protected boolean entryExists(Entry entry) { - DownloadFile check = new DownloadFile(context, entry, false); - return check.isCompleteFileAvailable(); - } - - public void deleteRecursively(Artist artist) { + private void deleteRecursively(Artist artist) { deleteRecursively(artist, FileUtil.getArtistDirectory(context, artist)); } - public void deleteRecursively(Entry album) { + void deleteRecursively(Entry album) { deleteRecursively(album, FileUtil.getAlbumDirectory(context, album)); } - public void deleteRecursively(final Object remove, final File dir) { - if(dir == null) { + private void deleteRecursively(final Object remove, final File dir) { + if (dir == null) { return; } @@ -1249,9 +1188,9 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR @Override protected void done(Void result) { - if(Util.isOffline(context)) { + if (Util.isOffline(context)) { SectionAdapter adapter = getCurrentAdapter(); - if(adapter != null) { + if (adapter != null) { adapter.removeItem(remove); } else { refresh(); @@ -1262,7 +1201,8 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } }.execute(); } - public void deleteSongs(final List songs) { + + private void deleteSongs(final List songs) { new LoadingTask(context) { @Override protected Void doInBackground() throws Throwable { @@ -1272,10 +1212,10 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR @Override protected void done(Void result) { - if(Util.isOffline(context)) { + if (Util.isOffline(context)) { SectionAdapter adapter = getCurrentAdapter(); - if(adapter != null) { - for(Entry song: songs) { + if (adapter != null) { + for (Entry song : songs) { adapter.removeItem(song); } } else { @@ -1288,88 +1228,72 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR }.execute(); } - public void showAlbumArtist(Entry entry) { + private void showAlbumArtist(Entry entry) { SubsonicFragment fragment = new SelectDirectoryFragment(); Bundle args = new Bundle(); - if(Util.isTagBrowsing(context)) { - args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getArtistId()); - } else { - args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getParent()); - } + args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getArtistId()); args.putString(Constants.INTENT_EXTRA_NAME_NAME, entry.getArtist()); args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true); fragment.setArguments(args); - replaceFragment(fragment, true); + replaceFragment(fragment); } - public void showArtist(Entry entry) { + + private void showArtist(Entry entry) { SubsonicFragment fragment = new SelectDirectoryFragment(); Bundle args = new Bundle(); - if(Util.isTagBrowsing(context)) { - args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getArtistId()); - } else { - if(entry.getGrandParent() == null) { - args.putString(Constants.INTENT_EXTRA_NAME_CHILD_ID, entry.getParent()); - } else { - args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getGrandParent()); - } - } + args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getArtistId()); args.putString(Constants.INTENT_EXTRA_NAME_NAME, entry.getArtist()); args.putBoolean(Constants.INTENT_EXTRA_NAME_ARTIST, true); fragment.setArguments(args); - replaceFragment(fragment, true); + replaceFragment(fragment); } - public void showAlbum(Entry entry) { + private void showAlbum(Entry entry) { SubsonicFragment fragment = new SelectDirectoryFragment(); Bundle args = new Bundle(); - if(Util.isTagBrowsing(context)) { - args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getAlbumId()); - } else { - args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getParent()); - } + args.putString(Constants.INTENT_EXTRA_NAME_ID, entry.getAlbumId()); args.putString(Constants.INTENT_EXTRA_NAME_NAME, entry.getAlbum()); fragment.setArguments(args); - replaceFragment(fragment, true); + replaceFragment(fragment); } public GestureDetector getGestureDetector() { return gestureScanner; } - protected void onSongPress(List entries, Entry entry) { - onSongPress(entries, entry, 0, true); + void onSongPress(List entries, Entry entry) { + onSongPress(entries, entry, true); } - protected void onSongPress(List entries, Entry entry, boolean allowPlayAll) { - onSongPress(entries, entry, 0, allowPlayAll); - } - protected void onSongPress(List entries, Entry entry, int position, boolean allowPlayAll) { - List songs = new ArrayList(); + + void onSongPress(List entries, Entry entry, boolean allowPlayAll) { + List songs = new ArrayList<>(); String songPressAction = Util.getSongPressAction(context); - if("all".equals(songPressAction) && allowPlayAll) { - for(Entry song: entries) { - if(!song.isDirectory()) { + if ("all".equals(songPressAction) && allowPlayAll) { + for (Entry song : entries) { + if (!song.isDirectory()) { songs.add(song); } } - playNow(songs, entry, position); - } else if("next".equals(songPressAction)) { - getDownloadService().download(Arrays.asList(entry), false, false, true, false); - } else if("last".equals(songPressAction)) { - getDownloadService().download(Arrays.asList(entry), false, false, false, false); + playNow(songs, entry); + } else if ("next".equals(songPressAction)) { + getDownloadService().download(Collections.singletonList(entry), false, false, true, false); + } else if ("last".equals(songPressAction)) { + getDownloadService().download(Collections.singletonList(entry), false, false, false, false); } else { songs.add(entry); playNow(songs); } } - protected void playNow(List entries) { + private void playNow(List entries) { playNow(entries, null, null); } - protected void playNow(final List entries, final String playlistName, final String playlistId) { + + private void playNow(final List entries, final String playlistName, final String playlistId) { new RecursiveLoader(context) { @Override protected Boolean doInBackground() throws Throwable { @@ -1379,27 +1303,21 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR @Override protected void done(Boolean result) { - playNow(songs, 0, playlistName, playlistId); + Entry selected = songs.isEmpty() ? null : songs.get(0); + playNow(songs, selected, playlistName, playlistId); } }.execute(); } - protected void playNow(List entries, int position) { - playNow(entries, position, null, null); - } - protected void playNow(List entries, int position, String playlistName, String playlistId) { - Entry selected = entries.isEmpty() ? null : entries.get(0); - playNow(entries, selected, position, playlistName, playlistId); + + private void playNow(List entries, Entry song) { + playNow(entries, song, null, null); } - protected void playNow(List entries, Entry song, int position) { - playNow(entries, song, position, null, null); - } - - protected void playNow(final List entries, final Entry song, final int position, final String playlistName, final String playlistId) { + private void playNow(final List entries, final Entry song, final String playlistName, final String playlistId) { new LoadingTask(context) { @Override protected Void doInBackground() throws Throwable { - playNowInTask(entries, song, position, playlistName, playlistId); + playNowInTask(entries, song, playlistName, playlistId); return null; } @@ -1409,51 +1327,56 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } }.execute(); } - protected void playNowInTask(final List entries, final Entry song, final int position) { - playNowInTask(entries, song, position, null, null); - } - protected void playNowInTask(final List entries, final Entry song, final int position, final String playlistName, final String playlistId) { + + private void playNowInTask(final List entries, final Entry song, final String playlistName, final String playlistId) { DownloadService downloadService = getDownloadService(); - if(downloadService == null) { + if (downloadService == null) { return; } downloadService.clear(); - downloadService.download(entries, false, true, true, false, entries.indexOf(song), position); + downloadService.download(entries, false, true, true, false, entries.indexOf(song)); downloadService.setSuggestedPlaylistName(playlistName, playlistId); } - public SectionAdapter getCurrentAdapter() { return null; } + public SectionAdapter getCurrentAdapter() { + return null; + } + public void stopActionMode() { SectionAdapter adapter = getCurrentAdapter(); - if(adapter != null) { + if (adapter != null) { adapter.stopActionMode(); } } - protected void clearSelected() { - if(getCurrentAdapter() != null) { + + private void clearSelected() { + if (getCurrentAdapter() != null) { getCurrentAdapter().clearSelected(); } } - protected List getSelectedEntries() { + + List getSelectedEntries() { return getCurrentAdapter().getSelected(); } - protected void playNow(final boolean shuffle, final boolean append) { + private void playNow(final boolean shuffle, final boolean append) { playNow(shuffle, append, false); } - protected void playNow(final boolean shuffle, final boolean append, final boolean playNext) { + + void playNow(final boolean shuffle, final boolean append, final boolean playNext) { List songs = getSelectedEntries(); - if(!songs.isEmpty()) { - download(songs, append, false, !append, playNext, shuffle); + if (!songs.isEmpty()) { + download(songs, append, !append, playNext, shuffle); clearSelected(); } } - protected void download(List entries, boolean append, boolean save, boolean autoplay, boolean playNext, boolean shuffle) { - download(entries, append, save, autoplay, playNext, shuffle, null, null); + void download(List entries, boolean append, boolean autoplay, boolean playNext, boolean shuffle) { + download(entries, append, autoplay, playNext, shuffle, null, null); } - protected void download(final List entries, final boolean append, final boolean save, final boolean autoplay, final boolean playNext, final boolean shuffle, final String playlistName, final String playlistId) { + + void download(final List entries, final boolean append, final boolean autoplay, final boolean playNext, final boolean shuffle, final String playlistName, final String playlistId) { final DownloadService downloadService = getDownloadService(); if (downloadService == null) { return; @@ -1461,7 +1384,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR warnIfStorageUnavailable(); // Conditions for using play now button - if(!append && !save && autoplay && !playNext && !shuffle) { + if (!append && autoplay && !playNext && !shuffle) { // Call playNow which goes through and tries to use information playNow(entries, playlistName, playlistId); return; @@ -1475,7 +1398,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR } getSongsRecursively(entries, songs); - downloadService.download(songs, save, autoplay, playNext, shuffle); + downloadService.download(songs, false, autoplay, playNext, shuffle); if (playlistName != null) { downloadService.setSuggestedPlaylistName(playlistName, playlistId); } else { @@ -1488,9 +1411,6 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR protected void done(Boolean result) { if (autoplay) { context.openNowPlaying(); - } else if (save) { - Util.toast(context, - context.getResources().getQuantityString(R.plurals.select_album_n_songs_downloading, songs.size(), songs.size())); } else if (append) { Util.toast(context, context.getResources().getQuantityString(R.plurals.select_album_n_songs_added, songs.size(), songs.size())); @@ -1500,17 +1420,19 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR executeOnValid(onValid); } - protected void executeOnValid(RecursiveLoader onValid) { + + private void executeOnValid(RecursiveLoader onValid) { onValid.execute(); } - protected void downloadBackground(final boolean save) { + + void downloadBackground(final boolean save) { List songs = getSelectedEntries(); - if(!songs.isEmpty()) { + if (!songs.isEmpty()) { downloadBackground(save, songs); } } - protected void downloadBackground(final boolean save, final List entries) { + void downloadBackground(final boolean save, final List entries) { if (getDownloadService() == null) { return; } @@ -1519,7 +1441,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR new RecursiveLoader(context) { @Override protected Boolean doInBackground() throws Throwable { - getSongsRecursively(entries, true); + getSongsRecursively(entries); getDownloadService().downloadBackground(songs, save); return null; } @@ -1531,78 +1453,53 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR }.execute(); } - protected void delete() { + void delete() { List songs = getSelectedEntries(); - if(!songs.isEmpty()) { + if (!songs.isEmpty()) { DownloadService downloadService = getDownloadService(); - if(downloadService != null) { + if (downloadService != null) { downloadService.delete(songs); } } } - protected boolean isShowArtistEnabled() { + boolean isShowArtistEnabled() { return false; } - protected String getCurrentQuery() { + String getCurrentQuery() { return null; } public abstract class RecursiveLoader extends LoadingTask { - protected MusicService musicService; - protected static final int MAX_SONGS = 500; - protected boolean playNowOverride = false; - protected List songs = new ArrayList<>(); + static final int MAX_SONGS = 500; + MusicService musicService; + boolean playNowOverride = false; + List songs = new ArrayList<>(); public RecursiveLoader(Activity context) { super(context); musicService = MusicServiceFactory.getMusicService(context); } - protected void getSiblingsRecursively(Entry entry) throws Exception { - MusicDirectory parent = new MusicDirectory(); - if(Util.isTagBrowsing(context) && !Util.isOffline(context)) { - parent.setId(entry.getAlbumId()); - } else { - parent.setId(entry.getParent()); - } + void getSongsRecursively(List entry) throws Exception { + getSongsRecursively(entry, songs); + } - if(parent.getId() == null) { - songs.add(entry); - } else { - MusicDirectory.Entry dir = new Entry(parent.getId()); - dir.setDirectory(true); - parent.addChild(dir); - getSongsRecursively(parent, songs); - } - } - protected void getSongsRecursively(List entry) throws Exception { - getSongsRecursively(entry, false); - } - protected void getSongsRecursively(List entry, boolean allowVideo) throws Exception { - getSongsRecursively(entry, songs, allowVideo); - } - protected void getSongsRecursively(List entry, List songs) throws Exception { - getSongsRecursively(entry, songs, false); - } - protected void getSongsRecursively(List entry, List songs, boolean allowVideo) throws Exception { + void getSongsRecursively(List entry, List songs) throws Exception { MusicDirectory dir = new MusicDirectory(); dir.addChildren(entry); - getSongsRecursively(dir, songs, allowVideo); + getSongsRecursively(dir, songs); } - protected void getSongsRecursively(MusicDirectory parent, List songs) throws Exception { - getSongsRecursively(parent, songs, false); - } - protected void getSongsRecursively(MusicDirectory parent, List songs, boolean allowVideo) throws Exception { + void getSongsRecursively(MusicDirectory parent, List songs) throws Exception { if (songs.size() > MAX_SONGS) { return; } for (Entry dir : parent.getChildren(true, false)) { MusicDirectory musicDirectory; - if(Util.isTagBrowsing(context) && !Util.isOffline(context)) { + if (!Util.isOffline(context)) { musicDirectory = musicService.getAlbum(dir.getId(), dir.getTitle(), false, context, this); } else { musicDirectory = musicService.getMusicDirectory(dir.getId(), dir.getTitle(), false, context, this); @@ -1610,21 +1507,19 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR getSongsRecursively(musicDirectory, songs); } - for (Entry song : parent.getChildren(false, true)) { - songs.add(song); - } + songs.addAll(parent.getChildren(false, true)); } @Override protected void done(Boolean result) { warnIfStorageUnavailable(); - if(playNowOverride) { + if (playNowOverride) { playNow(songs); return; } - if(result) { + if (result) { context.openNowPlaying(); } } diff --git a/app/src/main/java/net/nullsum/audinaut/provider/AudinautSearchProvider.java b/app/src/main/java/net/nullsum/audinaut/provider/AudinautSearchProvider.java index d15dbad..a088207 100644 --- a/app/src/main/java/net/nullsum/audinaut/provider/AudinautSearchProvider.java +++ b/app/src/main/java/net/nullsum/audinaut/provider/AudinautSearchProvider.java @@ -24,12 +24,6 @@ import android.content.ContentValues; import android.database.Cursor; import android.database.MatrixCursor; import android.net.Uri; -import android.util.Log; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; import net.nullsum.audinaut.R; import net.nullsum.audinaut.domain.Artist; @@ -40,13 +34,16 @@ import net.nullsum.audinaut.service.MusicService; import net.nullsum.audinaut.service.MusicServiceFactory; import net.nullsum.audinaut.util.Util; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + /** * Provides search suggestions based on recent searches. * * @author Sindre Mehus */ public class AudinautSearchProvider extends ContentProvider { - private static final String TAG = AudinautSearchProvider.class.getSimpleName(); private static final String RESOURCE_PREFIX = "android.resource://net.nullsum.audinaut/"; private static final String[] COLUMNS = {"_id", @@ -58,7 +55,7 @@ public class AudinautSearchProvider extends ContentProvider { @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { - if(selectionArgs[0].isEmpty()) { + if (selectionArgs[0].isEmpty()) { return null; } @@ -87,14 +84,14 @@ public class AudinautSearchProvider extends ContentProvider { } // Add all results into one pot - List results = new ArrayList(); + List results = new ArrayList<>(); results.addAll(searchResult.getArtists()); results.addAll(searchResult.getAlbums()); results.addAll(searchResult.getSongs()); // For each, calculate its string distance to the query - for(Object obj: results) { - if(obj instanceof Artist) { + for (Object obj : results) { + if (obj instanceof Artist) { Artist artist = (Artist) obj; artist.setCloseness(Util.getStringDistance(query, artist.getName())); } else { @@ -104,71 +101,64 @@ public class AudinautSearchProvider extends ContentProvider { } // Sort based on the closeness paramater - Collections.sort(results, new Comparator() { - @Override - public int compare(Object lhs, Object rhs) { - // Get the closeness of the two objects - int left, right; - boolean leftArtist = lhs instanceof Artist; - boolean rightArtist = rhs instanceof Artist; - if (leftArtist) { - left = ((Artist) lhs).getCloseness(); - } else { - left = ((MusicDirectory.Entry) lhs).getCloseness(); - } - if (rightArtist) { - right = ((Artist) rhs).getCloseness(); - } else { - right = ((MusicDirectory.Entry) rhs).getCloseness(); - } + Collections.sort(results, (lhs, rhs) -> { + // Get the closeness of the two objects + int left, right; + boolean leftArtist = lhs instanceof Artist; + boolean rightArtist = rhs instanceof Artist; + if (leftArtist) { + left = ((Artist) lhs).getCloseness(); + } else { + left = ((MusicDirectory.Entry) lhs).getCloseness(); + } + if (rightArtist) { + right = ((Artist) rhs).getCloseness(); + } else { + right = ((MusicDirectory.Entry) rhs).getCloseness(); + } - if (left == right) { - if(leftArtist && rightArtist) { - return 0; - } else if(leftArtist) { - return -1; - } else if(rightArtist) { - return 1; - } else { - return 0; - } - } else if (left > right) { + if (left == right) { + if (leftArtist && rightArtist) { + return 0; + } else if (leftArtist) { + return -1; + } else if (rightArtist) { return 1; } else { - return -1; + return 0; } + } else if (left > right) { + return 1; + } else { + return -1; } }); // Done sorting, add results to cursor - for(Object obj: results) { - if(obj instanceof Artist) { + for (Object obj : results) { + if (obj instanceof Artist) { Artist artist = (Artist) obj; String icon = RESOURCE_PREFIX + R.drawable.ic_action_artist; cursor.addRow(new Object[]{artist.getId().hashCode(), artist.getName(), null, "ar-" + artist.getId(), artist.getName(), icon}); } else { MusicDirectory.Entry entry = (MusicDirectory.Entry) obj; - if(entry.isDirectory()) { + if (entry.isDirectory()) { String icon = RESOURCE_PREFIX + R.drawable.ic_action_album; cursor.addRow(new Object[]{entry.getId().hashCode(), entry.getTitle(), entry.getArtist(), entry.getId(), entry.getTitle(), icon}); } else { String icon = RESOURCE_PREFIX + R.drawable.ic_action_song; String id; - if(Util.isTagBrowsing(getContext())) { - id = entry.getAlbumId(); - } else { - id = entry.getParent(); - } + id = entry.getAlbumId(); String artistDisplay; - if(entry.getArtist() == null) { - if(entry.getAlbum() != null) { + if (entry.getArtist() == null) { + if (entry.getAlbum() != null) { artistDisplay = entry.getAlbumDisplay(); } else { artistDisplay = ""; } - } else if(entry.getAlbum() != null) { + } else if (entry.getAlbum() != null) { artistDisplay = entry.getArtist() + " - " + entry.getAlbumDisplay(); } else { artistDisplay = entry.getArtist(); diff --git a/app/src/main/java/net/nullsum/audinaut/provider/AudinautWidgetProvider.java b/app/src/main/java/net/nullsum/audinaut/provider/AudinautWidgetProvider.java index 90a666f..f1df0bb 100644 --- a/app/src/main/java/net/nullsum/audinaut/provider/AudinautWidgetProvider.java +++ b/app/src/main/java/net/nullsum/audinaut/provider/AudinautWidgetProvider.java @@ -24,8 +24,8 @@ import android.appwidget.AppWidgetProvider; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.res.Resources; import android.content.SharedPreferences; +import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; @@ -38,6 +38,7 @@ import android.os.Environment; import android.util.Log; import android.view.View; import android.widget.RemoteViews; + import net.nullsum.audinaut.R; import net.nullsum.audinaut.activity.SubsonicActivity; import net.nullsum.audinaut.activity.SubsonicFragmentActivity; @@ -66,16 +67,16 @@ public class AudinautWidgetProvider extends AppWidgetProvider { private static AudinautWidget4x4 instance4x4; public static synchronized void notifyInstances(Context context, DownloadService service, boolean playing) { - if(instance4x1 == null) { + if (instance4x1 == null) { instance4x1 = new AudinautWidget4x1(); } - if(instance4x2 == null) { + if (instance4x2 == null) { instance4x2 = new AudinautWidget4x2(); } - if(instance4x3 == null) { + if (instance4x3 == null) { instance4x3 = new AudinautWidget4x3(); } - if(instance4x4 == null) { + if (instance4x4 == null) { instance4x4 = new AudinautWidget4x4(); } @@ -85,165 +86,6 @@ public class AudinautWidgetProvider extends AppWidgetProvider { instance4x4.notifyChange(context, service, playing); } - @Override - public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { - defaultAppWidget(context, appWidgetIds); - } - - @Override - public void onEnabled(Context context) { - notifyInstances(context, DownloadService.getInstance(), false); - } - - protected int getLayout() { - return 0; - } - - /** - * Initialize given widgets to default state, where we launch Subsonic on default click - * and hide actions if service not running. - */ - private void defaultAppWidget(Context context, int[] appWidgetIds) { - final Resources res = context.getResources(); - final RemoteViews views = new RemoteViews(context.getPackageName(), getLayout()); - - views.setTextViewText(R.id.artist, res.getText(R.string.widget_initial_text)); - if(getLayout() == R.layout.appwidget4x2) { - views.setTextViewText(R.id.album, ""); - } - - linkButtons(context, views, false); - performUpdate(context, null, appWidgetIds, false); - } - - private void pushUpdate(Context context, int[] appWidgetIds, RemoteViews views) { - // Update specific list of appWidgetIds if given, otherwise default to all - final AppWidgetManager manager = AppWidgetManager.getInstance(context); - if (appWidgetIds != null) { - manager.updateAppWidget(appWidgetIds, views); - } else { - manager.updateAppWidget(new ComponentName(context, this.getClass()), views); - } - } - - /** - * Handle a change notification coming over from {@link DownloadService} - */ - public void notifyChange(Context context, DownloadService service, boolean playing) { - if (hasInstances(context)) { - performUpdate(context, service, null, playing); - } - } - - /** - * Check against {@link AppWidgetManager} if there are any instances of this widget. - */ - private boolean hasInstances(Context context) { - AppWidgetManager manager = AppWidgetManager.getInstance(context); - int[] appWidgetIds = manager.getAppWidgetIds(new ComponentName(context, getClass())); - return (appWidgetIds.length > 0); - } - - /** - * Update all active widget instances by pushing changes - */ - private void performUpdate(Context context, DownloadService service, int[] appWidgetIds, boolean playing) { - final Resources res = context.getResources(); - final RemoteViews views = new RemoteViews(context.getPackageName(), getLayout()); - - if(playing) { - views.setViewVisibility(R.id.widget_root, View.VISIBLE); - } else { - // Hide widget - SharedPreferences prefs = Util.getPreferences(context); - if(prefs.getBoolean(Constants.PREFERENCES_KEY_HIDE_WIDGET, false)) { - views.setViewVisibility(R.id.widget_root, View.GONE); - } - } - - // Get Entry from current playing DownloadFile - MusicDirectory.Entry currentPlaying = null; - if(service == null) { - // Deserialize from playling list to setup - try { - PlayerQueue state = FileUtil.deserialize(context, DownloadServiceLifecycleSupport.FILENAME_DOWNLOADS_SER, PlayerQueue.class); - if (state != null && state.currentPlayingIndex != -1) { - currentPlaying = state.songs.get(state.currentPlayingIndex); - } - } catch(Exception e) { - Log.e(TAG, "Failed to grab current playing", e); - } - } else { - currentPlaying = service.getCurrentPlaying() == null ? null : service.getCurrentPlaying().getSong(); - } - - String title = currentPlaying == null ? null : currentPlaying.getTitle(); - CharSequence artist = currentPlaying == null ? null : currentPlaying.getArtist(); - CharSequence album = currentPlaying == null ? null : currentPlaying.getAlbum(); - CharSequence errorState = null; - - // Show error message? - String status = Environment.getExternalStorageState(); - if (status.equals(Environment.MEDIA_SHARED) || - status.equals(Environment.MEDIA_UNMOUNTED)) { - errorState = res.getText(R.string.widget_sdcard_busy); - } else if (status.equals(Environment.MEDIA_REMOVED)) { - errorState = res.getText(R.string.widget_sdcard_missing); - } else if (currentPlaying == null) { - errorState = res.getText(R.string.widget_initial_text); - } - - if (errorState != null) { - // Show error state to user - views.setTextViewText(R.id.title,null); - views.setTextViewText(R.id.artist, errorState); - views.setTextViewText(R.id.album, ""); - if(getLayout() != R.layout.appwidget4x1) { - views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_default); - } - } else { - // No error, so show normal titles - views.setTextViewText(R.id.title, title); - views.setTextViewText(R.id.artist, artist); - if(getLayout() != R.layout.appwidget4x1) { - views.setTextViewText(R.id.album, album); - } - } - - // Set correct drawable for pause state - if (playing) { - views.setImageViewResource(R.id.control_play, R.drawable.media_pause_dark); - } else { - views.setImageViewResource(R.id.control_play, R.drawable.media_start_dark); - } - - // Set the cover art - try { - boolean large = false; - if(getLayout() != R.layout.appwidget4x1 && getLayout() != R.layout.appwidget4x2) { - large = true; - } - ImageLoader imageLoader = SubsonicActivity.getStaticImageLoader(context); - Bitmap bitmap = imageLoader == null ? null : imageLoader.getCachedImage(context, currentPlaying, large); - - if (bitmap == null) { - // Set default cover art - views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_unknown); - } else { - bitmap = getRoundedCornerBitmap(bitmap); - views.setImageViewBitmap(R.id.appwidget_coverart, bitmap); - } - } catch (Exception x) { - Log.e(TAG, "Failed to load cover art", x); - views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_unknown); - } - - // Link actions buttons to intents - linkButtons(context, views, currentPlaying != null); - - pushUpdate(context, appWidgetIds, views); - } - /** * Round the corners of a bitmap for the cover art image */ @@ -270,12 +112,169 @@ public class AudinautWidgetProvider extends AppWidgetProvider { return output; } + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + defaultAppWidget(context, appWidgetIds); + } + + @Override + public void onEnabled(Context context) { + notifyInstances(context, DownloadService.getInstance(), false); + } + + int getLayout() { + return 0; + } + + /** + * Initialize given widgets to default state, where we launch Subsonic on default click + * and hide actions if service not running. + */ + private void defaultAppWidget(Context context, int[] appWidgetIds) { + final Resources res = context.getResources(); + final RemoteViews views = new RemoteViews(context.getPackageName(), getLayout()); + + views.setTextViewText(R.id.artist, res.getText(R.string.widget_initial_text)); + if (getLayout() == R.layout.appwidget4x2) { + views.setTextViewText(R.id.album, ""); + } + + linkButtons(context, views); + performUpdate(context, null, appWidgetIds, false); + } + + private void pushUpdate(Context context, int[] appWidgetIds, RemoteViews views) { + // Update specific list of appWidgetIds if given, otherwise default to all + final AppWidgetManager manager = AppWidgetManager.getInstance(context); + if (appWidgetIds != null) { + manager.updateAppWidget(appWidgetIds, views); + } else { + manager.updateAppWidget(new ComponentName(context, this.getClass()), views); + } + } + + /** + * Handle a change notification coming over from {@link DownloadService} + */ + void notifyChange(Context context, DownloadService service, boolean playing) { + if (hasInstances(context)) { + performUpdate(context, service, null, playing); + } + } + + /** + * Check against {@link AppWidgetManager} if there are any instances of this widget. + */ + private boolean hasInstances(Context context) { + AppWidgetManager manager = AppWidgetManager.getInstance(context); + int[] appWidgetIds = manager.getAppWidgetIds(new ComponentName(context, getClass())); + return (appWidgetIds.length > 0); + } + + /** + * Update all active widget instances by pushing changes + */ + private void performUpdate(Context context, DownloadService service, int[] appWidgetIds, boolean playing) { + final Resources res = context.getResources(); + final RemoteViews views = new RemoteViews(context.getPackageName(), getLayout()); + + if (playing) { + views.setViewVisibility(R.id.widget_root, View.VISIBLE); + } else { + // Hide widget + SharedPreferences prefs = Util.getPreferences(context); + if (prefs.getBoolean(Constants.PREFERENCES_KEY_HIDE_WIDGET, false)) { + views.setViewVisibility(R.id.widget_root, View.GONE); + } + } + + // Get Entry from current playing DownloadFile + MusicDirectory.Entry currentPlaying = null; + if (service == null) { + // Deserialize from playling list to setup + try { + PlayerQueue state = FileUtil.deserialize(context, DownloadServiceLifecycleSupport.FILENAME_DOWNLOADS_SER, PlayerQueue.class); + if (state != null && state.currentPlayingIndex != -1) { + currentPlaying = state.songs.get(state.currentPlayingIndex); + } + } catch (Exception e) { + Log.e(TAG, "Failed to grab current playing", e); + } + } else { + currentPlaying = service.getCurrentPlaying() == null ? null : service.getCurrentPlaying().getSong(); + } + + String title = currentPlaying == null ? null : currentPlaying.getTitle(); + CharSequence artist = currentPlaying == null ? null : currentPlaying.getArtist(); + CharSequence album = currentPlaying == null ? null : currentPlaying.getAlbum(); + CharSequence errorState = null; + + // Show error message? + String status = Environment.getExternalStorageState(); + if (status.equals(Environment.MEDIA_SHARED) || + status.equals(Environment.MEDIA_UNMOUNTED)) { + errorState = res.getText(R.string.widget_sdcard_busy); + } else if (status.equals(Environment.MEDIA_REMOVED)) { + errorState = res.getText(R.string.widget_sdcard_missing); + } else if (currentPlaying == null) { + errorState = res.getText(R.string.widget_initial_text); + } + + if (errorState != null) { + // Show error state to user + views.setTextViewText(R.id.title, null); + views.setTextViewText(R.id.artist, errorState); + views.setTextViewText(R.id.album, ""); + if (getLayout() != R.layout.appwidget4x1) { + views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_default); + } + } else { + // No error, so show normal titles + views.setTextViewText(R.id.title, title); + views.setTextViewText(R.id.artist, artist); + if (getLayout() != R.layout.appwidget4x1) { + views.setTextViewText(R.id.album, album); + } + } + + // Set correct drawable for pause state + if (playing) { + views.setImageViewResource(R.id.control_play, R.drawable.media_pause_dark); + } else { + views.setImageViewResource(R.id.control_play, R.drawable.media_start_dark); + } + + // Set the cover art + try { + boolean large = false; + if (getLayout() != R.layout.appwidget4x1 && getLayout() != R.layout.appwidget4x2) { + large = true; + } + ImageLoader imageLoader = SubsonicActivity.getStaticImageLoader(context); + Bitmap bitmap = imageLoader == null ? null : imageLoader.getCachedImage(context, currentPlaying, large); + + if (bitmap == null) { + // Set default cover art + views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_unknown); + } else { + bitmap = getRoundedCornerBitmap(bitmap); + views.setImageViewBitmap(R.id.appwidget_coverart, bitmap); + } + } catch (Exception x) { + Log.e(TAG, "Failed to load cover art", x); + views.setImageViewResource(R.id.appwidget_coverart, R.drawable.appwidget_art_unknown); + } + + // Link actions buttons to intents + linkButtons(context, views); + + pushUpdate(context, appWidgetIds, views); + } + /** * Link up various button actions using {@link PendingIntent}. - * - * @param playerActive @param playerActive True if player is active in background. Launch {@link net.nullsum.audinaut.activity.SubsonicFragmentActivity}. */ - private void linkButtons(Context context, RemoteViews views, boolean playerActive) { + private void linkButtons(Context context, RemoteViews views) { Intent intent = new Intent(context, SubsonicFragmentActivity.class); intent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, true); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); diff --git a/app/src/main/java/net/nullsum/audinaut/receiver/A2dpIntentReceiver.java b/app/src/main/java/net/nullsum/audinaut/receiver/A2dpIntentReceiver.java index 39afb61..6972e0e 100644 --- a/app/src/main/java/net/nullsum/audinaut/receiver/A2dpIntentReceiver.java +++ b/app/src/main/java/net/nullsum/audinaut/receiver/A2dpIntentReceiver.java @@ -4,11 +4,12 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; + import net.nullsum.audinaut.service.DownloadService; public class A2dpIntentReceiver extends BroadcastReceiver { private static final String PLAYSTATUS_RESPONSE = "com.android.music.playstatusresponse"; - private String TAG = A2dpIntentReceiver.class.getSimpleName(); + private final String TAG = A2dpIntentReceiver.class.getSimpleName(); @Override public void onReceive(Context context, Intent intent) { @@ -16,7 +17,7 @@ public class A2dpIntentReceiver extends BroadcastReceiver { DownloadService downloadService = DownloadService.getInstance(); - if (downloadService != null){ + if (downloadService != null) { Intent avrcpIntent = new Intent(PLAYSTATUS_RESPONSE); @@ -24,7 +25,7 @@ public class A2dpIntentReceiver extends BroadcastReceiver { avrcpIntent.putExtra("position", (long) downloadService.getPlayerPosition()); avrcpIntent.putExtra("ListSize", (long) downloadService.getSongs().size()); - switch (downloadService.getPlayerState()){ + switch (downloadService.getPlayerState()) { case STARTED: avrcpIntent.putExtra("playing", true); break; diff --git a/app/src/main/java/net/nullsum/audinaut/receiver/AudioNoisyReceiver.java b/app/src/main/java/net/nullsum/audinaut/receiver/AudioNoisyReceiver.java index 3a62f88..060a5ff 100644 --- a/app/src/main/java/net/nullsum/audinaut/receiver/AudioNoisyReceiver.java +++ b/app/src/main/java/net/nullsum/audinaut/receiver/AudioNoisyReceiver.java @@ -20,7 +20,6 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.media.AudioManager; -import android.util.Log; import net.nullsum.audinaut.domain.PlayerState; import net.nullsum.audinaut.service.DownloadService; @@ -28,24 +27,23 @@ import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.Util; public class AudioNoisyReceiver extends BroadcastReceiver { - private static final String TAG = AudioNoisyReceiver.class.getSimpleName(); @Override public void onReceive(Context context, Intent intent) { DownloadService downloadService = DownloadService.getInstance(); // Don't do anything if downloadService is not started - if(downloadService == null) { + if (downloadService == null) { return; } - if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals (intent.getAction ())) { - if((downloadService.getPlayerState() == PlayerState.STARTED || downloadService.getPlayerState() == PlayerState.PAUSED_TEMP)) { - SharedPreferences prefs = Util.getPreferences(downloadService); - int pausePref = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_PAUSE_DISCONNECT, "0")); - if(pausePref == 0) { - downloadService.pause(); - } + if (AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())) { + if ((downloadService.getPlayerState() == PlayerState.STARTED || downloadService.getPlayerState() == PlayerState.PAUSED_TEMP)) { + SharedPreferences prefs = Util.getPreferences(downloadService); + int pausePref = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_PAUSE_DISCONNECT, "0")); + if (pausePref == 0) { + downloadService.pause(); } + } } } } diff --git a/app/src/main/java/net/nullsum/audinaut/receiver/BootReceiver.java b/app/src/main/java/net/nullsum/audinaut/receiver/BootReceiver.java index 10d7896..bcbd7fa 100644 --- a/app/src/main/java/net/nullsum/audinaut/receiver/BootReceiver.java +++ b/app/src/main/java/net/nullsum/audinaut/receiver/BootReceiver.java @@ -22,10 +22,10 @@ import android.content.Intent; import net.nullsum.audinaut.service.HeadphoneListenerService; import net.nullsum.audinaut.util.Util; -public class BootReceiver extends BroadcastReceiver { +public class BootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - if(Util.shouldStartOnHeadphones(context)) { + if (Util.shouldStartOnHeadphones(context)) { Intent serviceIntent = new Intent(); serviceIntent.setClassName(context.getPackageName(), HeadphoneListenerService.class.getName()); context.startService(serviceIntent); diff --git a/app/src/main/java/net/nullsum/audinaut/receiver/HeadphonePlugReceiver.java b/app/src/main/java/net/nullsum/audinaut/receiver/HeadphonePlugReceiver.java index 0a9ee98..5c29ac0 100644 --- a/app/src/main/java/net/nullsum/audinaut/receiver/HeadphonePlugReceiver.java +++ b/app/src/main/java/net/nullsum/audinaut/receiver/HeadphonePlugReceiver.java @@ -18,19 +18,17 @@ package net.nullsum.audinaut.receiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.util.Log; import net.nullsum.audinaut.service.DownloadService; import net.nullsum.audinaut.util.Util; public class HeadphonePlugReceiver extends BroadcastReceiver { - private static final String TAG = HeadphonePlugReceiver.class.getSimpleName(); @Override public void onReceive(Context context, Intent intent) { - if(Intent.ACTION_HEADSET_PLUG.equals(intent.getAction())) { + if (Intent.ACTION_HEADSET_PLUG.equals(intent.getAction())) { int headphoneState = intent.getIntExtra("state", -1); - if(headphoneState == 1 && Util.shouldStartOnHeadphones(context)) { + if (headphoneState == 1 && Util.shouldStartOnHeadphones(context)) { Intent start = new Intent(context, DownloadService.class); start.setAction(DownloadService.START_PLAY); context.startService(start); diff --git a/app/src/main/java/net/nullsum/audinaut/receiver/MediaButtonIntentReceiver.java b/app/src/main/java/net/nullsum/audinaut/receiver/MediaButtonIntentReceiver.java index 4480090..79dc31e 100644 --- a/app/src/main/java/net/nullsum/audinaut/receiver/MediaButtonIntentReceiver.java +++ b/app/src/main/java/net/nullsum/audinaut/receiver/MediaButtonIntentReceiver.java @@ -36,8 +36,8 @@ public class MediaButtonIntentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT); - if(DownloadService.getInstance() == null && (event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_STOP || - event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || event.getKeyCode() == KeyEvent.KEYCODE_HEADSETHOOK)) { + if (DownloadService.getInstance() == null && (event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_STOP || + event.getKeyCode() == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || event.getKeyCode() == KeyEvent.KEYCODE_HEADSETHOOK)) { Log.w(TAG, "Ignore keycode event because downloadService is off"); return; } diff --git a/app/src/main/java/net/nullsum/audinaut/receiver/PlayActionReceiver.java b/app/src/main/java/net/nullsum/audinaut/receiver/PlayActionReceiver.java index ec0e0cc..108a5bf 100644 --- a/app/src/main/java/net/nullsum/audinaut/receiver/PlayActionReceiver.java +++ b/app/src/main/java/net/nullsum/audinaut/receiver/PlayActionReceiver.java @@ -19,17 +19,15 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.util.Log; import net.nullsum.audinaut.service.DownloadService; import net.nullsum.audinaut.util.Constants; public class PlayActionReceiver extends BroadcastReceiver { - private static final String TAG = PlayActionReceiver.class.getSimpleName(); @Override public void onReceive(Context context, Intent intent) { - if(intent.hasExtra(Constants.TASKER_EXTRA_BUNDLE)) { + if (intent.hasExtra(Constants.TASKER_EXTRA_BUNDLE)) { Bundle data = intent.getBundleExtra(Constants.TASKER_EXTRA_BUNDLE); Boolean startShuffled = data.getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE); diff --git a/app/src/main/java/net/nullsum/audinaut/service/CachedMusicService.java b/app/src/main/java/net/nullsum/audinaut/service/CachedMusicService.java index d0c204d..c54b8fd 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/CachedMusicService.java +++ b/app/src/main/java/net/nullsum/audinaut/service/CachedMusicService.java @@ -18,17 +18,6 @@ */ package net.nullsum.audinaut.service; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.concurrent.TimeUnit; - -import okhttp3.Response; - import android.content.Context; import android.graphics.Bitmap; import android.util.Log; @@ -36,41 +25,43 @@ import android.util.Log; import net.nullsum.audinaut.domain.Artist; import net.nullsum.audinaut.domain.Genre; import net.nullsum.audinaut.domain.Indexes; -import net.nullsum.audinaut.domain.PlayerQueue; import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.domain.MusicFolder; import net.nullsum.audinaut.domain.Playlist; import net.nullsum.audinaut.domain.SearchCritera; import net.nullsum.audinaut.domain.SearchResult; import net.nullsum.audinaut.domain.User; -import net.nullsum.audinaut.util.SilentBackgroundTask; +import net.nullsum.audinaut.util.FileUtil; import net.nullsum.audinaut.util.ProgressListener; +import net.nullsum.audinaut.util.SilentBackgroundTask; import net.nullsum.audinaut.util.SongDBHandler; import net.nullsum.audinaut.util.TimeLimitedCache; -import net.nullsum.audinaut.util.FileUtil; import net.nullsum.audinaut.util.Util; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.ListIterator; + +import okhttp3.Response; + import static net.nullsum.audinaut.domain.MusicDirectory.Entry; /** * @author Sindre Mehus */ public class CachedMusicService implements MusicService { + public static final int CACHE_UPDATE_LIST = 1; + private static final int CACHE_UPDATE_METADATA = 2; private static final String TAG = CachedMusicService.class.getSimpleName(); - private static final int MUSIC_DIR_CACHE_SIZE = 20; - private static final int TTL_MUSIC_DIR = 5 * 60; // Five minutes - public static final int CACHE_UPDATE_LIST = 1; - public static final int CACHE_UPDATE_METADATA = 2; - private static final int CACHED_LAST_FM = 24 * 60; - private final RESTMusicService musicService; - private final TimeLimitedCache cachedIndexes = new TimeLimitedCache(60 * 60, TimeUnit.SECONDS); - private final TimeLimitedCache> cachedPlaylists = new TimeLimitedCache>(3600, TimeUnit.SECONDS); - private final TimeLimitedCache> cachedMusicFolders = new TimeLimitedCache>(10 * 3600, TimeUnit.SECONDS); + private final TimeLimitedCache cachedIndexes = new TimeLimitedCache<>(60 * 60); + private final TimeLimitedCache> cachedPlaylists = new TimeLimitedCache<>(3600); + private final TimeLimitedCache> cachedMusicFolders = new TimeLimitedCache<>(10 * 3600); private String restUrl; private String musicFolderId; - private boolean isTagBrowsing = false; public CachedMusicService(RESTMusicService musicService) { this.musicService = musicService; @@ -90,13 +81,13 @@ public class CachedMusicService implements MusicService { } List result = cachedMusicFolders.get(); if (result == null) { - if(!refresh) { + if (!refresh) { result = FileUtil.deserialize(context, getCacheName(context, "musicFolders"), ArrayList.class); } - if(result == null) { + if (result == null) { result = musicService.getMusicFolders(refresh, context, progressListener); - FileUtil.serialize(context, new ArrayList(result), getCacheName(context, "musicFolders")); + FileUtil.serialize(context, new ArrayList<>(result), getCacheName(context, "musicFolders")); } MusicFolder.sort(result); @@ -114,13 +105,13 @@ public class CachedMusicService implements MusicService { } Indexes result = cachedIndexes.get(); if (result == null) { - String name = Util.isTagBrowsing(context, musicService.getInstance(context)) ? "artists" : "indexes"; + String name = "artists"; name = getCacheName(context, name, musicFolderId); - if(!refresh) { + if (!refresh) { result = FileUtil.deserialize(context, name, Indexes.class); } - if(result == null) { + if (result == null) { result = musicService.getIndexes(musicFolderId, refresh, context, progressListener); FileUtil.serialize(context, result, name); } @@ -133,7 +124,7 @@ public class CachedMusicService implements MusicService { public MusicDirectory getMusicDirectory(final String id, final String name, final boolean refresh, final Context context, final ProgressListener progressListener) throws Exception { MusicDirectory dir = null; final MusicDirectory cached = FileUtil.deserialize(context, getCacheName(context, "directory", id), MusicDirectory.class); - if(!refresh && cached != null) { + if (!refresh && cached != null) { dir = cached; new SilentBackgroundTask(context) { @@ -153,11 +144,11 @@ public class CachedMusicService implements MusicService { // Update which entries exist @Override public void done(Void result) { - if(progressListener != null) { - if(cached.updateEntriesList(context, musicService.getInstance(context), refreshed)) { + if (progressListener != null) { + if (cached.updateEntriesList(context, refreshed)) { progressListener.updateCache(CACHE_UPDATE_LIST); } - if(metadataUpdated) { + if (metadataUpdated) { progressListener.updateCache(CACHE_UPDATE_METADATA); } } @@ -170,7 +161,7 @@ public class CachedMusicService implements MusicService { }.execute(); } - if(dir == null) { + if (dir == null) { dir = musicService.getMusicDirectory(id, name, refresh, context, progressListener); updateAllSongs(context, dir); FileUtil.serialize(context, dir, getCacheName(context, "directory", id)); @@ -178,7 +169,7 @@ public class CachedMusicService implements MusicService { // If a cached copy exists to check against, look for removes deleteRemovedEntries(context, dir, cached); } - dir.sortChildren(context, musicService.getInstance(context)); + dir.sortChildren(context); return dir; } @@ -187,7 +178,7 @@ public class CachedMusicService implements MusicService { public MusicDirectory getArtist(final String id, final String name, final boolean refresh, final Context context, final ProgressListener progressListener) throws Exception { MusicDirectory dir = null; final MusicDirectory cached = FileUtil.deserialize(context, getCacheName(context, "artist", id), MusicDirectory.class); - if(!refresh && cached != null) { + if (!refresh && cached != null) { dir = cached; new SilentBackgroundTask(context) { @@ -205,8 +196,8 @@ public class CachedMusicService implements MusicService { // Update which entries exist @Override public void done(Void result) { - if(progressListener != null) { - if(cached.updateEntriesList(context, musicService.getInstance(context), refreshed)) { + if (progressListener != null) { + if (cached.updateEntriesList(context, refreshed)) { progressListener.updateCache(CACHE_UPDATE_LIST); } } @@ -219,14 +210,14 @@ public class CachedMusicService implements MusicService { }.execute(); } - if(dir == null) { + if (dir == null) { dir = musicService.getArtist(id, name, refresh, context, progressListener); FileUtil.serialize(context, dir, getCacheName(context, "artist", id)); // If a cached copy exists to check against, look for removes deleteRemovedEntries(context, dir, cached); } - dir.sortChildren(context, musicService.getInstance(context)); + dir.sortChildren(context); return dir; } @@ -235,7 +226,7 @@ public class CachedMusicService implements MusicService { public MusicDirectory getAlbum(final String id, final String name, final boolean refresh, final Context context, final ProgressListener progressListener) throws Exception { MusicDirectory dir = null; final MusicDirectory cached = FileUtil.deserialize(context, getCacheName(context, "album", id), MusicDirectory.class); - if(!refresh && cached != null) { + if (!refresh && cached != null) { dir = cached; new SilentBackgroundTask(context) { @@ -255,11 +246,11 @@ public class CachedMusicService implements MusicService { // Update which entries exist @Override public void done(Void result) { - if(progressListener != null) { - if(cached.updateEntriesList(context, musicService.getInstance(context), refreshed)) { + if (progressListener != null) { + if (cached.updateEntriesList(context, refreshed)) { progressListener.updateCache(CACHE_UPDATE_LIST); } - if(metadataUpdated) { + if (metadataUpdated) { progressListener.updateCache(CACHE_UPDATE_METADATA); } } @@ -272,7 +263,7 @@ public class CachedMusicService implements MusicService { }.execute(); } - if(dir == null) { + if (dir == null) { dir = musicService.getAlbum(id, name, refresh, context, progressListener); updateAllSongs(context, dir); FileUtil.serialize(context, dir, getCacheName(context, "album", id)); @@ -280,7 +271,7 @@ public class CachedMusicService implements MusicService { // If a cached copy exists to check against, look for removes deleteRemovedEntries(context, dir, cached); } - dir.sortChildren(context, musicService.getInstance(context)); + dir.sortChildren(context); return dir; } @@ -294,16 +285,16 @@ public class CachedMusicService implements MusicService { public MusicDirectory getPlaylist(boolean refresh, String id, String name, Context context, ProgressListener progressListener) throws Exception { MusicDirectory dir = null; MusicDirectory cachedPlaylist = FileUtil.deserialize(context, getCacheName(context, "playlist", id), MusicDirectory.class); - if(!refresh) { + if (!refresh) { dir = cachedPlaylist; } - if(dir == null) { + if (dir == null) { dir = musicService.getPlaylist(refresh, id, name, context, progressListener); updateAllSongs(context, dir); FileUtil.serialize(context, dir, getCacheName(context, "playlist", id)); File playlistFile = FileUtil.getPlaylistFile(context, Util.getServerName(context, musicService.getInstance(context)), dir.getName()); - if(cachedPlaylist == null || !playlistFile.exists() || !cachedPlaylist.getChildren().equals(dir.getChildren())) { + if (cachedPlaylist == null || !playlistFile.exists() || !cachedPlaylist.getChildren().equals(dir.getChildren())) { FileUtil.writePlaylistFile(context, playlistFile, dir); } } @@ -315,13 +306,13 @@ public class CachedMusicService implements MusicService { checkSettingsChanged(context); List result = refresh ? null : cachedPlaylists.get(); if (result == null) { - if(!refresh) { + if (!refresh) { result = FileUtil.deserialize(context, getCacheName(context, "playlist"), ArrayList.class); } - if(result == null) { + if (result == null) { result = musicService.getPlaylists(refresh, context, progressListener); - FileUtil.serialize(context, new ArrayList(result), getCacheName(context, "playlist")); + FileUtil.serialize(context, new ArrayList<>(result), getCacheName(context, "playlist")); } cachedPlaylists.set(result); } @@ -381,9 +372,9 @@ public class CachedMusicService implements MusicService { boolean supposedToUnpin = false; // Remove in reverse order so indexes are still correct as we iterate through - for(ListIterator iterator = toRemove.listIterator(toRemove.size()); iterator.hasPrevious(); ) { + for (ListIterator iterator = toRemove.listIterator(toRemove.size()); iterator.hasPrevious(); ) { int index = iterator.previous(); - if(supposedToUnpin) { + if (supposedToUnpin) { Entry entry = objects.get(index); DownloadFile file = new DownloadFile(context, entry, true); file.unpin(); @@ -439,24 +430,17 @@ public class CachedMusicService implements MusicService { String recentlyAddedFile = getCacheName(context, type); ArrayList recents = FileUtil.deserialize(context, recentlyAddedFile, ArrayList.class); if (recents == null) { - recents = new ArrayList(); + recents = new ArrayList<>(); } // Add any new items - final int instance = musicService.getInstance(context); - isTagBrowsing = Util.isTagBrowsing(context, instance); for (final Entry album : dir.getChildren()) { if (!recents.contains(album.getId())) { recents.add(album.getId()); String cacheName, parent; - if (isTagBrowsing) { - cacheName = "artist"; - parent = album.getArtistId(); - } else { - cacheName = "directory"; - parent = album.getParent(); - } + cacheName = "artist"; + parent = album.getArtistId(); // Add album to artist if (parent != null) { @@ -492,7 +476,7 @@ public class CachedMusicService implements MusicService { artist.setId(album.getId()); artist.setName(album.getTitle()); - new IndexesUpdater(context, isTagBrowsing ? "artists" : "indexes") { + new IndexesUpdater(context) { private boolean changed = false; @Override @@ -530,17 +514,17 @@ public class CachedMusicService implements MusicService { FileUtil.serialize(context, dir, getCacheName(context, type, Integer.toString(offset))); return dir; - } catch(IOException e) { + } catch (IOException e) { Log.w(TAG, "Failed to refresh album list: ", e); - if(refresh) { + if (refresh) { throw e; } MusicDirectory dir = FileUtil.deserialize(context, getCacheName(context, type, Integer.toString(offset)), MusicDirectory.class); - if(dir == null) { + if (dir == null) { // If we are at start and no cache, throw error higher - if(offset == 0) { + if (offset == 0) { throw e; } else { // Otherwise just pretend we are at the end of the list @@ -558,17 +542,17 @@ public class CachedMusicService implements MusicService { MusicDirectory dir = musicService.getAlbumList(type, extra, size, offset, refresh, context, progressListener); FileUtil.serialize(context, dir, getCacheName(context, type + extra, Integer.toString(offset))); return dir; - } catch(IOException e) { + } catch (IOException e) { Log.w(TAG, "Failed to refresh album list: ", e); - if(refresh) { + if (refresh) { throw e; } MusicDirectory dir = FileUtil.deserialize(context, getCacheName(context, type + extra, Integer.toString(offset)), MusicDirectory.class); - if(dir == null) { + if (dir == null) { // If we are at start and no cache, throw error higher - if(offset == 0) { + if (offset == 0) { throw e; } else { // Otherwise just pretend we are at the end of the list @@ -585,11 +569,6 @@ public class CachedMusicService implements MusicService { return musicService.getSongList(type, size, offset, context, progressListener); } - @Override - public MusicDirectory getRandomSongs(int size, String artistId, Context context, ProgressListener progressListener) throws Exception { - return musicService.getRandomSongs(size, artistId, context, progressListener); - } - @Override public MusicDirectory getRandomSongs(int size, String folder, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception { return musicService.getRandomSongs(size, folder, genre, startYear, endYear, context, progressListener); @@ -609,13 +588,13 @@ public class CachedMusicService implements MusicService { public List getGenres(boolean refresh, Context context, ProgressListener progressListener) throws Exception { List result = null; - if(!refresh) { + if (!refresh) { result = FileUtil.deserialize(context, getCacheName(context, "genre"), ArrayList.class); } - if(result == null) { + if (result == null) { result = musicService.getGenres(refresh, context, progressListener); - FileUtil.serialize(context, new ArrayList(result), getCacheName(context, "genre")); + FileUtil.serialize(context, new ArrayList<>(result), getCacheName(context, "genre")); } return result; @@ -628,12 +607,12 @@ public class CachedMusicService implements MusicService { FileUtil.serialize(context, dir, getCacheName(context, "genreSongs", Integer.toString(offset))); return dir; - } catch(IOException e) { + } catch (IOException e) { MusicDirectory dir = FileUtil.deserialize(context, getCacheName(context, "genreSongs", Integer.toString(offset)), MusicDirectory.class); - if(dir == null) { + if (dir == null) { // If we are at start and no cache, throw error higher - if(offset == 0) { + if (offset == 0) { throw e; } else { // Otherwise just pretend we are at the end of the list @@ -652,32 +631,17 @@ public class CachedMusicService implements MusicService { try { result = musicService.getUser(refresh, username, context, progressListener); FileUtil.serialize(context, result, getCacheName(context, "user-" + username)); - } catch(Exception e) { + } catch (Exception e) { // Don't care } - if(result == null && !refresh) { + if (result == null && !refresh) { result = FileUtil.deserialize(context, getCacheName(context, "user-" + username), User.class); } return result; } - @Override - public Bitmap getBitmap(String url, int size, Context context, ProgressListener progressListener, SilentBackgroundTask task) throws Exception { - return musicService.getBitmap(url, size, context, progressListener, task); - } - -@Override - public void savePlayQueue(List songs, Entry currentPlaying, int position, Context context, ProgressListener progressListener) throws Exception { - musicService.savePlayQueue(songs, currentPlaying, position, context, progressListener); - } - - @Override - public PlayerQueue getPlayQueue(Context context, ProgressListener progressListener) throws Exception { - return musicService.getPlayQueue(context, progressListener); - } - @Override public void setInstance(Integer instance) throws Exception { musicService.setInstance(instance); @@ -687,57 +651,76 @@ public class CachedMusicService implements MusicService { String s = musicService.getRestUrl(context, null, false) + id; return name + "-" + s.hashCode() + ".ser"; } + private String getCacheName(Context context, String name) { String s = musicService.getRestUrl(context, null, false); return name + "-" + s.hashCode() + ".ser"; } private void deleteRemovedEntries(Context context, MusicDirectory dir, MusicDirectory cached) { - if(cached != null) { - List oldList = new ArrayList(); + if (cached != null) { + List oldList = new ArrayList<>(); oldList.addAll(cached.getChildren()); - - // Remove all current items from old list - for(Entry entry: dir.getChildren()) { - oldList.remove(entry); - } + oldList.removeAll(dir.getChildren()); // Anything remaining has been removed from server MediaStoreService store = new MediaStoreService(context); - for(Entry entry: oldList) { + for (Entry entry : oldList) { File file = FileUtil.getEntryFile(context, entry); FileUtil.recursiveDelete(file, store); } } } + private void updateAllSongs(Context context, MusicDirectory dir) { + List songs = dir.getSongs(); + if (!songs.isEmpty()) { + SongDBHandler.getHandler(context).addSongs(musicService.getInstance(context), songs); + } + } + + private void checkSettingsChanged(Context context) { + int instance = musicService.getInstance(context); + String newUrl = musicService.getRestUrl(context, null, false); + if (!Util.equals(newUrl, restUrl)) { + cachedMusicFolders.clear(); + cachedIndexes.clear(); + cachedPlaylists.clear(); + restUrl = newUrl; + } + + String newMusicFolderId = Util.getSelectedMusicFolderId(context, instance); + if (!Util.equals(newMusicFolderId, musicFolderId)) { + cachedIndexes.clear(); + musicFolderId = newMusicFolderId; + } + } + private abstract class SerializeUpdater { final Context context; final String cacheName; final boolean singleUpdate; - public SerializeUpdater(Context context, String cacheName) { - this(context, cacheName, true); - } - public SerializeUpdater(Context context, String cacheName, boolean singleUpdate) { + public SerializeUpdater(Context context) { this.context = context; - this.cacheName = getCacheName(context, cacheName); - this.singleUpdate = singleUpdate; + this.cacheName = getCacheName(context, "playlist"); + this.singleUpdate = true; } + public SerializeUpdater(Context context, String cacheName, String id) { - this(context, cacheName, id, true); - } - public SerializeUpdater(Context context, String cacheName, String id, boolean singleUpdate) { this.context = context; this.cacheName = getCacheName(context, cacheName, id); - this.singleUpdate = singleUpdate; + this.singleUpdate = true; } public ArrayList getArrayList() { return FileUtil.deserialize(context, cacheName, ArrayList.class); } + public abstract boolean checkResult(T check); + public abstract void updateResult(List objects, T result); + public void save(ArrayList objects) { FileUtil.serialize(context, objects, cacheName); } @@ -746,47 +729,35 @@ public class CachedMusicService implements MusicService { ArrayList objects = getArrayList(); // Only execute if something to check against - if(objects != null) { - List results = new ArrayList(); - for(T check: objects) { - if(checkResult(check)) { + if (objects != null) { + List results = new ArrayList<>(); + for (T check : objects) { + if (checkResult(check)) { results.add(check); - if(singleUpdate) { + if (singleUpdate) { break; } } } // Iterate through and update each object matched - for(T result: results) { + for (T result : results) { updateResult(objects, result); } // Only reserialize if at least one match was found - if(results.size() > 0) { + if (results.size() > 0) { save(objects); } } } } - private abstract class UserUpdater extends SerializeUpdater { - String username; - public UserUpdater(Context context, String username) { - super(context, "users"); - this.username = username; - } - - @Override - public boolean checkResult(User check) { - return username.equals(check.getUsername()); - } - } private abstract class PlaylistUpdater extends SerializeUpdater { - String id; + final String id; public PlaylistUpdater(Context context, String id) { - super(context, "playlist"); + super(context); this.id = id; } @@ -795,199 +766,45 @@ public class CachedMusicService implements MusicService { return id.equals(check.getId()); } } + private abstract class MusicDirectoryUpdater extends SerializeUpdater { - protected MusicDirectory musicDirectory; + MusicDirectory musicDirectory; public MusicDirectoryUpdater(Context context, String cacheName, String id) { - super(context, cacheName, id, true); - } - public MusicDirectoryUpdater(Context context, String cacheName, String id, boolean singleUpdate) { - super(context, cacheName, id, singleUpdate); + super(context, cacheName, id); } @Override public ArrayList getArrayList() { musicDirectory = FileUtil.deserialize(context, cacheName, MusicDirectory.class); - if(musicDirectory != null) { + if (musicDirectory != null) { return new ArrayList<>(musicDirectory.getChildren()); } else { return null; } } + public void save(ArrayList objects) { musicDirectory.replaceChildren(objects); FileUtil.serialize(context, musicDirectory, cacheName); } } - private abstract class PlaylistDirectoryUpdater { - Context context; - public PlaylistDirectoryUpdater(Context context) { - this.context = context; - } - - public abstract boolean checkResult(Entry check); - public abstract void updateResult(Entry result); - - public void execute() { - List playlists = FileUtil.deserialize(context, getCacheName(context, "playlist"), ArrayList.class); - if(playlists == null) { - // No playlist list cache, nothing to update! - return; - } - - for(Playlist playlist: playlists) { - new MusicDirectoryUpdater(context, "playlist", playlist.getId(), false) { - @Override - public boolean checkResult(Entry check) { - return PlaylistDirectoryUpdater.this.checkResult(check); - } - - @Override - public void updateResult(List objects, Entry result) { - PlaylistDirectoryUpdater.this.updateResult(result); - } - }.execute(); - } - } - } - private abstract class GenericEntryUpdater { - Context context; - List entries; - - public GenericEntryUpdater(Context context, Entry entry) { - this.context = context; - this.entries = Arrays.asList(entry); - } - public GenericEntryUpdater(Context context, List entries) { - this.context = context; - this.entries = entries; - } - - public boolean checkResult(Entry entry, Entry check) { - return entry.getId().equals(check.getId()); - } - public abstract void updateResult(Entry result); - - public void execute() { - String cacheName, parent; - // Make sure it is up to date - isTagBrowsing = Util.isTagBrowsing(context, musicService.getInstance(context)); - - // Run through each entry, trying to update the directory it is in - final List songs = new ArrayList(); - for(final Entry entry: entries) { - if(isTagBrowsing) { - // If starring album, needs to reference artist instead - if(entry.isDirectory()) { - if(entry.isAlbum()) { - cacheName = "artist"; - parent = entry.getArtistId(); - } else { - cacheName = "artists"; - parent = null; - } - } else { - cacheName = "album"; - parent = entry.getAlbumId(); - } - } else { - if(entry.isDirectory() && !entry.isAlbum()) { - cacheName = "indexes"; - parent = null; - } else { - cacheName = "directory"; - parent = entry.getParent(); - } - } - - // Parent is only null when it is an artist - if(parent == null) { - new IndexesUpdater(context, cacheName) { - @Override - public boolean checkResult(Artist check) { - return GenericEntryUpdater.this.checkResult(entry, new Entry(check)); - } - - @Override - public void updateResult(List objects, Artist result) { - // Don't try to put anything here, as the Entry update method will not be called since it's a artist! - } - }.execute(); - } else { - new MusicDirectoryUpdater(context, cacheName, parent) { - @Override - public boolean checkResult(Entry check) { - return GenericEntryUpdater.this.checkResult(entry, check); - } - - @Override - public void updateResult(List objects, Entry result) { - GenericEntryUpdater.this.updateResult(result); - } - }.execute(); - } - - songs.add(entry); - } - - // Only run through playlists once and check each song against it - if(songs.size() > 0) { - new PlaylistDirectoryUpdater(context) { - @Override - public boolean checkResult(Entry check) { - for(Entry entry: songs) { - if(GenericEntryUpdater.this.checkResult(entry, check)) { - return true; - } - } - - return false; - } - - @Override - public void updateResult(Entry result) { - GenericEntryUpdater.this.updateResult(result); - } - }.execute(); - } - } - } - - private class StarUpdater extends GenericEntryUpdater { - public StarUpdater(Context context, List entries) { - super(context, entries); - } - - @Override - public boolean checkResult(Entry entry, Entry check) { - if (!entry.getId().equals(check.getId())) { - return false; - } - - return true; - } - - @Override - public void updateResult(Entry result) { - - } - }; private abstract class IndexesUpdater extends SerializeUpdater { Indexes indexes; - IndexesUpdater(Context context, String name) { - super(context, name, Util.getSelectedMusicFolderId(context, musicService.getInstance(context))); + IndexesUpdater(Context context) { + super(context, "artists", Util.getSelectedMusicFolderId(context, musicService.getInstance(context))); } @Override public ArrayList getArrayList() { indexes = FileUtil.deserialize(context, cacheName, Indexes.class); - if(indexes == null) { + if (indexes == null) { return null; } - ArrayList artists = new ArrayList(); + ArrayList artists = new ArrayList<>(); artists.addAll(indexes.getArtists()); artists.addAll(indexes.getShortcuts()); return artists; @@ -999,34 +816,4 @@ public class CachedMusicService implements MusicService { cachedIndexes.set(indexes); } } - - protected void updateAllSongs(Context context, MusicDirectory dir) { - List songs = dir.getSongs(); - if(!songs.isEmpty()) { - SongDBHandler.getHandler(context).addSongs(musicService.getInstance(context), songs); - } - } - - private void checkSettingsChanged(Context context) { - int instance = musicService.getInstance(context); - String newUrl = musicService.getRestUrl(context, null, false); - boolean newIsTagBrowsing = Util.isTagBrowsing(context, instance); - if (!Util.equals(newUrl, restUrl) || isTagBrowsing != newIsTagBrowsing) { - cachedMusicFolders.clear(); - cachedIndexes.clear(); - cachedPlaylists.clear(); - restUrl = newUrl; - isTagBrowsing = newIsTagBrowsing; - } - - String newMusicFolderId = Util.getSelectedMusicFolderId(context, instance); - if(!Util.equals(newMusicFolderId, musicFolderId)) { - cachedIndexes.clear(); - musicFolderId = newMusicFolderId; - } - } - - public RESTMusicService getMusicService() { - return musicService; - } } diff --git a/app/src/main/java/net/nullsum/audinaut/service/DownloadFile.java b/app/src/main/java/net/nullsum/audinaut/service/DownloadFile.java index 679d2a6..c301c5d 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/DownloadFile.java +++ b/app/src/main/java/net/nullsum/audinaut/service/DownloadFile.java @@ -18,13 +18,6 @@ */ package net.nullsum.audinaut.service; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.OutputStream; - import android.content.Context; import android.net.wifi.WifiManager; import android.os.PowerManager; @@ -38,6 +31,13 @@ import net.nullsum.audinaut.util.FileUtil; import net.nullsum.audinaut.util.SilentBackgroundTask; import net.nullsum.audinaut.util.Util; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + import okhttp3.Response; /** @@ -54,16 +54,15 @@ public class DownloadFile implements BufferFile { private final File saveFile; private final MediaStoreService mediaStoreService; + private final boolean save; + private final Long contentLength = null; private DownloadTask downloadTask; - private boolean save; private boolean failedDownload = false; private int failed = 0; private int bitRate; private boolean isPlaying = false; private boolean saveWhenDone = false; private boolean completeWhenDone = false; - private Long contentLength = null; - private long currentSpeed = 0; private boolean rateLimit = false; public DownloadFile(Context context, MusicDirectory.Entry song, boolean save) { @@ -82,19 +81,16 @@ public class DownloadFile implements BufferFile { public MusicDirectory.Entry getSong() { return song; } + public boolean isSong() { return song.isSong(); } - public Context getContext() { - return context; - } - /** * Returns the effective bit rate. */ public int getBitRate() { - if(!partialFile.exists()) { + if (!partialFile.exists()) { bitRate = getActualBitrate(); } if (bitRate > 0) { @@ -102,17 +98,18 @@ public class DownloadFile implements BufferFile { } return song.getBitRate() == null ? 160 : song.getBitRate(); } + private int getActualBitrate() { int br = Util.getMaxBitrate(context); - if(br == 0 && song.getTranscodedSuffix() != null && "mp3".equals(song.getTranscodedSuffix().toLowerCase())) { - if(song.getBitRate() != null) { + if (br == 0 && song.getTranscodedSuffix() != null && "mp3".equals(song.getTranscodedSuffix().toLowerCase())) { + if (song.getBitRate() != null) { br = Math.min(320, song.getBitRate()); } else { br = 320; } - } else if(song.getSuffix() != null && (song.getTranscodedSuffix() == null || song.getSuffix().equals(song.getTranscodedSuffix()))) { + } else if (song.getSuffix() != null && (song.getTranscodedSuffix() == null || song.getSuffix().equals(song.getTranscodedSuffix()))) { // If just downsampling, don't try to upsample (ie: 128 kpbs -> 192 kpbs) - if(song.getBitRate() != null && (br == 0 || br > song.getBitRate())) { + if (song.getBitRate() != null && (br == 0 || br > song.getBitRate())) { br = song.getBitRate(); } } @@ -124,29 +121,16 @@ public class DownloadFile implements BufferFile { return contentLength; } - public long getCurrentSize() { - if(partialFile.exists()) { - return partialFile.length(); - } else { - File file = getCompleteFile(); - if(file.exists()) { - return file.length(); - } else { - return 0L; - } - } - } - @Override public long getEstimatedSize() { - if(contentLength != null) { + if (contentLength != null) { return contentLength; } File file = getCompleteFile(); - if(file.exists()) { + if (file.exists()) { return file.length(); - } else if(song.getDuration() == null) { + } else if (song.getDuration() == null) { return 0; } else { int br = (getBitRate() * 1000) / 8; @@ -155,29 +139,16 @@ public class DownloadFile implements BufferFile { } } - public long getBytesPerSecond() { - return currentSpeed; - } - public synchronized void download() { rateLimit = false; preDownload(); downloadTask.execute(); } - public synchronized void downloadNow(MusicService musicService) { - rateLimit = true; - preDownload(); - downloadTask.setMusicService(musicService); - try { - downloadTask.doInBackground(); - } catch(InterruptedException e) { - // This should never be reached - } - } + private void preDownload() { FileUtil.createDirectoryForParent(saveFile); failedDownload = false; - if(!partialFile.exists()) { + if (!partialFile.exists()) { bitRate = getActualBitrate(); } downloadTask = new DownloadTask(context); @@ -211,9 +182,6 @@ public class DownloadFile implements BufferFile { return saveFile; } - public File getSaveFile() { - return saveFile; - } public File getPartialFile() { return partialFile; @@ -244,7 +212,7 @@ public class DownloadFile implements BufferFile { @Override public synchronized void onResume() { - if(!isWorkDone() && !isFailedMax() && !isDownloading() && !isDownloadCancelled()) { + if (!isWorkDone() && !isFailedMax() && !isDownloading() && !isDownloadCancelled()) { download(); } } @@ -264,6 +232,7 @@ public class DownloadFile implements BufferFile { public boolean isFailed() { return failedDownload; } + public boolean isFailedMax() { return failed > MAX_FAILURES; } @@ -317,60 +286,52 @@ public class DownloadFile implements BufferFile { } } + public void renamePartial() { + Util.renameFile(partialFile, completeFile); + saveToStore(); + } + public void setPlaying(boolean isPlaying) { - try { - if(saveWhenDone && !isPlaying) { - Util.renameFile(completeFile, saveFile); - renameInStore(completeFile, saveFile); - saveWhenDone = false; - } else if(completeWhenDone && !isPlaying) { - if(save) { - Util.renameFile(partialFile, saveFile); - saveToStore(); - } else { - Util.renameFile(partialFile, completeFile); - saveToStore(); - } - completeWhenDone = false; + if (saveWhenDone && !isPlaying) { + Util.renameFile(completeFile, saveFile); + renameInStore(completeFile, saveFile); + saveWhenDone = false; + } else if (completeWhenDone && !isPlaying) { + if (save) { + Util.renameFile(partialFile, saveFile); + saveToStore(); + } else { + Util.renameFile(partialFile, completeFile); + saveToStore(); } - } catch(IOException ex) { - Log.w(TAG, "Failed to rename file " + completeFile + " to " + saveFile, ex); + completeWhenDone = false; } this.isPlaying = isPlaying; } - public void renamePartial() { - try { - Util.renameFile(partialFile, completeFile); - saveToStore(); - } catch(IOException ex) { - Log.w(TAG, "Failed to rename file " + partialFile + " to " + completeFile, ex); - } - } - public boolean getPlaying() { - return isPlaying; - } private void deleteFromStore() { try { mediaStoreService.deleteFromMediaStore(this); - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to remove from store", e); } } + private void saveToStore() { - if(!Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_HIDE_MEDIA, false)) { + if (!Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_HIDE_MEDIA, false)) { try { mediaStoreService.saveInMediaStore(this); - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to save in media store", e); } } } + private void renameInStore(File start, File end) { try { mediaStoreService.renameInMediaStore(start, end); - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to rename in store", e); } } @@ -425,7 +386,7 @@ public class DownloadFile implements BufferFile { } if (completeFile.exists()) { if (save) { - if(isPlaying) { + if (isPlaying) { saveWhenDone = true; } else { Util.renameFile(completeFile, saveFile); @@ -438,7 +399,7 @@ public class DownloadFile implements BufferFile { return null; } - if(musicService == null) { + if (musicService == null) { musicService = MusicServiceFactory.getMusicService(context); } @@ -446,15 +407,14 @@ public class DownloadFile implements BufferFile { boolean compare; try { compare = (bitRate == 0) || (song.getDuration() == 0) || (partialFile.length() == 0) || (bitRate * song.getDuration() * 1000 / 8) > partialFile.length(); - } catch(Exception e) { + } catch (Exception e) { compare = true; } - if(compare) { + if (compare) { // Attempt partial HTTP GET, appending to the file if it exists. Response response = musicService.getDownloadInputStream(context, song, partialFile.length(), bitRate, DownloadTask.this); - if(response.header("Content-Length") != null) { + if (response.header("Content-Length") != null) { Log.i(TAG, "Content Length: " + contentLength); - contentLength = contentLength; } boolean partial = response.code() == 206; @@ -472,17 +432,17 @@ public class DownloadFile implements BufferFile { if (isCancelled()) { throw new Exception("Download of '" + song + "' was cancelled"); - } else if(partialFile.length() == 0) { + } else if (partialFile.length() == 0) { throw new Exception("Download of '" + song + "' failed. File is 0 bytes long."); } downloadAndSaveCoverArt(musicService); } - if(isPlaying) { + if (isPlaying) { completeWhenDone = true; } else { - if(save) { + if (save) { Util.renameFile(partialFile, saveFile); } else { Util.renameFile(partialFile, completeFile); @@ -490,20 +450,20 @@ public class DownloadFile implements BufferFile { DownloadFile.this.saveToStore(); } - } catch(InterruptedException x) { + } catch (InterruptedException x) { throw x; - } catch(FileNotFoundException x) { + } catch (FileNotFoundException x) { Util.delete(completeFile); Util.delete(saveFile); - if(!isCancelled()) { + if (!isCancelled()) { failed = MAX_FAILURES + 1; failedDownload = true; Log.w(TAG, "Failed to download '" + song + "'.", x); } - } catch(IOException x) { + } catch (IOException x) { Util.delete(completeFile); Util.delete(saveFile); - if(!isCancelled()) { + if (!isCancelled()) { failedDownload = true; Log.w(TAG, "Failed to download '" + song + "'.", x); } @@ -529,7 +489,7 @@ public class DownloadFile implements BufferFile { // Only run these if not interrupted, ie: cancelled DownloadService downloadService = DownloadService.getInstance(); - if(downloadService != null && !isCancelled()) { + if (downloadService != null && !isCancelled()) { new CacheCleaner(context, downloadService).cleanSpace(); checkDownloads(); } @@ -539,7 +499,7 @@ public class DownloadFile implements BufferFile { private void checkDownloads() { DownloadService downloadService = DownloadService.getInstance(); - if(downloadService != null) { + if (downloadService != null) { downloadService.checkDownloads(); } } @@ -549,16 +509,12 @@ public class DownloadFile implements BufferFile { return "DownloadTask (" + song + ")"; } - public void setMusicService(MusicService musicService) { - this.musicService = musicService; - } - - private void downloadAndSaveCoverArt(MusicService musicService) throws Exception { + private void downloadAndSaveCoverArt(MusicService musicService) { try { if (song.getCoverArt() != null) { // Check if album art already exists, don't want to needlessly load into memory File albumArtFile = FileUtil.getAlbumArtFile(context, song); - if(!albumArtFile.exists()) { + if (!albumArtFile.exists()) { musicService.getCoverArt(context, song, 0, null, null); } } @@ -602,23 +558,18 @@ public class DownloadFile implements BufferFile { long now = System.currentTimeMillis(); if (now - lastLog > 3000L) { // Only every so often. Log.i(TAG, "Downloaded " + Util.formatBytes(count) + " of " + song); - currentSpeed = lastCount / ((now - lastLog) / 1000L); lastLog = now; lastCount = 0; // Re-establish every few seconds whether screen is on or not - if(rateLimit) { + if (rateLimit) { PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); - if(pm.isScreenOn()) { - activeLimit = true; - } else { - activeLimit = false; - } + activeLimit = pm.isScreenOn(); } } // If screen is on and rateLimit is true, stop downloading from exhausting bandwidth - if(activeLimit) { + if (activeLimit) { Thread.sleep(10L); } } diff --git a/app/src/main/java/net/nullsum/audinaut/service/DownloadService.java b/app/src/main/java/net/nullsum/audinaut/service/DownloadService.java index 215b770..cde7b0e 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/DownloadService.java +++ b/app/src/main/java/net/nullsum/audinaut/service/DownloadService.java @@ -18,6 +18,48 @@ */ package net.nullsum.audinaut.service; +import android.app.Service; +import android.content.ComponentCallbacks2; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.media.AudioManager; +import android.media.MediaPlayer; +import android.media.audiofx.AudioEffect; +import android.net.wifi.WifiManager; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.PowerManager; +import android.support.v4.util.LruCache; +import android.util.Log; + +import net.nullsum.audinaut.R; +import net.nullsum.audinaut.activity.SubsonicActivity; +import net.nullsum.audinaut.audiofx.AudioEffectsController; +import net.nullsum.audinaut.audiofx.EqualizerController; +import net.nullsum.audinaut.domain.MusicDirectory; +import net.nullsum.audinaut.domain.PlayerState; +import net.nullsum.audinaut.domain.RepeatMode; +import net.nullsum.audinaut.receiver.AudioNoisyReceiver; +import net.nullsum.audinaut.util.BufferProxy; +import net.nullsum.audinaut.util.Constants; +import net.nullsum.audinaut.util.ImageLoader; +import net.nullsum.audinaut.util.Notifications; +import net.nullsum.audinaut.util.ShufflePlayBuffer; +import net.nullsum.audinaut.util.SilentBackgroundTask; +import net.nullsum.audinaut.util.SimpleServiceBinder; +import net.nullsum.audinaut.util.Util; +import net.nullsum.audinaut.util.tags.BastpUtil; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + import static net.nullsum.audinaut.domain.PlayerState.COMPLETED; import static net.nullsum.audinaut.domain.PlayerState.DOWNLOADING; import static net.nullsum.audinaut.domain.PlayerState.IDLE; @@ -28,64 +70,11 @@ import static net.nullsum.audinaut.domain.PlayerState.PREPARING; import static net.nullsum.audinaut.domain.PlayerState.STARTED; import static net.nullsum.audinaut.domain.PlayerState.STOPPED; -import net.nullsum.audinaut.R; -import net.nullsum.audinaut.activity.SubsonicActivity; -import net.nullsum.audinaut.audiofx.AudioEffectsController; -import net.nullsum.audinaut.audiofx.EqualizerController; -import net.nullsum.audinaut.domain.MusicDirectory; -import net.nullsum.audinaut.domain.PlayerState; -import net.nullsum.audinaut.domain.RepeatMode; -import net.nullsum.audinaut.receiver.AudioNoisyReceiver; -import net.nullsum.audinaut.receiver.MediaButtonIntentReceiver; -import net.nullsum.audinaut.util.BufferProxy; -import net.nullsum.audinaut.util.Constants; -import net.nullsum.audinaut.util.ImageLoader; -import net.nullsum.audinaut.util.Notifications; -import net.nullsum.audinaut.util.ShufflePlayBuffer; -import net.nullsum.audinaut.util.SilentBackgroundTask; -import net.nullsum.audinaut.util.SimpleServiceBinder; -import net.nullsum.audinaut.util.UpdateHelper; -import net.nullsum.audinaut.util.Util; -import net.nullsum.audinaut.util.tags.BastpUtil; -import net.nullsum.audinaut.view.UpdateView; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.Iterator; -import java.util.List; - -import android.app.Service; -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; -import android.media.PlaybackParams; -import android.media.audiofx.AudioEffect; -import android.net.wifi.WifiManager; -import android.os.Build; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.PowerManager; -import android.util.Log; -import android.support.v4.util.LruCache; -import android.view.KeyEvent; - /** * @author Sindre Mehus * @version $Id$ */ public class DownloadService extends Service { - private static final String TAG = DownloadService.class.getSimpleName(); - public static final String CMD_PLAY = "net.nullsum.audinaut.CMD_PLAY"; public static final String CMD_TOGGLEPAUSE = "net.nullsum.audinaut.CMD_TOGGLEPAUSE"; public static final String CMD_PAUSE = "net.nullsum.audinaut.CMD_PAUSE"; @@ -96,34 +85,33 @@ public class DownloadService extends Service { public static final String START_PLAY = "net.nullsum.audinaut.START_PLAYING"; public static final int FAST_FORWARD = 30000; public static final int REWIND = 10000; + public static final int METADATA_UPDATED_ALL = 0; + public static final int METADATA_UPDATED_COVER_ART = 8; + private static final String TAG = DownloadService.class.getSimpleName(); private static final long DEFAULT_DELAY_UPDATE_PROGRESS = 1000L; - private static final double DELETE_CUTOFF = 0.84; private static final int REQUIRED_ALBUM_MATCHES = 4; private static final int REMOTE_PLAYLIST_TOTAL = 3; private static final int SHUFFLE_MODE_NONE = 0; private static final int SHUFFLE_MODE_ALL = 1; - private static final int SHUFFLE_MODE_ARTIST = 2; - - public static final int METADATA_UPDATED_ALL = 0; - public static final int METADATA_UPDATED_STAR = 1; - public static final int METADATA_UPDATED_COVER_ART = 8; - - private final IBinder binder = new SimpleServiceBinder<>(this); + private static DownloadService instance; + private final IBinder binder = new SimpleServiceBinder<>(); + private final List downloadList = new ArrayList<>(); + private final List backgroundDownloadList = new ArrayList<>(); + private final List toDelete = new ArrayList<>(); + private final Handler handler = new Handler(); + private final DownloadServiceLifecycleSupport lifecycleSupport = new DownloadServiceLifecycleSupport(this); + private final LruCache downloadFileCache = new LruCache<>(100); + private final List cleanupCandidates = new ArrayList<>(); + private final List onSongChangedListeners = new ArrayList<>(); + private final long delayUpdateProgress = DEFAULT_DELAY_UPDATE_PROGRESS; + private final AudioNoisyReceiver audioNoisyReceiver = new AudioNoisyReceiver(); private Looper mediaPlayerLooper; private MediaPlayer mediaPlayer; private MediaPlayer nextMediaPlayer; private int audioSessionId; private boolean nextSetup = false; - private final List downloadList = new ArrayList(); - private final List backgroundDownloadList = new ArrayList(); - private final List toDelete = new ArrayList(); - private final Handler handler = new Handler(); private Handler mediaPlayerHandler; - private final DownloadServiceLifecycleSupport lifecycleSupport = new DownloadServiceLifecycleSupport(this); private ShufflePlayBuffer shufflePlayBuffer; - - private final LruCache downloadFileCache = new LruCache(100); - private final List cleanupCandidates = new ArrayList(); private DownloadFile currentPlaying; private int currentPlayingIndex = -1; private DownloadFile nextPlaying; @@ -134,97 +122,84 @@ public class DownloadService extends Service { private PlayerState nextPlayerState = IDLE; private boolean removePlayed; private boolean shufflePlay; - private final List onSongChangedListeners = new ArrayList<>(); private long revision; - private static DownloadService instance; private String suggestedPlaylistName; private String suggestedPlaylistId; private PowerManager.WakeLock wakeLock; - private WifiManager.WifiLock wifiLock; - private boolean keepScreenOn; private int cachedPosition = 0; private boolean downloadOngoing = false; private float volume = 1.0f; - private long delayUpdateProgress = DEFAULT_DELAY_UPDATE_PROGRESS; - private AudioEffectsController effectsController; private PositionCache positionCache; private BufferProxy proxy; - private boolean autoPlayStart = false; private boolean runListenersOnInit = false; - // Variables to manage getCurrentPosition sometimes starting from an arbitrary non-zero number private long subtractNextPosition = 0; private int subtractPosition = 0; - private AudioNoisyReceiver audioNoisyReceiver = new AudioNoisyReceiver(); + public static DownloadService getInstance() { + return instance; + } @Override public void onCreate() { super.onCreate(); final SharedPreferences prefs = Util.getPreferences(this); - new Thread(new Runnable() { - public void run() { - Looper.prepare(); + new Thread(() -> { + Looper.prepare(); - mediaPlayer = new MediaPlayer(); - mediaPlayer.setWakeMode(DownloadService.this, PowerManager.PARTIAL_WAKE_LOCK); + mediaPlayer = new MediaPlayer(); + mediaPlayer.setWakeMode(DownloadService.this, PowerManager.PARTIAL_WAKE_LOCK); - audioSessionId = -1; - Integer id = prefs.getInt(Constants.CACHE_AUDIO_SESSION_ID, -1); - if(id != -1) { - try { - audioSessionId = id; - mediaPlayer.setAudioSessionId(audioSessionId); - } catch (Throwable e) { - audioSessionId = -1; - } + audioSessionId = -1; + Integer id = prefs.getInt(Constants.CACHE_AUDIO_SESSION_ID, -1); + if (id != -1) { + try { + audioSessionId = id; + mediaPlayer.setAudioSessionId(audioSessionId); + } catch (Throwable e) { + audioSessionId = -1; } - - if(audioSessionId == -1) { - mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); - audioSessionId = mediaPlayer.getAudioSessionId(); - prefs.edit().putInt(Constants.CACHE_AUDIO_SESSION_ID, audioSessionId).apply(); - } - - mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { - @Override - public boolean onError(MediaPlayer mediaPlayer, int what, int more) { - handleError(new Exception("MediaPlayer error: " + what + " (" + more + ")")); - return false; - } - }); - - effectsController = new AudioEffectsController(DownloadService.this, audioSessionId); - if(prefs.getBoolean(Constants.PREFERENCES_EQUALIZER_ON, false)) { - getEqualizerController(); - } - - mediaPlayerLooper = Looper.myLooper(); - mediaPlayerHandler = new Handler(mediaPlayerLooper); - - if(runListenersOnInit) { - onSongsChanged(); - onSongProgress(); - onStateUpdate(); - } - - Looper.loop(); } + + if (audioSessionId == -1) { + mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + audioSessionId = mediaPlayer.getAudioSessionId(); + prefs.edit().putInt(Constants.CACHE_AUDIO_SESSION_ID, audioSessionId).apply(); + } + + mediaPlayer.setOnErrorListener((mediaPlayer, what, more) -> { + handleError(new Exception("MediaPlayer error: " + what + " (" + more + ")")); + return false; + }); + + effectsController = new AudioEffectsController(DownloadService.this, audioSessionId); + if (prefs.getBoolean(Constants.PREFERENCES_EQUALIZER_ON, false)) { + getEqualizerController(); + } + + mediaPlayerLooper = Looper.myLooper(); + mediaPlayerHandler = new Handler(mediaPlayerLooper); + + if (runListenersOnInit) { + onSongsChanged(); + onSongProgress(); + onStateUpdate(); + } + + Looper.loop(); }, "DownloadService").start(); Util.registerMediaButtonEventReceiver(this); - PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE); + PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this.getClass().getName()); wakeLock.setReferenceCounted(false); WifiManager wifiManager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE); - wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "downloadServiceLock"); - - keepScreenOn = prefs.getBoolean(Constants.PREFERENCES_KEY_KEEP_SCREEN_ON, false); + wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "downloadServiceLock"); instance = this; shufflePlayBuffer = new ShufflePlayBuffer(this); @@ -245,19 +220,19 @@ public class DownloadService extends Service { @Override public void onTrimMemory(int level) { ImageLoader imageLoader = SubsonicActivity.getStaticImageLoader(this); - if(imageLoader != null) { + if (imageLoader != null) { Log.i(TAG, "Memory Trim Level: " + level); if (level < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL) { imageLoader.onLowMemory(0.75f); } else if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW) { imageLoader.onLowMemory(0.50f); - } else if(level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE) { + } else if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE) { imageLoader.onLowMemory(0.25f); } } else if (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE) { imageLoader.onLowMemory(0.25f); - } else if(level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) { + } else if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) { imageLoader.onLowMemory(0.75f); } } @@ -268,7 +243,7 @@ public class DownloadService extends Service { super.onDestroy(); instance = null; - if(currentPlaying != null) currentPlaying.setPlaying(false); + if (currentPlaying != null) currentPlaying.setPlaying(false); lifecycleSupport.onDestroy(); Intent i = new Intent(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION); @@ -277,22 +252,22 @@ public class DownloadService extends Service { sendBroadcast(i); mediaPlayer.release(); - if(nextMediaPlayer != null) { + if (nextMediaPlayer != null) { nextMediaPlayer.release(); } mediaPlayerLooper.quit(); shufflePlayBuffer.shutdown(); effectsController.release(); - if(bufferTask != null) { + if (bufferTask != null) { bufferTask.cancel(); bufferTask = null; } - if(nextPlayingTask != null) { + if (nextPlayingTask != null) { nextPlayingTask.cancel(); nextPlayingTask = null; } - if(proxy != null) { + if (proxy != null) { proxy.stop(); proxy = null; } @@ -302,26 +277,16 @@ public class DownloadService extends Service { unregisterReceiver(audioNoisyReceiver); } - public static DownloadService getInstance() { - return instance; - } - @Override public IBinder onBind(Intent intent) { return binder; } - public void post(Runnable r) { - handler.post(r); - } - public void postDelayed(Runnable r, long millis) { - handler.postDelayed(r, millis); + public synchronized void download(List songs, boolean save, boolean autoplay, boolean playNext, boolean shuffle) { + download(songs, save, autoplay, playNext, shuffle, 0); } - public synchronized void download(List songs, boolean save, boolean autoplay, boolean playNext, boolean shuffle) { - download(songs, save, autoplay, playNext, shuffle, 0, 0); - } - public synchronized void download(List songs, boolean save, boolean autoplay, boolean playNext, boolean shuffle, int start, int position) { + public synchronized void download(List songs, boolean save, boolean autoplay, boolean playNext, boolean shuffle, int start) { setShufflePlayEnabled(false); int offset = 1; boolean noNetwork = !Util.isOffline(this) && !Util.isNetworkConnected(this); @@ -336,11 +301,11 @@ public class DownloadService extends Service { offset = 0; } for (MusicDirectory.Entry song : songs) { - if(song != null) { + if (song != null) { DownloadFile downloadFile = new DownloadFile(this, song, save); addToDownloadList(downloadFile, getCurrentPlayingIndex() + offset); - if(noNetwork && !warnNetwork) { - if(!downloadFile.isCompleteFileAvailable()) { + if (noNetwork && !warnNetwork) { + if (!downloadFile.isCompleteFileAvailable()) { warnNetwork = true; } } @@ -353,19 +318,19 @@ public class DownloadService extends Service { int size = size(); int index = getCurrentPlayingIndex(); for (MusicDirectory.Entry song : songs) { - if(song == null) { + if (song == null) { continue; } DownloadFile downloadFile = new DownloadFile(this, song, save); addToDownloadList(downloadFile, -1); - if(noNetwork && !warnNetwork) { - if(!downloadFile.isCompleteFileAvailable()) { + if (noNetwork && !warnNetwork) { + if (!downloadFile.isCompleteFileAvailable()) { warnNetwork = true; } } } - if(!autoplay && (size - 1) == index) { + if (!autoplay && (size - 1) == index) { setNextPlaying(); } } @@ -373,17 +338,17 @@ public class DownloadService extends Service { onSongsChanged(); updateRemotePlaylist(); - if(shuffle) { + if (shuffle) { shuffle(); } - if(warnNetwork) { + if (warnNetwork) { Util.toast(this, R.string.select_album_no_network); } if (autoplay) { - play(start, true, position); - } else if(start != 0 || position != 0) { - play(start, false, position); + play(start, true, 0); + } else if (start != 0) { + play(start, false, 0); } else { if (currentPlaying == null) { currentPlaying = downloadList.get(0); @@ -396,27 +361,29 @@ public class DownloadService extends Service { } lifecycleSupport.serializeDownloadQueue(); } + private void addToDownloadList(DownloadFile file, int offset) { - if(offset == -1) { + if (offset == -1) { downloadList.add(file); } else { downloadList.add(offset, file); } } + public synchronized void downloadBackground(List songs, boolean save) { for (MusicDirectory.Entry song : songs) { DownloadFile downloadFile = new DownloadFile(this, song, save); - if(!downloadFile.isWorkDone() || (downloadFile.shouldSave() && !downloadFile.isSaved())) { + if (!downloadFile.isWorkDone() || (downloadFile.shouldSave() && !downloadFile.isSaved())) { // Only add to list if there is work to be done backgroundDownloadList.add(downloadFile); - } else if(downloadFile.isSaved() && !save) { + } else if (downloadFile.isSaved() && !save) { // Quickly unpin song instead of adding it to work to be done downloadFile.unpin(); } } revision++; - if(!Util.isOffline(this) && !Util.isNetworkConnected(this)) { + if (!Util.isOffline(this) && !Util.isNetworkConnected(this)) { Util.toast(this, R.string.select_album_no_network); } @@ -426,15 +393,15 @@ public class DownloadService extends Service { private synchronized void updateRemotePlaylist() { List playlist = new ArrayList<>(); - if(currentPlaying != null) { + if (currentPlaying != null) { int index = downloadList.indexOf(currentPlaying); - if(index == -1) { + if (index == -1) { index = 0; } int size = size(); int end = index + REMOTE_PLAYLIST_TOTAL; - for(int i = index; i < size && i < end; i++) { + for (int i = index; i < size && i < end; i++) { playlist.add(downloadList.get(i)); } } @@ -442,13 +409,13 @@ public class DownloadService extends Service { public synchronized void restore(List songs, List toDelete, int currentPlayingIndex, int currentPlayingPosition) { SharedPreferences prefs = Util.getPreferences(this); - if(prefs.getBoolean(Constants.PREFERENCES_KEY_REMOVE_PLAYED, false)) { + if (prefs.getBoolean(Constants.PREFERENCES_KEY_REMOVE_PLAYED, false)) { removePlayed = true; } int startShufflePlay = prefs.getInt(Constants.PREFERENCES_KEY_SHUFFLE_MODE, SHUFFLE_MODE_NONE); download(songs, false, false, false, false); - if(startShufflePlay != SHUFFLE_MODE_NONE) { - if(startShufflePlay == SHUFFLE_MODE_ALL) { + if (startShufflePlay != SHUFFLE_MODE_NONE) { + if (startShufflePlay == SHUFFLE_MODE_ALL) { shufflePlay = true; } SharedPreferences.Editor editor = prefs.edit(); @@ -456,7 +423,7 @@ public class DownloadService extends Service { editor.apply(); } if (currentPlayingIndex != -1) { - while(mediaPlayer == null) { + while (mediaPlayer == null) { Util.sleepQuietly(50L); } @@ -464,8 +431,8 @@ public class DownloadService extends Service { autoPlayStart = false; } - if(toDelete != null) { - for(MusicDirectory.Entry entry: toDelete) { + if (toDelete != null) { + for (MusicDirectory.Entry entry : toDelete) { this.toDelete.add(forSong(entry)); } } @@ -478,13 +445,13 @@ public class DownloadService extends Service { return lifecycleSupport != null && lifecycleSupport.isInitialized(); } - public synchronized Date getLastStateChanged() { - return lifecycleSupport.getLastChange(); + public boolean isRemovePlayed() { + return removePlayed; } public synchronized void setRemovePlayed(boolean enabled) { removePlayed = enabled; - if(removePlayed) { + if (removePlayed) { checkDownloads(); lifecycleSupport.serializeDownloadQueue(); } @@ -492,8 +459,9 @@ public class DownloadService extends Service { editor.putBoolean(Constants.PREFERENCES_KEY_REMOVE_PLAYED, enabled); editor.apply(); } - public boolean isRemovePlayed() { - return removePlayed; + + public boolean isShufflePlayEnabled() { + return shufflePlay; } public synchronized void setShufflePlayEnabled(boolean enabled) { @@ -506,10 +474,6 @@ public class DownloadService extends Service { editor.apply(); } - public boolean isShufflePlayEnabled() { - return shufflePlay; - } - public synchronized void shuffle() { Collections.shuffle(downloadList); currentPlayingIndex = downloadList.indexOf(currentPlaying); @@ -534,24 +498,11 @@ public class DownloadService extends Service { setNextPlaying(); } - public boolean getKeepScreenOn() { - return keepScreenOn; - } - - public void setKeepScreenOn(boolean keepScreenOn) { - this.keepScreenOn = keepScreenOn; - - SharedPreferences prefs = Util.getPreferences(this); - SharedPreferences.Editor editor = prefs.edit(); - editor.putBoolean(Constants.PREFERENCES_KEY_KEEP_SCREEN_ON, keepScreenOn); - editor.apply(); - } - public synchronized DownloadFile forSong(MusicDirectory.Entry song) { DownloadFile returnFile = null; for (DownloadFile downloadFile : downloadList) { if (downloadFile.getSong().equals(song)) { - if(((downloadFile.isDownloading() && !downloadFile.isDownloadCancelled() && downloadFile.getPartialFile().exists()) || downloadFile.isWorkDone())) { + if (((downloadFile.isDownloading() && !downloadFile.isDownloadCancelled() && downloadFile.getPartialFile().exists()) || downloadFile.isWorkDone())) { // If downloading, return immediately return downloadFile; } else { @@ -566,7 +517,7 @@ public class DownloadService extends Service { } } - if(returnFile != null) { + if (returnFile != null) { return returnFile; } @@ -579,7 +530,7 @@ public class DownloadService extends Service { } public synchronized void clearBackground() { - if(currentDownloading != null && backgroundDownloadList.contains(currentDownloading)) { + if (currentDownloading != null && backgroundDownloadList.contains(currentDownloading)) { currentDownloading.cancelDownload(); currentDownloading = null; } @@ -596,7 +547,7 @@ public class DownloadService extends Service { iterator.remove(); // Reset if the current playing song has been removed - if(currentPlaying == downloadFile) { + if (currentPlaying == downloadFile) { reset(); } @@ -609,18 +560,15 @@ public class DownloadService extends Service { } public void setOnline(final boolean online) { - if(shufflePlay) { + if (shufflePlay) { setShufflePlayEnabled(false); } - lifecycleSupport.post(new Runnable() { - @Override - public void run() { - if (online) { - checkDownloads(); - } else { - clearIncomplete(); - } + lifecycleSupport.post(() -> { + if (online) { + checkDownloads(); + } else { + clearIncomplete(); } }); } @@ -630,14 +578,8 @@ public class DownloadService extends Service { } public synchronized void clear() { - clear(true); - } - public synchronized void clear(boolean serialize) { // Delete podcast if fully listened to - int position = getPlayerPosition(); - int duration = getPlayerDuration(); - boolean cutoff = isPastCutoff(position, duration, true); - for(DownloadFile podcast: toDelete) { + for (DownloadFile podcast : toDelete) { podcast.delete(); } toDelete.clear(); @@ -649,14 +591,11 @@ public class DownloadService extends Service { currentDownloading.cancelDownload(); currentDownloading = null; } - setCurrentPlaying(null, false); - - if (serialize) { - lifecycleSupport.serializeDownloadQueue(); - } + setCurrentPlaying(null); + lifecycleSupport.serializeDownloadQueue(); updateRemotePlaylist(); setNextPlaying(); - if(proxy != null) { + if (proxy != null) { proxy.stop(); proxy = null; } @@ -668,11 +607,6 @@ public class DownloadService extends Service { checkDownloads(); } - public synchronized void remove(int which) { - downloadList.remove(which); - currentPlayingIndex = downloadList.indexOf(currentPlaying); - } - public synchronized void remove(DownloadFile downloadFile) { if (downloadFile == currentDownloading) { currentDownloading.cancelDownload(); @@ -680,7 +614,7 @@ public class DownloadService extends Service { } if (downloadFile == currentPlaying) { reset(); - setCurrentPlaying(null, false); + setCurrentPlaying(null); } downloadList.remove(downloadFile); currentPlayingIndex = downloadList.indexOf(currentPlaying); @@ -689,12 +623,13 @@ public class DownloadService extends Service { onSongsChanged(); lifecycleSupport.serializeDownloadQueue(); updateRemotePlaylist(); - if(downloadFile == nextPlaying) { + if (downloadFile == nextPlaying) { setNextPlaying(); } checkDownloads(); } + public synchronized void removeBackground(DownloadFile downloadFile) { if (downloadFile == currentDownloading && downloadFile != currentPlaying && downloadFile != nextPlaying) { currentDownloading.cancelDownload(); @@ -712,42 +647,15 @@ public class DownloadService extends Service { } } - public synchronized void unpin(List songs) { - for (MusicDirectory.Entry song : songs) { - forSong(song).unpin(); - } - } - - synchronized void setCurrentPlaying(int currentPlayingIndex, boolean showNotification) { + private synchronized void setCurrentPlaying(int currentPlayingIndex) { try { - setCurrentPlaying(downloadList.get(currentPlayingIndex), showNotification); + setCurrentPlaying(downloadList.get(currentPlayingIndex)); } catch (IndexOutOfBoundsException x) { // Ignored } } - synchronized void setCurrentPlaying(DownloadFile currentPlaying, boolean showNotification) { - if(this.currentPlaying != null) { - this.currentPlaying.setPlaying(false); - } - this.currentPlaying = currentPlaying; - if(currentPlaying == null) { - currentPlayingIndex = -1; - setPlayerState(IDLE); - } else { - currentPlayingIndex = downloadList.indexOf(currentPlaying); - } - - if (currentPlaying != null && currentPlaying.getSong() != null) { - Util.broadcastNewTrackInfo(this, currentPlaying.getSong()); - } else { - Util.broadcastNewTrackInfo(this, null); - Notifications.hidePlayingNotification(this, this, handler); - } - onSongChanged(); - } - - synchronized void setNextPlaying() { + private synchronized void setNextPlaying() { SharedPreferences prefs = Util.getPreferences(DownloadService.this); boolean gaplessPlayback = prefs.getBoolean(Constants.PREFERENCES_KEY_GAPLESS_PLAYBACK, true); @@ -760,13 +668,13 @@ public class DownloadService extends Service { int index = getNextPlayingIndex(); - if(nextPlayingTask != null) { + if (nextPlayingTask != null) { nextPlayingTask.cancel(); nextPlayingTask = null; } resetNext(); - if(index < size() && index != -1 && index != currentPlayingIndex) { + if (index < size() && index != -1 && index != currentPlayingIndex) { nextPlaying = downloadList.get(index); nextPlayingTask = new CheckCompletionTask(nextPlaying); @@ -779,6 +687,7 @@ public class DownloadService extends Service { public int getCurrentPlayingIndex() { return currentPlayingIndex; } + private int getNextPlayingIndex() { int index = getCurrentPlayingIndex(); if (index != -1) { @@ -800,28 +709,24 @@ public class DownloadService extends Service { } return index; } + private int checkNextIndexValid(int index, RepeatMode repeatMode) { int startIndex = index; int size = size(); - if(index < size && index != -1) { - if(!Util.isAllowedToDownload(this)){ + if (index < size && index != -1) { + if (!Util.isAllowedToDownload(this)) { DownloadFile next = downloadList.get(index); - while(!next.isCompleteFileAvailable()) { + while (!next.isCompleteFileAvailable()) { index++; if (index >= size) { - if(repeatMode == RepeatMode.ALL) { + if (repeatMode == RepeatMode.ALL) { index = 0; } else { return -1; } - } else if(index == startIndex) { - handler.post(new Runnable() { - @Override - public void run() { - Util.toast(DownloadService.this, R.string.download_playerstate_mobile_disabled); - } - }); + } else if (index == startIndex) { + handler.post(() -> Util.toast(DownloadService.this, R.string.download_playerstate_mobile_disabled)); return -1; } @@ -837,22 +742,41 @@ public class DownloadService extends Service { return currentPlaying; } - public DownloadFile getCurrentDownloading() { - return currentDownloading; + private synchronized void setCurrentPlaying(DownloadFile currentPlaying) { + if (this.currentPlaying != null) { + this.currentPlaying.setPlaying(false); + } + this.currentPlaying = currentPlaying; + if (currentPlaying == null) { + currentPlayingIndex = -1; + setPlayerState(IDLE); + } else { + currentPlayingIndex = downloadList.indexOf(currentPlaying); + } + + if (currentPlaying != null && currentPlaying.getSong() != null) { + Util.broadcastNewTrackInfo(this, currentPlaying.getSong()); + } else { + Util.broadcastNewTrackInfo(this, null); + Notifications.hidePlayingNotification(this, this, handler); + } + onSongChanged(); } - public DownloadFile getNextPlaying() { - return nextPlaying; + public DownloadFile getCurrentDownloading() { + return currentDownloading; } public List getSongs() { return downloadList; } - public List getToDelete() { return toDelete; } + public List getToDelete() { + return toDelete; + } public synchronized List getDownloads() { - List temp = new ArrayList(); + List temp = new ArrayList<>(); temp.addAll(downloadList); temp.addAll(backgroundDownloadList); return temp; @@ -862,9 +786,10 @@ public class DownloadService extends Service { return backgroundDownloadList; } - /** Plays either the current song (resume) or the first/next one in queue. */ - public synchronized void play() - { + /** + * Plays either the current song (resume) or the first/next one in queue. + */ + public synchronized void play() { int current = getCurrentPlayingIndex(); if (current == -1) { play(0); @@ -876,38 +801,42 @@ public class DownloadService extends Service { public synchronized void play(int index) { play(index, true); } + public synchronized void play(DownloadFile downloadFile) { play(downloadList.indexOf(downloadFile)); } + private synchronized void play(int index, boolean start) { play(index, start, 0); } + private synchronized void play(int index, boolean start, int position) { int size = this.size(); cachedPosition = 0; if (index < 0 || index >= size) { reset(); - if(index >= size && size != 0) { - setCurrentPlaying(0, false); + if (index >= size && size != 0) { + setCurrentPlaying(0); Notifications.hidePlayingNotification(this, this, handler); } else { - setCurrentPlaying(null, false); + setCurrentPlaying(null); } lifecycleSupport.serializeDownloadQueue(); } else { - if(nextPlayingTask != null) { + if (nextPlayingTask != null) { nextPlayingTask.cancel(); nextPlayingTask = null; } - setCurrentPlaying(index, start); + setCurrentPlaying(index); bufferAndPlay(position, start); checkDownloads(); setNextPlaying(); } } + private synchronized void playNext() { - if(nextPlaying != null && nextPlayerState == PlayerState.PREPARED) { - if(!nextSetup) { + if (nextPlaying != null && nextPlayerState == PlayerState.PREPARED) { + if (!nextSetup) { playNext(true); } else { nextSetup = false; @@ -917,14 +846,15 @@ public class DownloadService extends Service { onSongCompleted(); } } + private synchronized void playNext(boolean start) { Util.broadcastPlaybackStatusChange(this, currentPlaying.getSong(), PlayerState.PREPARED); // Swap the media players since nextMediaPlayer is ready to play subtractPosition = 0; - if(start) { + if (start) { nextMediaPlayer.start(); - } else if(!nextMediaPlayer.isPlaying()) { + } else if (!nextMediaPlayer.isPlaying()) { Log.w(TAG, "nextSetup lied about it's state!"); nextMediaPlayer.start(); } else { @@ -936,13 +866,13 @@ public class DownloadService extends Service { MediaPlayer tmp = mediaPlayer; mediaPlayer = nextMediaPlayer; nextMediaPlayer = tmp; - setCurrentPlaying(nextPlaying, true); + setCurrentPlaying(nextPlaying); setPlayerState(PlayerState.STARTED); setupHandlers(currentPlaying, false, start); setNextPlaying(); // Proxy should not be being used here since the next player was already setup to play - if(proxy != null) { + if (proxy != null) { proxy.stop(); proxy = null; } @@ -950,7 +880,9 @@ public class DownloadService extends Service { updateRemotePlaylist(); } - /** Plays or resumes the playback, depending on the current player state. */ + /** + * Plays or resumes the playback, depending on the current player state. + */ public synchronized void togglePlayPause() { if (playerState == PAUSED || playerState == COMPLETED || playerState == STOPPED) { start(); @@ -963,12 +895,12 @@ public class DownloadService extends Service { } public synchronized void seekTo(int position) { - if(position < 0) { + if (position < 0) { position = 0; } try { - if(proxy != null && currentPlaying.isCompleteFileAvailable()) { + if (proxy != null && currentPlaying.isCompleteFileAvailable()) { doPlay(currentPlaying, position, playerState == STARTED); return; } @@ -978,26 +910,29 @@ public class DownloadService extends Service { cachedPosition = position; onSongProgress(); - if(playerState == PAUSED) { + if (playerState == PAUSED) { lifecycleSupport.serializeDownloadQueue(); } } catch (Exception x) { handleError(x); } } + public synchronized int rewind() { return seekToWrapper(-REWIND); } + public synchronized int fastForward() { return seekToWrapper(FAST_FORWARD); } - protected int seekToWrapper(int difference) { + + private int seekToWrapper(int difference) { int msPlayed = Math.max(0, getPlayerPosition()); Integer duration = getPlayerDuration(); int msTotal = duration == null ? 0 : duration; int seekTo; - if(msPlayed + difference > msTotal) { + if (msPlayed + difference > msTotal) { seekTo = msTotal; } else { seekTo = msPlayed + difference; @@ -1014,7 +949,7 @@ public class DownloadService extends Service { } // If only one song, just skip within song - if(size() == 1 || (currentPlaying != null && !currentPlaying.isSong())) { + if (size() == 1 || (currentPlaying != null && !currentPlaying.isSong())) { rewind(); return; } @@ -1024,7 +959,7 @@ public class DownloadService extends Service { if (getPlayerPosition() > 5000 || (index == 0 && getRepeatMode() != RepeatMode.ALL)) { seekTo(0); } else { - if(index == 0) { + if (index == 0) { index = size(); } @@ -1035,32 +970,20 @@ public class DownloadService extends Service { public synchronized void next() { next(false); } - public synchronized void next(boolean forceCutoff) { - next(forceCutoff, false); - } - public synchronized void next(boolean forceCutoff, boolean forceStart) { + + public synchronized void next(boolean forceStart) { // If only one song, just skip within song - if(size() == 1 || (currentPlaying != null && !currentPlaying.isSong())) { + if (size() == 1 || (currentPlaying != null && !currentPlaying.isSong())) { fastForward(); return; - } else if(playerState == PREPARING || playerState == PREPARED) { + } else if (playerState == PREPARING || playerState == PREPARED) { return; } - // Delete podcast if fully listened to - int position = getPlayerPosition(); - int duration = getPlayerDuration(); - boolean cutoff; - if(forceCutoff) { - cutoff = true; - } else { - cutoff = isPastCutoff(position, duration); - } - int index = getCurrentPlayingIndex(); int nextPlayingIndex = getNextPlayingIndex(); // Make sure to actually go to next when repeat song is on - if(index == nextPlayingIndex) { + if (index == nextPlayingIndex) { nextPlayingIndex++; } if (index != -1 && nextPlayingIndex < size()) { @@ -1068,28 +991,21 @@ public class DownloadService extends Service { } } - public void onSongCompleted() { + private void onSongCompleted() { setPlayerStateCompleted(); - postPlayCleanup(); play(getNextPlayingIndex()); } - public void onNextStarted(DownloadFile nextPlaying) { - setPlayerStateCompleted(); - postPlayCleanup(); - setCurrentPlaying(nextPlaying, true); - setPlayerState(STARTED); - setNextPlayerState(IDLE); - } public synchronized void pause() { pause(false); } + public synchronized void pause(boolean temp) { try { if (playerState == STARTED) { mediaPlayer.pause(); setPlayerState(temp ? PAUSED_TEMP : PAUSED); - } else if(playerState == PAUSED_TEMP) { + } else if (playerState == PAUSED_TEMP) { setPlayerState(temp ? PAUSED_TEMP : PAUSED); } } catch (Exception x) { @@ -1102,10 +1018,10 @@ public class DownloadService extends Service { if (playerState == STARTED) { mediaPlayer.pause(); setPlayerState(STOPPED); - } else if(playerState == PAUSED) { + } else if (playerState == PAUSED) { setPlayerState(STOPPED); } - } catch(Exception x) { + } catch (Exception x) { handleError(x); } } @@ -1113,7 +1029,7 @@ public class DownloadService extends Service { public synchronized void start() { try { // Only start if done preparing - if(playerState != PREPARING) { + if (playerState != PREPARING) { mediaPlayer.start(); } else { // Otherwise, we need to set it up to start when done preparing @@ -1134,7 +1050,7 @@ public class DownloadService extends Service { setPlayerState(IDLE); mediaPlayer.setOnErrorListener(null); mediaPlayer.setOnCompletionListener(null); - if(nextSetup) { + if (nextSetup) { mediaPlayer.setNextMediaPlayer(null); nextSetup = false; } @@ -1145,7 +1061,7 @@ public class DownloadService extends Service { } } - public synchronized void resetNext() { + private synchronized void resetNext() { try { if (nextMediaPlayer != null) { if (nextSetup) { @@ -1158,7 +1074,7 @@ public class DownloadService extends Service { nextMediaPlayer.reset(); nextMediaPlayer.release(); nextMediaPlayer = null; - } else if(nextSetup) { + } else if (nextSetup) { nextSetup = false; } } catch (Exception e) { @@ -1180,14 +1096,14 @@ public class DownloadService extends Service { public synchronized int getPlayerDuration() { if (playerState != IDLE && playerState != DOWNLOADING && playerState != PlayerState.PREPARING) { - int duration = 0; + int duration; try { duration = mediaPlayer.getDuration(); } catch (Exception x) { duration = 0; } - if(duration != 0) { + if (duration != 0) { return duration; } } @@ -1206,11 +1122,7 @@ public class DownloadService extends Service { return playerState; } - public PlayerState getNextPlayerState() { - return nextPlayerState; - } - - public synchronized void setPlayerState(final PlayerState playerState) { + private synchronized void setPlayerState(final PlayerState playerState) { Log.i(TAG, this.playerState.name() + " -> " + playerState.name() + " (" + currentPlaying + ")"); if (playerState == PAUSED) { @@ -1224,7 +1136,7 @@ public class DownloadService extends Service { this.playerState = playerState; - if(playerState == STARTED) { + if (playerState == STARTED) { Util.requestAudioFocus(this); } @@ -1232,19 +1144,19 @@ public class DownloadService extends Service { Notifications.showPlayingNotification(this, this, handler, currentPlaying.getSong()); } else if (pause) { SharedPreferences prefs = Util.getPreferences(this); - if(prefs.getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false)) { + if (prefs.getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false)) { Notifications.showPlayingNotification(this, this, handler, currentPlaying.getSong()); } else { Notifications.hidePlayingNotification(this, this, handler); } - } else if(hide) { + } else if (hide) { Notifications.hidePlayingNotification(this, this, handler); } - if(playerState == STARTED && positionCache == null) { + if (playerState == STARTED && positionCache == null) { positionCache = new LocalPositionCache(); Thread thread = new Thread(positionCache, "PositionCache"); thread.start(); - } else if(playerState != STARTED && positionCache != null) { + } else if (playerState != STARTED && positionCache != null) { positionCache.stop(); positionCache = null; } @@ -1253,13 +1165,18 @@ public class DownloadService extends Service { onStateUpdate(); } - public void setPlayerStateCompleted() { + private synchronized void setNextPlayerState(PlayerState playerState) { + Log.i(TAG, "Next: " + this.nextPlayerState.name() + " -> " + playerState.name() + " (" + nextPlaying + ")"); + this.nextPlayerState = playerState; + } + + private void setPlayerStateCompleted() { // Acquire a temporary wakelock acquireWakelock(); Log.i(TAG, this.playerState.name() + " -> " + PlayerState.COMPLETED + " (" + currentPlaying + ")"); this.playerState = PlayerState.COMPLETED; - if(positionCache != null) { + if (positionCache != null) { positionCache.stop(); positionCache = null; } @@ -1267,77 +1184,6 @@ public class DownloadService extends Service { onStateUpdate(); } - private class PositionCache implements Runnable { - boolean isRunning = true; - - public void stop() { - isRunning = false; - } - - @Override - public void run() { - // Stop checking position before the song reaches completion - while(isRunning) { - try { - onSongProgress(); - Thread.sleep(delayUpdateProgress); - } - catch(Exception e) { - isRunning = false; - positionCache = null; - } - } - } - } - private class LocalPositionCache extends PositionCache { - boolean isRunning = true; - - public void stop() { - isRunning = false; - } - - @Override - public void run() { - // Stop checking position before the song reaches completion - while(isRunning) { - try { - if(mediaPlayer != null && playerState == STARTED) { - int newPosition = mediaPlayer.getCurrentPosition(); - - // If sudden jump in position, something is wrong - if(subtractNextPosition == 0 && newPosition > (cachedPosition + 5000)) { - // Only 1 second should have gone by, subtract the rest - subtractPosition += (newPosition - cachedPosition) - 1000; - } - - cachedPosition = newPosition; - - if(subtractNextPosition > 0) { - // Subtraction amount is current position - how long ago onCompletionListener was called - subtractPosition = cachedPosition - (int) (System.currentTimeMillis() - subtractNextPosition); - if(subtractPosition < 0) { - subtractPosition = 0; - } - subtractNextPosition = 0; - } - } - onSongProgress(cachedPosition < 2000 ? true: false); - Thread.sleep(delayUpdateProgress); - } - catch(Exception e) { - Log.w(TAG, "Crashed getting current position", e); - isRunning = false; - positionCache = null; - } - } - } - } - - public synchronized void setNextPlayerState(PlayerState playerState) { - Log.i(TAG, "Next: " + this.nextPlayerState.name() + " -> " + playerState.name() + " (" + nextPlaying + ")"); - this.nextPlayerState = playerState; - } - public void setSuggestedPlaylistName(String name, String id) { this.suggestedPlaylistName = name; this.suggestedPlaylistId = id; @@ -1357,17 +1203,16 @@ public class DownloadService extends Service { } public EqualizerController getEqualizerController() { - EqualizerController controller = null; + EqualizerController controller; try { controller = effectsController.getEqualizerController(); - if(controller.getEqualizer() == null) { + if (controller.getEqualizer() == null) { throw new Exception("Failed to get EQ"); } - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to start EQ, retrying with new mediaPlayer: " + e); // If we failed, we are going to try to reinitialize the MediaPlayer - boolean playing = playerState == STARTED; int pos = getPlayerPosition(); mediaPlayer.pause(); Util.sleepQuietly(10L); @@ -1379,10 +1224,10 @@ public class DownloadService extends Service { mediaPlayer.setDataSource(currentPlaying.getFile().getCanonicalPath()); controller = effectsController.getEqualizerController(); - if(controller.getEqualizer() == null) { + if (controller.getEqualizer() == null) { throw new Exception("Failed to get EQ"); } - } catch(Exception e2) { + } catch (Exception e2) { Log.w(TAG, "Failed to setup EQ even after reinitialization"); // Don't try again, just resetup media player and continue on controller = null; @@ -1395,30 +1240,19 @@ public class DownloadService extends Service { return controller; } - public boolean isSeekable() { + private boolean isSeekable() { return currentPlaying != null && currentPlaying.isWorkDone() && playerState != PREPARING; } - public void updateRemoteVolume(boolean up) { - AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); - audioManager.adjustVolume(up ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER, AudioManager.FLAG_SHOW_UI); - } - - private synchronized void bufferAndPlay() { - bufferAndPlay(0); - } - private synchronized void bufferAndPlay(int position) { - bufferAndPlay(position, true); - } private synchronized void bufferAndPlay(int position, boolean start) { - if(!currentPlaying.isCompleteFileAvailable()) { - if(Util.isAllowedToDownload(this)) { + if (!currentPlaying.isCompleteFileAvailable()) { + if (Util.isAllowedToDownload(this)) { reset(); bufferTask = new BufferTask(currentPlaying, position, start); bufferTask.execute(); } else { - next(false, start); + next(start); } } else { doPlay(currentPlaying, position, start); @@ -1435,12 +1269,12 @@ public class DownloadService extends Service { setPlayerState(IDLE); try { mediaPlayer.setAudioSessionId(audioSessionId); - } catch(Throwable e) { + } catch (Throwable e) { mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); } String dataSource; - boolean isPartial = false; + boolean isPartial; downloadFile.setPlaying(true); final File file = downloadFile.isCompleteFileAvailable() ? downloadFile.getCompleteFile() : downloadFile.getPartialFile(); isPartial = file.equals(downloadFile.getPartialFile()); @@ -1449,7 +1283,7 @@ public class DownloadService extends Service { dataSource = file.getAbsolutePath(); if (isPartial && !Util.isOffline(this)) { if (proxy == null) { - proxy = new BufferProxy(this); + proxy = new BufferProxy(); proxy.start(); } proxy.setBufferFile(downloadFile); @@ -1463,50 +1297,46 @@ public class DownloadService extends Service { mediaPlayer.setDataSource(dataSource); setPlayerState(PREPARING); - mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() { - public void onBufferingUpdate(MediaPlayer mp, int percent) { - Log.i(TAG, "Buffered " + percent + "%"); - if (percent == 100) { - mediaPlayer.setOnBufferingUpdateListener(null); - } + mediaPlayer.setOnBufferingUpdateListener((mp, percent) -> { + Log.i(TAG, "Buffered " + percent + "%"); + if (percent == 100) { + mediaPlayer.setOnBufferingUpdateListener(null); } }); - mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { - public void onPrepared(MediaPlayer mediaPlayer) { - try { - setPlayerState(PREPARED); + mediaPlayer.setOnPreparedListener(mediaPlayer -> { + try { + setPlayerState(PREPARED); - synchronized (DownloadService.this) { - if (position != 0) { - Log.i(TAG, "Restarting player from position " + position); - mediaPlayer.seekTo(position); - } - cachedPosition = position; + synchronized (DownloadService.this) { + if (position != 0) { + Log.i(TAG, "Restarting player from position " + position); + mediaPlayer.seekTo(position); + } + cachedPosition = position; - applyReplayGain(mediaPlayer, downloadFile); + applyReplayGain(mediaPlayer, downloadFile); - if (start || autoPlayStart) { - mediaPlayer.start(); - setPlayerState(STARTED); + if (start || autoPlayStart) { + mediaPlayer.start(); + setPlayerState(STARTED); - // Disable autoPlayStart after done - autoPlayStart = false; - } else { - setPlayerState(PAUSED); - onSongProgress(); - } - - updateRemotePlaylist(); + // Disable autoPlayStart after done + autoPlayStart = false; + } else { + setPlayerState(PAUSED); + onSongProgress(); } - // Only call when starting, setPlayerState(PAUSED) already calls this - if(start) { - lifecycleSupport.serializeDownloadQueue(); - } - } catch (Exception x) { - handleError(x); + updateRemotePlaylist(); } + + // Only call when starting, setPlayerState(PAUSED) already calls this + if (start) { + lifecycleSupport.serializeDownloadQueue(); + } + } catch (Exception x) { + handleError(x); } }); @@ -1527,39 +1357,35 @@ public class DownloadService extends Service { nextMediaPlayer.setWakeMode(DownloadService.this, PowerManager.PARTIAL_WAKE_LOCK); try { nextMediaPlayer.setAudioSessionId(audioSessionId); - } catch(Throwable e) { + } catch (Throwable e) { nextMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); } nextMediaPlayer.setDataSource(file.getPath()); setNextPlayerState(PREPARING); - nextMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { - public void onPrepared(MediaPlayer mp) { - // Changed to different while preparing so ignore - if(nextMediaPlayer != mp) { - return; + nextMediaPlayer.setOnPreparedListener(mp -> { + // Changed to different while preparing so ignore + if (nextMediaPlayer != mp) { + return; + } + + try { + setNextPlayerState(PREPARED); + + if (playerState == PlayerState.STARTED || playerState == PlayerState.PAUSED) { + mediaPlayer.setNextMediaPlayer(nextMediaPlayer); + nextSetup = true; } - try { - setNextPlayerState(PREPARED); - - if(playerState == PlayerState.STARTED || playerState == PlayerState.PAUSED) { - mediaPlayer.setNextMediaPlayer(nextMediaPlayer); - nextSetup = true; - } - - applyReplayGain(nextMediaPlayer, downloadFile); - } catch (Exception x) { - handleErrorNext(x); - } + applyReplayGain(nextMediaPlayer, downloadFile); + } catch (Exception x) { + handleErrorNext(x); } }); - nextMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { - public boolean onError(MediaPlayer mediaPlayer, int what, int extra) { - Log.w(TAG, "Error on playing next " + "(" + what + ", " + extra + "): " + downloadFile); - return true; - } + nextMediaPlayer.setOnErrorListener((mediaPlayer, what, extra) -> { + Log.w(TAG, "Error on playing next " + "(" + what + ", " + extra + "): " + downloadFile); + return true; }); nextMediaPlayer.prepareAsync(); @@ -1570,61 +1396,55 @@ public class DownloadService extends Service { private void setupHandlers(final DownloadFile downloadFile, final boolean isPartial, final boolean isPlaying) { final int duration = downloadFile.getSong().getDuration() == null ? 0 : downloadFile.getSong().getDuration() * 1000; - mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { - public boolean onError(MediaPlayer mediaPlayer, int what, int extra) { - Log.w(TAG, "Error on playing file " + "(" + what + ", " + extra + "): " + downloadFile); - int pos = getPlayerPosition(); - reset(); - if (!isPartial || (downloadFile.isWorkDone() && (Math.abs(duration - pos) < 10000))) { - playNext(); - } else { - downloadFile.setPlaying(false); - doPlay(downloadFile, pos, isPlaying); - downloadFile.setPlaying(true); - } - return true; + mediaPlayer.setOnErrorListener((mediaPlayer, what, extra) -> { + Log.w(TAG, "Error on playing file " + "(" + what + ", " + extra + "): " + downloadFile); + int pos = getPlayerPosition(); + reset(); + if (!isPartial || (downloadFile.isWorkDone() && (Math.abs(duration - pos) < 10000))) { + playNext(); + } else { + downloadFile.setPlaying(false); + doPlay(downloadFile, pos, isPlaying); + downloadFile.setPlaying(true); } + return true; }); - mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { - @Override - public void onCompletion(MediaPlayer mediaPlayer) { - setPlayerStateCompleted(); + mediaPlayer.setOnCompletionListener(mediaPlayer -> { + setPlayerStateCompleted(); - int pos = getPlayerPosition(); - Log.i(TAG, "Ending position " + pos + " of " + duration); - if (!isPartial || (downloadFile.isWorkDone() && (Math.abs(duration - pos) < 10000)) || nextSetup) { - playNext(); - postPlayCleanup(downloadFile); - } else { - // If file is not completely downloaded, restart the playback from the current position. - synchronized (DownloadService.this) { - if (downloadFile.isWorkDone()) { - // Complete was called early even though file is fully buffered - Log.i(TAG, "Requesting restart from " + pos + " of " + duration); - reset(); - downloadFile.setPlaying(false); - doPlay(downloadFile, pos, true); - downloadFile.setPlaying(true); - } else { - Log.i(TAG, "Requesting restart from " + pos + " of " + duration); - reset(); - bufferTask = new BufferTask(downloadFile, pos, true); - bufferTask.execute(); - } + int pos = getPlayerPosition(); + Log.i(TAG, "Ending position " + pos + " of " + duration); + if (!isPartial || (downloadFile.isWorkDone() && (Math.abs(duration - pos) < 10000)) || nextSetup) { + playNext(); + } else { + // If file is not completely downloaded, restart the playback from the current position. + synchronized (DownloadService.this) { + if (downloadFile.isWorkDone()) { + // Complete was called early even though file is fully buffered + Log.i(TAG, "Requesting restart from " + pos + " of " + duration); + reset(); + downloadFile.setPlaying(false); + doPlay(downloadFile, pos, true); + downloadFile.setPlaying(true); + } else { + Log.i(TAG, "Requesting restart from " + pos + " of " + duration); + reset(); + bufferTask = new BufferTask(downloadFile, pos, true); + bufferTask.execute(); } - checkDownloads(); } + checkDownloads(); } }); } public void setVolume(float volume) { - if(mediaPlayer != null && (playerState == STARTED || playerState == PAUSED || playerState == STOPPED)) { + if (mediaPlayer != null && (playerState == STARTED || playerState == PAUSED || playerState == STOPPED)) { try { this.volume = volume; reapplyVolume(); - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to set volume"); } } @@ -1634,56 +1454,49 @@ public class DownloadService extends Service { applyReplayGain(mediaPlayer, currentPlaying); } - public synchronized void swap(boolean mainList, DownloadFile from, DownloadFile to) { - List list = mainList ? downloadList : backgroundDownloadList; - swap(mainList, list.indexOf(from), list.indexOf(to)); - } public synchronized void swap(boolean mainList, int from, int to) { List list = mainList ? downloadList : backgroundDownloadList; int max = list.size(); - if(to >= max) { + if (to >= max) { to = max - 1; - } - else if(to < 0) { + } else if (to < 0) { to = 0; } DownloadFile movedSong = list.remove(from); list.add(to, movedSong); currentPlayingIndex = downloadList.indexOf(currentPlaying); - if(mainList) { + if (mainList) { // Moving next playing, current playing, or moving a song to be next playing - if(movedSong == nextPlaying || movedSong == currentPlaying || (currentPlayingIndex + 1) == to) { + if (movedSong == nextPlaying || movedSong == currentPlaying || (currentPlayingIndex + 1) == to) { setNextPlaying(); } } } public synchronized void serializeQueue() { - serializeQueue(true); - } - public synchronized void serializeQueue(boolean serializeRemote) { - if(playerState == PlayerState.PAUSED) { - lifecycleSupport.serializeDownloadQueue(serializeRemote); + if (playerState == PlayerState.PAUSED) { + lifecycleSupport.serializeDownloadQueue(); } } private void handleError(Exception x) { Log.w(TAG, "Media player error: " + x, x); - if(mediaPlayer != null) { + if (mediaPlayer != null) { try { mediaPlayer.reset(); - } catch(Exception e) { + } catch (Exception e) { Log.e(TAG, "Failed to reset player in error handler"); } } setPlayerState(IDLE); } + private void handleErrorNext(Exception x) { Log.w(TAG, "Next Media player error: " + x, x); try { nextMediaPlayer.reset(); - } catch(Exception e) { + } catch (Exception e) { Log.e(TAG, "Failed to reset next media player", x); } setNextPlayerState(IDLE); @@ -1694,7 +1507,7 @@ public class DownloadService extends Service { return; } - if(removePlayed) { + if (removePlayed) { checkRemovePlayed(); } if (shufflePlay) { @@ -1728,9 +1541,9 @@ public class DownloadService extends Service { int preloaded = 0; - if(n != 0) { + if (n != 0) { int start = currentPlaying == null ? 0 : getCurrentPlayingIndex(); - if(start == -1) { + if (start == -1) { start = 0; } int i = start; @@ -1741,7 +1554,7 @@ public class DownloadService extends Service { currentDownloading = downloadFile; currentDownloading.download(); cleanupCandidates.add(currentDownloading); - if(i == (start + 1)) { + if (i == (start + 1)) { setNextPlayerState(DOWNLOADING); } break; @@ -1754,10 +1567,10 @@ public class DownloadService extends Service { } while (i != start); } - if((preloaded + 1 == n || preloaded >= Util.getPreloadCount(this) || downloadList.isEmpty()) && !backgroundDownloadList.isEmpty()) { - for(int i = 0; i < backgroundDownloadList.size(); i++) { + if ((preloaded + 1 == n || preloaded >= Util.getPreloadCount(this) || downloadList.isEmpty()) && !backgroundDownloadList.isEmpty()) { + for (int i = 0; i < backgroundDownloadList.size(); i++) { DownloadFile downloadFile = backgroundDownloadList.get(i); - if(downloadFile.isWorkDone() && (!downloadFile.shouldSave() || downloadFile.isSaved()) || downloadFile.isFailedMax()) { + if (downloadFile.isWorkDone() && (!downloadFile.shouldSave() || downloadFile.isSaved()) || downloadFile.isFailedMax()) { // Don't need to keep list like active song list backgroundDownloadList.remove(i); revision++; @@ -1772,10 +1585,10 @@ public class DownloadService extends Service { } } - if(!backgroundDownloadList.isEmpty()) { + if (!backgroundDownloadList.isEmpty()) { Notifications.showDownloadingNotification(this, this, handler, currentDownloading, backgroundDownloadList.size()); downloadOngoing = true; - } else if(backgroundDownloadList.isEmpty() && downloadOngoing) { + } else if (backgroundDownloadList.isEmpty() && downloadOngoing) { Notifications.hideDownloadingNotification(this, this, handler); downloadOngoing = false; } @@ -1788,13 +1601,13 @@ public class DownloadService extends Service { boolean changed = false; SharedPreferences prefs = Util.getPreferences(this); int keepCount = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_KEEP_PLAYED_CNT, "0")); - while(currentPlayingIndex > keepCount) { + while (currentPlayingIndex > keepCount) { downloadList.remove(0); currentPlayingIndex = downloadList.indexOf(currentPlaying); changed = true; } - if(changed) { + if (changed) { revision++; onSongsChanged(); } @@ -1859,35 +1672,8 @@ public class DownloadService extends Service { } } - public void postPlayCleanup() { - postPlayCleanup(currentPlaying); - } - public void postPlayCleanup(DownloadFile downloadFile) { - if(downloadFile == null) { - return; - } - } - - private boolean isPastCutoff() { - return isPastCutoff(getPlayerPosition(), getPlayerDuration()); - } - private boolean isPastCutoff(int position, int duration) { - return isPastCutoff(position, duration, false); - } - private boolean isPastCutoff(int position, int duration, boolean allowSkipping) { - if(currentPlaying == null) { - return false; - } - - // Make cutoff a maximum of 10 minutes - int cutoffPoint = Math.max((int) (duration * DELETE_CUTOFF), duration - 10 * 60 * 1000); - boolean isPastCutoff = duration > 0 && position > cutoffPoint; - - return isPastCutoff; - } - private void applyReplayGain(MediaPlayer mediaPlayer, DownloadFile downloadFile) { - if(currentPlaying == null) { + if (currentPlaying == null) { return; } @@ -1900,17 +1686,17 @@ public class DownloadService extends Service { String replayGainType = prefs.getString(Constants.PREFERENCES_KEY_REPLAY_GAIN_TYPE, "1"); // 1 => Smart replay gain - if("1".equals(replayGainType)) { + if ("1".equals(replayGainType)) { // Check if part of at least consequetive songs of the same album int index = downloadList.indexOf(downloadFile); - if(index != -1) { + if (index != -1) { String albumName = downloadFile.getSong().getAlbum(); int matched = 0; // Check forwards - for(int i = index + 1; i < downloadList.size() && matched < REQUIRED_ALBUM_MATCHES; i++) { - if(albumName.equals(downloadList.get(i).getSong().getAlbum())) { + for (int i = index + 1; i < downloadList.size() && matched < REQUIRED_ALBUM_MATCHES; i++) { + if (albumName.equals(downloadList.get(i).getSong().getAlbum())) { matched++; } else { break; @@ -1918,21 +1704,21 @@ public class DownloadService extends Service { } // Check backwards - for(int i = index - 1; i >= 0 && matched < REQUIRED_ALBUM_MATCHES; i--) { - if(albumName.equals(downloadList.get(i).getSong().getAlbum())) { + for (int i = index - 1; i >= 0 && matched < REQUIRED_ALBUM_MATCHES; i--) { + if (albumName.equals(downloadList.get(i).getSong().getAlbum())) { matched++; } else { break; } } - if(matched >= REQUIRED_ALBUM_MATCHES) { + if (matched >= REQUIRED_ALBUM_MATCHES) { singleAlbum = true; } } } // 2 => Use album tags - else if("2".equals(replayGainType)) { + else if ("2".equals(replayGainType)) { singleAlbum = true; } // 3 => Use track tags @@ -1940,7 +1726,7 @@ public class DownloadService extends Service { // If playing a single album or no track gain, use album gain - if((singleAlbum || rg[0] == 0) && rg[1] != 0) { + if ((singleAlbum || rg[0] == 0) && rg[1] != 0) { adjust = rg[1]; } else { // Otherwise, give priority to track gain @@ -1964,62 +1750,37 @@ public class DownloadService extends Service { rg_result = 0.0f; } mediaPlayer.setVolume(rg_result, rg_result); - } catch(IOException e) { + } catch (IOException e) { Log.w(TAG, "Failed to apply replay gain values", e); } } - private synchronized boolean isNextPlayingSameAlbum() { - return isNextPlayingSameAlbum(currentPlaying, nextPlaying); - } - private synchronized boolean isNextPlayingSameAlbum(DownloadFile currentPlaying, DownloadFile nextPlaying) { - if(currentPlaying == null || nextPlaying == null) { - return false; - } else { - return currentPlaying.getSong().getAlbum().equals(nextPlaying.getSong().getAlbum()); - } - } - - public void acquireWakelock() { - acquireWakelock(30000); - } - public void acquireWakelock(int ms) { - wakeLock.acquire(ms); - } - - public void handleKeyEvent(KeyEvent keyEvent) { - lifecycleSupport.handleKeyEvent(keyEvent); + private void acquireWakelock() { + wakeLock.acquire(30000); } public void addOnSongChangedListener(OnSongChangedListener listener) { - addOnSongChangedListener(listener, false); - } - public void addOnSongChangedListener(OnSongChangedListener listener, boolean run) { - synchronized(onSongChangedListeners) { + synchronized (onSongChangedListeners) { int index = onSongChangedListeners.indexOf(listener); if (index == -1) { onSongChangedListeners.add(listener); } } - if(run) { - if(mediaPlayerHandler != null) { - mediaPlayerHandler.post(new Runnable() { - @Override - public void run() { - onSongsChanged(); - onSongProgress(); - onStateUpdate(); - onMetadataUpdate(METADATA_UPDATED_ALL); - } - }); - } else { - runListenersOnInit = true; - } + if (mediaPlayerHandler != null) { + mediaPlayerHandler.post(() -> { + onSongsChanged(); + onSongProgress(); + onStateUpdate(); + onMetadataUpdate(METADATA_UPDATED_ALL); + }); + } else { + runListenersOnInit = true; } } + public void removeOnSongChangeListener(OnSongChangedListener listener) { - synchronized(onSongChangedListeners) { + synchronized (onSongChangedListeners) { int index = onSongChangedListeners.indexOf(listener); if (index != -1) { onSongChangedListeners.remove(index); @@ -2029,41 +1790,31 @@ public class DownloadService extends Service { private void onSongChanged() { final long atRevision = revision; - synchronized(onSongChangedListeners) { + synchronized (onSongChangedListeners) { for (final OnSongChangedListener listener : onSongChangedListeners) { - handler.post(new Runnable() { - @Override - public void run() { - if (revision == atRevision && instance != null) { - listener.onSongChanged(currentPlaying, currentPlayingIndex); + handler.post(() -> { + if (revision == atRevision && instance != null) { + listener.onSongChanged(currentPlaying, currentPlayingIndex); - MusicDirectory.Entry entry = currentPlaying != null ? currentPlaying.getSong() : null; - listener.onMetadataUpdate(entry, METADATA_UPDATED_ALL); - } + MusicDirectory.Entry entry = currentPlaying != null ? currentPlaying.getSong() : null; + listener.onMetadataUpdate(entry, METADATA_UPDATED_ALL); } }); } if (mediaPlayerHandler != null && !onSongChangedListeners.isEmpty()) { - mediaPlayerHandler.post(new Runnable() { - @Override - public void run() { - onSongProgress(); - } - }); + mediaPlayerHandler.post(this::onSongProgress); } } } + private void onSongsChanged() { final long atRevision = revision; - synchronized(onSongChangedListeners) { + synchronized (onSongChangedListeners) { for (final OnSongChangedListener listener : onSongChangedListeners) { - handler.post(new Runnable() { - @Override - public void run() { - if (revision == atRevision && instance != null) { - listener.onSongsChanged(downloadList, currentPlaying, currentPlayingIndex); - } + handler.post(() -> { + if (revision == atRevision && instance != null) { + listener.onSongsChanged(downloadList, currentPlaying, currentPlayingIndex); } }); } @@ -2073,73 +1824,135 @@ public class DownloadService extends Service { private void onSongProgress() { onSongProgress(true); } + private synchronized void onSongProgress(boolean manual) { final long atRevision = revision; final Integer duration = getPlayerDuration(); final boolean isSeekable = isSeekable(); final int position = getPlayerPosition(); - synchronized(onSongChangedListeners) { + synchronized (onSongChangedListeners) { for (final OnSongChangedListener listener : onSongChangedListeners) { - handler.post(new Runnable() { - @Override - public void run() { - if (revision == atRevision && instance != null) { - listener.onSongProgress(currentPlaying, position, duration, isSeekable); - } + handler.post(() -> { + if (revision == atRevision && instance != null) { + listener.onSongProgress(currentPlaying, position, duration, isSeekable); } }); } } - if(manual) { - handler.post(new Runnable() { - @Override - public void run() { - } + if (manual) { + handler.post(() -> { }); } } + private void onStateUpdate() { final long atRevision = revision; - synchronized(onSongChangedListeners) { + synchronized (onSongChangedListeners) { for (final OnSongChangedListener listener : onSongChangedListeners) { - handler.post(new Runnable() { - @Override - public void run() { - if (revision == atRevision && instance != null) { - listener.onStateUpdate(currentPlaying, playerState); - } + handler.post(() -> { + if (revision == atRevision && instance != null) { + listener.onStateUpdate(playerState); } }); } } } - public void onMetadataUpdate() { - onMetadataUpdate(METADATA_UPDATED_ALL); - } + public void onMetadataUpdate(final int updateType) { - synchronized(onSongChangedListeners) { + synchronized (onSongChangedListeners) { for (final OnSongChangedListener listener : onSongChangedListeners) { - handler.post(new Runnable() { - @Override - public void run() { - if (instance != null) { - MusicDirectory.Entry entry = currentPlaying != null ? currentPlaying.getSong() : null; - listener.onMetadataUpdate(entry, updateType); - } + handler.post(() -> { + if (instance != null) { + MusicDirectory.Entry entry = currentPlaying != null ? currentPlaying.getSong() : null; + listener.onMetadataUpdate(entry, updateType); } }); } } - handler.post(new Runnable() { - @Override - public void run() { - } + handler.post(() -> { }); } + public interface OnSongChangedListener { + void onSongChanged(DownloadFile currentPlaying, int currentPlayingIndex); + + void onSongsChanged(List songs, DownloadFile currentPlaying, int currentPlayingIndex); + + void onSongProgress(DownloadFile currentPlaying, int millisPlayed, Integer duration, boolean isSeekable); + + void onStateUpdate(PlayerState playerState); + + void onMetadataUpdate(MusicDirectory.Entry entry, int fieldChange); + } + + private class PositionCache implements Runnable { + boolean isRunning = true; + + public void stop() { + isRunning = false; + } + + @Override + public void run() { + // Stop checking position before the song reaches completion + while (isRunning) { + try { + onSongProgress(); + Thread.sleep(delayUpdateProgress); + } catch (Exception e) { + isRunning = false; + positionCache = null; + } + } + } + } + + private class LocalPositionCache extends PositionCache { + boolean isRunning = true; + + public void stop() { + isRunning = false; + } + + @Override + public void run() { + // Stop checking position before the song reaches completion + while (isRunning) { + try { + if (mediaPlayer != null && playerState == STARTED) { + int newPosition = mediaPlayer.getCurrentPosition(); + + // If sudden jump in position, something is wrong + if (subtractNextPosition == 0 && newPosition > (cachedPosition + 5000)) { + // Only 1 second should have gone by, subtract the rest + subtractPosition += (newPosition - cachedPosition) - 1000; + } + + cachedPosition = newPosition; + + if (subtractNextPosition > 0) { + // Subtraction amount is current position - how long ago onCompletionListener was called + subtractPosition = cachedPosition - (int) (System.currentTimeMillis() - subtractNextPosition); + if (subtractPosition < 0) { + subtractPosition = 0; + } + subtractNextPosition = 0; + } + } + onSongProgress(cachedPosition < 2000); + Thread.sleep(delayUpdateProgress); + } catch (Exception e) { + Log.w(TAG, "Crashed getting current position", e); + isRunning = false; + positionCache = null; + } + } + } + } + private class BufferTask extends SilentBackgroundTask { private final DownloadFile downloadFile; private final int position; @@ -2171,7 +1984,7 @@ public class DownloadService extends Service { Thread.sleep(1000L); if (isCancelled() || downloadFile.isFailedMax()) { return null; - } else if(!downloadFile.isFailedMax() && !downloadFile.isDownloading()) { + } else if (!downloadFile.isFailedMax() && !downloadFile.isDownloading()) { checkDownloads(); } } @@ -2201,7 +2014,7 @@ public class DownloadService extends Service { public CheckCompletionTask(DownloadFile downloadFile) { super(instance); this.downloadFile = downloadFile; - if(downloadFile != null) { + if (downloadFile != null) { partialFile = downloadFile.getPartialFile(); } else { partialFile = null; @@ -2209,8 +2022,8 @@ public class DownloadService extends Service { } @Override - public Void doInBackground() throws InterruptedException { - if(downloadFile == null) { + public Void doInBackground() throws InterruptedException { + if (downloadFile == null) { return null; } @@ -2224,11 +2037,9 @@ public class DownloadService extends Service { } // Start the setup of the next media player - mediaPlayerHandler.post(new Runnable() { - public void run() { - if(!CheckCompletionTask.this.isCancelled()) { - setupNext(downloadFile); - } + mediaPlayerHandler.post(() -> { + if (!CheckCompletionTask.this.isCancelled()) { + setupNext(downloadFile); } }); return null; @@ -2245,12 +2056,4 @@ public class DownloadService extends Service { return "CheckCompletionTask (" + downloadFile + ")"; } } - - public interface OnSongChangedListener { - void onSongChanged(DownloadFile currentPlaying, int currentPlayingIndex); - void onSongsChanged(List songs, DownloadFile currentPlaying, int currentPlayingIndex); - void onSongProgress(DownloadFile currentPlaying, int millisPlayed, Integer duration, boolean isSeekable); - void onStateUpdate(DownloadFile downloadFile, PlayerState playerState); - void onMetadataUpdate(MusicDirectory.Entry entry, int fieldChange); - } } diff --git a/app/src/main/java/net/nullsum/audinaut/service/DownloadServiceLifecycleSupport.java b/app/src/main/java/net/nullsum/audinaut/service/DownloadServiceLifecycleSupport.java index caa05a6..81b7ac0 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/DownloadServiceLifecycleSupport.java +++ b/app/src/main/java/net/nullsum/audinaut/service/DownloadServiceLifecycleSupport.java @@ -18,12 +18,6 @@ */ package net.nullsum.audinaut.service; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.concurrent.locks.ReentrantLock; -import java.util.concurrent.atomic.AtomicBoolean; - import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -36,64 +30,60 @@ import android.telephony.TelephonyManager; import android.util.Log; import android.view.KeyEvent; -import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.domain.PlayerQueue; import net.nullsum.audinaut.domain.PlayerState; import net.nullsum.audinaut.util.CacheCleaner; import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.FileUtil; -import net.nullsum.audinaut.util.Pair; -import net.nullsum.audinaut.util.SilentBackgroundTask; -import net.nullsum.audinaut.util.SongDBHandler; import net.nullsum.audinaut.util.Util; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.ReentrantLock; + import static net.nullsum.audinaut.domain.PlayerState.PREPARING; /** * @author Sindre Mehus */ public class DownloadServiceLifecycleSupport { - private static final String TAG = DownloadServiceLifecycleSupport.class.getSimpleName(); public static final String FILENAME_DOWNLOADS_SER = "downloadstate2.ser"; + private static final String TAG = DownloadServiceLifecycleSupport.class.getSimpleName(); private static final int DEBOUNCE_TIME = 200; private final DownloadService downloadService; + private final AtomicBoolean setup = new AtomicBoolean(false); + private final ReentrantLock lock = new ReentrantLock(); private Looper eventLooper; private Handler eventHandler; private BroadcastReceiver ejectEventReceiver; private PhoneStateListener phoneStateListener; - private boolean externalStorageAvailable= true; - private ReentrantLock lock = new ReentrantLock(); - private final AtomicBoolean setup = new AtomicBoolean(false); + private boolean externalStorageAvailable = true; private long lastPressTime = 0; - private SilentBackgroundTask currentSavePlayQueueTask = null; - private Date lastChange = null; /** * This receiver manages the intent that could come from other applications. */ - private BroadcastReceiver intentReceiver = new BroadcastReceiver() { + private final BroadcastReceiver intentReceiver = new BroadcastReceiver() { @Override public void onReceive(final Context context, final Intent intent) { - eventHandler.post(new Runnable() { - @Override - public void run() { - String action = intent.getAction(); - Log.i(TAG, "intentReceiver.onReceive: " + action); - if (DownloadService.CMD_PLAY.equals(action)) { - downloadService.play(); - } else if (DownloadService.CMD_NEXT.equals(action)) { - downloadService.next(); - } else if (DownloadService.CMD_PREVIOUS.equals(action)) { - downloadService.previous(); - } else if (DownloadService.CMD_TOGGLEPAUSE.equals(action)) { - downloadService.togglePlayPause(); - } else if (DownloadService.CMD_PAUSE.equals(action)) { - downloadService.pause(); - } else if (DownloadService.CMD_STOP.equals(action)) { - downloadService.pause(); - downloadService.seekTo(0); - } + eventHandler.post(() -> { + String action = intent.getAction(); + Log.i(TAG, "intentReceiver.onReceive: " + action); + if (DownloadService.CMD_PLAY.equals(action)) { + downloadService.play(); + } else if (DownloadService.CMD_NEXT.equals(action)) { + downloadService.next(); + } else if (DownloadService.CMD_PREVIOUS.equals(action)) { + downloadService.previous(); + } else if (DownloadService.CMD_TOGGLEPAUSE.equals(action)) { + downloadService.togglePlayPause(); + } else if (DownloadService.CMD_PAUSE.equals(action)) { + downloadService.pause(); + } else if (DownloadService.CMD_STOP.equals(action)) { + downloadService.pause(); + downloadService.seekTo(0); } }); } @@ -105,30 +95,27 @@ public class DownloadServiceLifecycleSupport { } public void onCreate() { - new Thread(new Runnable() { - @Override - public void run() { - Looper.prepare(); - eventLooper = Looper.myLooper(); - eventHandler = new Handler(eventLooper); + new Thread(() -> { + Looper.prepare(); + eventLooper = Looper.myLooper(); + eventHandler = new Handler(eventLooper); - // Deserialize queue before starting looper - try { - lock.lock(); - deserializeDownloadQueueNow(); + // Deserialize queue before starting looper + try { + lock.lock(); + deserializeDownloadQueueNow(); - // Wait until PREPARING is done to mark lifecycle as ready to receive events - while(downloadService.getPlayerState() == PREPARING) { - Util.sleepQuietly(50L); - } - - setup.set(true); - } finally { - lock.unlock(); + // Wait until PREPARING is done to mark lifecycle as ready to receive events + while (downloadService.getPlayerState() == PREPARING) { + Util.sleepQuietly(50L); } - Looper.loop(); + setup.set(true); + } finally { + lock.unlock(); } + + Looper.loop(); }, "DownloadServiceLifecycleSupport").start(); // Stop when SD card is ejected. @@ -181,70 +168,67 @@ public class DownloadServiceLifecycleSupport { if (intent != null) { final String action = intent.getAction(); - if(eventHandler == null) { + if (eventHandler == null) { Util.sleepQuietly(100L); } - if(eventHandler == null) { + if (eventHandler == null) { return; } - eventHandler.post(new Runnable() { - @Override - public void run() { - if(!setup.get()) { - lock.lock(); - lock.unlock(); + eventHandler.post(() -> { + if (!setup.get()) { + lock.lock(); + lock.unlock(); + } + + if (DownloadService.START_PLAY.equals(action)) { + int offlinePref = intent.getIntExtra(Constants.PREFERENCES_KEY_OFFLINE, 0); + if (offlinePref != 0) { + boolean offline = (offlinePref == 2); + Util.setOffline(downloadService, offline); + if (offline) { + downloadService.clearIncomplete(); + } else { + downloadService.checkDownloads(); + } } - if(DownloadService.START_PLAY.equals(action)) { - int offlinePref = intent.getIntExtra(Constants.PREFERENCES_KEY_OFFLINE, 0); - if(offlinePref != 0) { - boolean offline = (offlinePref == 2); - Util.setOffline(downloadService, offline); - if (offline) { - downloadService.clearIncomplete(); - } else { - downloadService.checkDownloads(); - } + if (intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, false)) { + // Add shuffle parameters + SharedPreferences.Editor editor = Util.getPreferences(downloadService).edit(); + String startYear = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR); + if (startYear != null) { + editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, startYear); } - if(intent.getBooleanExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, false)) { - // Add shuffle parameters - SharedPreferences.Editor editor = Util.getPreferences(downloadService).edit(); - String startYear = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR); - if(startYear != null) { - editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, startYear); - } - - String endYear = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR); - if(endYear != null) { - editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, endYear); - } - - String genre = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_GENRE); - if(genre != null) { - editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, genre); - } - editor.apply(); - - downloadService.clear(); - downloadService.setShufflePlayEnabled(true); - } else { - downloadService.start(); + String endYear = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR); + if (endYear != null) { + editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, endYear); } - } else if(DownloadService.CMD_TOGGLEPAUSE.equals(action)) { - downloadService.togglePlayPause(); - } else if(DownloadService.CMD_NEXT.equals(action)) { - downloadService.next(); - } else if(DownloadService.CMD_PREVIOUS.equals(action)) { - downloadService.previous(); - } else if(DownloadService.CANCEL_DOWNLOADS.equals(action)) { - downloadService.clearBackground(); - } else if(intent.getExtras() != null) { - final KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT); - if (event != null) { - handleKeyEvent(event); + + String genre = intent.getStringExtra(Constants.PREFERENCES_KEY_SHUFFLE_GENRE); + if (genre != null) { + editor.putString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, genre); } + editor.apply(); + + downloadService.clear(); + downloadService.setShufflePlayEnabled(true); + } else { + downloadService.start(); + } + } else if (DownloadService.CMD_TOGGLEPAUSE.equals(action)) { + downloadService.togglePlayPause(); + } else if (DownloadService.CMD_NEXT.equals(action)) { + downloadService.next(); + } else if (DownloadService.CMD_PREVIOUS.equals(action)) { + downloadService.previous(); + } else if (DownloadService.CANCEL_DOWNLOADS.equals(action)) { + downloadService.clearBackground(); + } else if (intent.getExtras() != null) { + final KeyEvent event = (KeyEvent) intent.getExtras().get(Intent.EXTRA_KEY_EVENT); + if (event != null) { + handleKeyEvent(event); } } }); @@ -266,29 +250,23 @@ public class DownloadServiceLifecycleSupport { } public void serializeDownloadQueue() { - serializeDownloadQueue(true); - } - public void serializeDownloadQueue(final boolean serializeRemote) { - if(!setup.get()) { + if (!setup.get()) { return; } - final List songs = new ArrayList(downloadService.getSongs()); - eventHandler.post(new Runnable() { - @Override - public void run() { - if(lock.tryLock()) { - try { - serializeDownloadQueueNow(songs, serializeRemote); - } finally { - lock.unlock(); - } + final List songs = new ArrayList<>(downloadService.getSongs()); + eventHandler.post(() -> { + if (lock.tryLock()) { + try { + serializeDownloadQueueNow(songs); + } finally { + lock.unlock(); } } }); } - public void serializeDownloadQueueNow(List songs, boolean serializeRemote) { + private void serializeDownloadQueueNow(List songs) { final PlayerQueue state = new PlayerQueue(); for (DownloadFile downloadFile : songs) { state.songs.add(downloadFile.getSong()); @@ -300,11 +278,9 @@ public class DownloadServiceLifecycleSupport { state.currentPlayingPosition = downloadService.getPlayerPosition(); DownloadFile currentPlaying = downloadService.getCurrentPlaying(); - if(currentPlaying != null) { + if (currentPlaying != null) { state.renameCurrent = currentPlaying.isWorkDone() && !currentPlaying.isCompleteFileAvailable(); } - state.changed = lastChange = new Date(); - Log.i(TAG, "Serialized currentPlayingIndex: " + state.currentPlayingIndex + ", currentPlayingPosition: " + state.currentPlayingPosition); FileUtil.serialize(downloadService, state, FILENAME_DOWNLOADS_SER); } @@ -321,24 +297,16 @@ public class DownloadServiceLifecycleSupport { Log.i(TAG, "Deserialized currentPlayingIndex: " + state.currentPlayingIndex + ", currentPlayingPosition: " + state.currentPlayingPosition); // Rename first thing before anything else starts - if(state.renameCurrent && state.currentPlayingIndex != -1 && state.currentPlayingIndex < state.songs.size()) { + if (state.renameCurrent && state.currentPlayingIndex != -1 && state.currentPlayingIndex < state.songs.size()) { DownloadFile currentPlaying = new DownloadFile(downloadService, state.songs.get(state.currentPlayingIndex), false); currentPlaying.renamePartial(); } downloadService.restore(state.songs, state.toDelete, state.currentPlayingIndex, state.currentPlayingPosition); - - if(state != null) { - lastChange = state.changed; - } } - public Date getLastChange() { - return lastChange; - } - - public void handleKeyEvent(KeyEvent event) { - if(event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() > 0) { + private void handleKeyEvent(KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() > 0) { switch (event.getKeyCode()) { case KeyEvent.KEYCODE_MEDIA_PREVIOUS: downloadService.fastForward(); @@ -347,25 +315,25 @@ public class DownloadServiceLifecycleSupport { downloadService.rewind(); break; } - } else if(event.getAction() == KeyEvent.ACTION_UP) { + } else if (event.getAction() == KeyEvent.ACTION_UP) { switch (event.getKeyCode()) { case KeyEvent.KEYCODE_HEADSETHOOK: case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: - if(lastPressTime < (System.currentTimeMillis() - 500)) { + if (lastPressTime < (System.currentTimeMillis() - 500)) { lastPressTime = System.currentTimeMillis(); downloadService.togglePlayPause(); } else { - downloadService.next(false, true); + downloadService.next(true); } break; case KeyEvent.KEYCODE_MEDIA_PREVIOUS: - if(lastPressTime < (System.currentTimeMillis() - DEBOUNCE_TIME)) { + if (lastPressTime < (System.currentTimeMillis() - DEBOUNCE_TIME)) { lastPressTime = System.currentTimeMillis(); downloadService.previous(); } break; case KeyEvent.KEYCODE_MEDIA_NEXT: - if(lastPressTime < (System.currentTimeMillis() - DEBOUNCE_TIME)) { + if (lastPressTime < (System.currentTimeMillis() - DEBOUNCE_TIME)) { lastPressTime = System.currentTimeMillis(); downloadService.next(); } @@ -380,7 +348,7 @@ public class DownloadServiceLifecycleSupport { downloadService.stop(); break; case KeyEvent.KEYCODE_MEDIA_PLAY: - if(downloadService.getPlayerState() != PlayerState.STARTED) { + if (downloadService.getPlayerState() != PlayerState.STARTED) { downloadService.start(); } break; @@ -401,28 +369,25 @@ public class DownloadServiceLifecycleSupport { @Override public void onCallStateChanged(final int state, String incomingNumber) { - eventHandler.post(new Runnable() { - @Override - public void run() { - switch (state) { - case TelephonyManager.CALL_STATE_RINGING: - case TelephonyManager.CALL_STATE_OFFHOOK: - if (downloadService.getPlayerState() == PlayerState.STARTED) { - resumeAfterCall = true; - downloadService.pause(true); + eventHandler.post(() -> { + switch (state) { + case TelephonyManager.CALL_STATE_RINGING: + case TelephonyManager.CALL_STATE_OFFHOOK: + if (downloadService.getPlayerState() == PlayerState.STARTED) { + resumeAfterCall = true; + downloadService.pause(true); + } + break; + case TelephonyManager.CALL_STATE_IDLE: + if (resumeAfterCall) { + resumeAfterCall = false; + if (downloadService.getPlayerState() == PlayerState.PAUSED_TEMP) { + downloadService.start(); } - break; - case TelephonyManager.CALL_STATE_IDLE: - if (resumeAfterCall) { - resumeAfterCall = false; - if(downloadService.getPlayerState() == PlayerState.PAUSED_TEMP) { - downloadService.start(); - } - } - break; - default: - break; - } + } + break; + default: + break; } }); } diff --git a/app/src/main/java/net/nullsum/audinaut/service/HeadphoneListenerService.java b/app/src/main/java/net/nullsum/audinaut/service/HeadphoneListenerService.java index 2fb9aca..09c0f0d 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/HeadphoneListenerService.java +++ b/app/src/main/java/net/nullsum/audinaut/service/HeadphoneListenerService.java @@ -44,7 +44,7 @@ public class HeadphoneListenerService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { - if(!Util.shouldStartOnHeadphones(this)) { + if (!Util.shouldStartOnHeadphones(this)) { stopSelf(); } @@ -56,10 +56,10 @@ public class HeadphoneListenerService extends Service { super.onDestroy(); try { - if(receiver != null) { + if (receiver != null) { unregisterReceiver(receiver); } - } catch(Exception e) { + } catch (Exception e) { // Don't care } } diff --git a/app/src/main/java/net/nullsum/audinaut/service/MediaStoreService.java b/app/src/main/java/net/nullsum/audinaut/service/MediaStoreService.java index 39e2dc6..cb95418 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/MediaStoreService.java +++ b/app/src/main/java/net/nullsum/audinaut/service/MediaStoreService.java @@ -18,8 +18,6 @@ */ package net.nullsum.audinaut.service; -import java.io.File; - import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; @@ -27,9 +25,11 @@ import android.database.Cursor; import android.net.Uri; import android.provider.MediaStore; import android.util.Log; + import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.util.FileUtil; -import net.nullsum.audinaut.util.Util; + +import java.io.File; /** * @author Sindre Mehus @@ -67,7 +67,7 @@ public class MediaStoreService { if (song.getYear() != null) { values.put(MediaStore.Audio.AudioColumns.YEAR, song.getYear()); } - if(song.getTranscodedContentType() != null) { + if (song.getTranscodedContentType() != null) { values.put(MediaStore.MediaColumns.MIME_TYPE, song.getTranscodedContentType()); } else { values.put(MediaStore.MediaColumns.MIME_TYPE, song.getContentType()); diff --git a/app/src/main/java/net/nullsum/audinaut/service/MusicService.java b/app/src/main/java/net/nullsum/audinaut/service/MusicService.java index 4f83bb3..292f92b 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/MusicService.java +++ b/app/src/main/java/net/nullsum/audinaut/service/MusicService.java @@ -18,24 +18,23 @@ */ package net.nullsum.audinaut.service; -import java.util.List; - -import okhttp3.Response; - import android.content.Context; import android.graphics.Bitmap; import net.nullsum.audinaut.domain.Genre; import net.nullsum.audinaut.domain.Indexes; -import net.nullsum.audinaut.domain.PlayerQueue; import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.domain.MusicFolder; import net.nullsum.audinaut.domain.Playlist; import net.nullsum.audinaut.domain.SearchCritera; import net.nullsum.audinaut.domain.SearchResult; import net.nullsum.audinaut.domain.User; -import net.nullsum.audinaut.util.SilentBackgroundTask; import net.nullsum.audinaut.util.ProgressListener; +import net.nullsum.audinaut.util.SilentBackgroundTask; + +import java.util.List; + +import okhttp3.Response; /** * @author Sindre Mehus @@ -78,7 +77,6 @@ public interface MusicService { MusicDirectory getSongList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception; - MusicDirectory getRandomSongs(int size, String artistId, Context context, ProgressListener progressListener) throws Exception; MusicDirectory getRandomSongs(int size, String folder, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception; Bitmap getCoverArt(Context context, MusicDirectory.Entry entry, int size, ProgressListener progressListener, SilentBackgroundTask task) throws Exception; @@ -91,11 +89,5 @@ public interface MusicService { User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) throws Exception; - Bitmap getBitmap(String url, int size, Context context, ProgressListener progressListener, SilentBackgroundTask task) throws Exception; - - void savePlayQueue(List songs, MusicDirectory.Entry currentPlaying, int position, Context context, ProgressListener progressListener) throws Exception; - - PlayerQueue getPlayQueue(Context context, ProgressListener progressListener) throws Exception; - void setInstance(Integer instance) throws Exception; } diff --git a/app/src/main/java/net/nullsum/audinaut/service/OfflineException.java b/app/src/main/java/net/nullsum/audinaut/service/OfflineException.java index b0a834a..c636bdc 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/OfflineException.java +++ b/app/src/main/java/net/nullsum/audinaut/service/OfflineException.java @@ -26,7 +26,7 @@ package net.nullsum.audinaut.service; */ public class OfflineException extends Exception { - public OfflineException(String message) { - super(message); + public OfflineException() { + super(OfflineMusicService.ERRORMSG); } } diff --git a/app/src/main/java/net/nullsum/audinaut/service/OfflineMusicService.java b/app/src/main/java/net/nullsum/audinaut/service/OfflineMusicService.java index 8e03630..4cb2aac 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/OfflineMusicService.java +++ b/app/src/main/java/net/nullsum/audinaut/service/OfflineMusicService.java @@ -18,30 +18,15 @@ */ package net.nullsum.audinaut.service; -import java.io.File; -import java.io.Reader; -import java.io.FileReader; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Random; -import java.util.Set; - import android.content.Context; -import android.content.SharedPreferences; import android.graphics.Bitmap; import android.util.Log; -import okhttp3.Response; - import net.nullsum.audinaut.domain.Artist; import net.nullsum.audinaut.domain.Genre; import net.nullsum.audinaut.domain.Indexes; -import net.nullsum.audinaut.domain.MusicDirectory.Entry; -import net.nullsum.audinaut.domain.PlayerQueue; import net.nullsum.audinaut.domain.MusicDirectory; +import net.nullsum.audinaut.domain.MusicDirectory.Entry; import net.nullsum.audinaut.domain.MusicFolder; import net.nullsum.audinaut.domain.Playlist; import net.nullsum.audinaut.domain.SearchCritera; @@ -49,21 +34,31 @@ import net.nullsum.audinaut.domain.SearchResult; import net.nullsum.audinaut.domain.User; import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.FileUtil; -import net.nullsum.audinaut.util.Pair; import net.nullsum.audinaut.util.ProgressListener; import net.nullsum.audinaut.util.SilentBackgroundTask; -import net.nullsum.audinaut.util.SongDBHandler; import net.nullsum.audinaut.util.Util; -import java.io.*; -import java.util.Comparator; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.Reader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; +import java.util.Set; import java.util.SortedSet; +import okhttp3.Response; + /** * @author Sindre Mehus */ public class OfflineMusicService implements MusicService { + public static final String ERRORMSG = "Not available in offline mode"; private static final String TAG = OfflineMusicService.class.getSimpleName(); - private static final String ERRORMSG = "Not available in offline mode"; private static final Random random = new Random(); @Override @@ -73,7 +68,7 @@ public class OfflineMusicService implements MusicService { @Override public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception { - List artists = new ArrayList(); + List artists = new ArrayList<>(); List entries = new ArrayList<>(); File root = FileUtil.getMusicDirectory(context); for (File file : FileUtil.listFiles(root)) { @@ -83,31 +78,31 @@ public class OfflineMusicService implements MusicService { artist.setIndex(file.getName().substring(0, 1)); artist.setName(file.getName()); artists.add(artist); - } else if(!file.getName().equals("albumart.jpg") && !file.getName().equals(".nomedia")) { + } else if (!file.getName().equals("albumart.jpg") && !file.getName().equals(".nomedia")) { entries.add(createEntry(context, file)); } } - Indexes indexes = new Indexes(0L, Collections.emptyList(), artists, entries); - return indexes; + return new Indexes(Collections.emptyList(), artists, entries); } @Override public MusicDirectory getMusicDirectory(String id, String artistName, boolean refresh, Context context, ProgressListener progressListener) throws Exception { - return getMusicDirectory(id, artistName, refresh, context, progressListener, false); + return getMusicDirectory(id, context); } - private MusicDirectory getMusicDirectory(String id, String artistName, boolean refresh, Context context, ProgressListener progressListener, boolean isPodcast) throws Exception { + + private MusicDirectory getMusicDirectory(String id, Context context) throws Exception { File dir = new File(id); MusicDirectory result = new MusicDirectory(); result.setName(dir.getName()); - Set names = new HashSet(); + Set names = new HashSet<>(); for (File file : FileUtil.listMediaFiles(dir)) { String name = getName(file); if (name != null & !names.contains(name)) { names.add(name); - result.addChild(createEntry(context, file, name, true, isPodcast)); + result.addChild(createEntry(context, file, name, true)); } } result.sortChildren(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_CUSTOM_SORT_ENABLED, true)); @@ -116,12 +111,12 @@ public class OfflineMusicService implements MusicService { @Override public MusicDirectory getArtist(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); + throw new OfflineException(); } @Override public MusicDirectory getAlbum(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); + throw new OfflineException(); } private String getName(File file) { @@ -141,29 +136,24 @@ public class OfflineMusicService implements MusicService { private Entry createEntry(Context context, File file) { return createEntry(context, file, getName(file)); } + private Entry createEntry(Context context, File file, String name) { return createEntry(context, file, name, true); } + private Entry createEntry(Context context, File file, String name, boolean load) { - return createEntry(context, file, name, load, false); - } - private Entry createEntry(Context context, File file, String name, boolean load, boolean isPodcast) { Entry entry; entry = new Entry(); entry.setDirectory(file.isDirectory()); entry.setId(file.getPath()); entry.setParent(file.getParent()); - entry.setSize(file.length()); String root = FileUtil.getMusicDirectory(context).getPath(); - if(!file.getParentFile().getParentFile().getPath().equals(root)) { - entry.setGrandParent(file.getParentFile().getParent()); - } - entry.setPath(file.getPath().replaceFirst("^" + root + "/" , "")); + entry.setPath(file.getPath().replaceFirst("^" + root + "/", "")); String title = name; if (file.isFile()) { File artistFolder = file.getParentFile().getParentFile(); File albumFolder = file.getParentFile(); - if(artistFolder.getPath().equals(root)) { + if (artistFolder.getPath().equals(root)) { entry.setArtist(albumFolder.getName()); } else { entry.setArtist(artistFolder.getName()); @@ -171,16 +161,16 @@ public class OfflineMusicService implements MusicService { entry.setAlbum(albumFolder.getName()); int index = name.indexOf('-'); - if(index != -1) { + if (index != -1) { try { entry.setTrack(Integer.parseInt(name.substring(0, index))); title = title.substring(index + 1); - } catch(Exception e) { + } catch (Exception e) { // Failed parseInt, just means track filled out } } - if(load) { + if (load) { entry.loadMetadata(file); } } @@ -199,32 +189,32 @@ public class OfflineMusicService implements MusicService { public Bitmap getCoverArt(Context context, Entry entry, int size, ProgressListener progressListener, SilentBackgroundTask task) throws Exception { try { return FileUtil.getAlbumArtBitmap(context, entry, size); - } catch(Exception e) { + } catch (Exception e) { return null; } } @Override public Response getDownloadInputStream(Context context, Entry song, long offset, int maxBitrate, SilentBackgroundTask task) throws Exception { - throw new OfflineException(ERRORMSG); + throw new OfflineException(); } @Override public List getMusicFolders(boolean refresh, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); + throw new OfflineException(); } @Override public SearchResult search(SearchCritera criteria, Context context, ProgressListener progressListener) throws Exception { - List artists = new ArrayList(); - List albums = new ArrayList(); - List songs = new ArrayList(); + List artists = new ArrayList<>(); + List albums = new ArrayList<>(); + List songs = new ArrayList<>(); File root = FileUtil.getMusicDirectory(context); - int closeness = 0; + int closeness; for (File artistFile : FileUtil.listFiles(root)) { String artistName = artistFile.getName(); if (artistFile.isDirectory()) { - if((closeness = matchCriteria(criteria, artistName)) > 0) { + if ((closeness = matchCriteria(criteria, artistName)) > 0) { Artist artist = new Artist(); artist.setId(artistFile.getPath()); artist.setIndex(artistFile.getName().substring(0, 1)); @@ -237,43 +227,31 @@ public class OfflineMusicService implements MusicService { } } - Collections.sort(artists, new Comparator() { - public int compare(Artist lhs, Artist rhs) { - if(lhs.getCloseness() == rhs.getCloseness()) { - return 0; - } - else if(lhs.getCloseness() > rhs.getCloseness()) { - return -1; - } - else { - return 1; - } + Collections.sort(artists, (lhs, rhs) -> { + if (lhs.getCloseness() == rhs.getCloseness()) { + return 0; + } else if (lhs.getCloseness() > rhs.getCloseness()) { + return -1; + } else { + return 1; } }); - Collections.sort(albums, new Comparator() { - public int compare(Entry lhs, Entry rhs) { - if(lhs.getCloseness() == rhs.getCloseness()) { - return 0; - } - else if(lhs.getCloseness() > rhs.getCloseness()) { - return -1; - } - else { - return 1; - } + Collections.sort(albums, (lhs, rhs) -> { + if (lhs.getCloseness() == rhs.getCloseness()) { + return 0; + } else if (lhs.getCloseness() > rhs.getCloseness()) { + return -1; + } else { + return 1; } }); - Collections.sort(songs, new Comparator() { - public int compare(Entry lhs, Entry rhs) { - if(lhs.getCloseness() == rhs.getCloseness()) { - return 0; - } - else if(lhs.getCloseness() > rhs.getCloseness()) { - return -1; - } - else { - return 1; - } + Collections.sort(songs, (lhs, rhs) -> { + if (lhs.getCloseness() == rhs.getCloseness()) { + return 0; + } else if (lhs.getCloseness() > rhs.getCloseness()) { + return -1; + } else { + return 1; } }); @@ -290,26 +268,25 @@ public class OfflineMusicService implements MusicService { private void recursiveAlbumSearch(String artistName, File file, SearchCritera criteria, Context context, List albums, List songs) { int closeness; - for(File albumFile : FileUtil.listMediaFiles(file)) { - if(albumFile.isDirectory()) { + for (File albumFile : FileUtil.listMediaFiles(file)) { + if (albumFile.isDirectory()) { String albumName = getName(albumFile); - if((closeness = matchCriteria(criteria, albumName)) > 0) { + if ((closeness = matchCriteria(criteria, albumName)) > 0) { Entry album = createEntry(context, albumFile, albumName); album.setArtist(artistName); album.setCloseness(closeness); albums.add(album); } - for(File songFile : FileUtil.listMediaFiles(albumFile)) { + for (File songFile : FileUtil.listMediaFiles(albumFile)) { String songName = getName(songFile); - if(songName == null) { + if (songName == null) { continue; } - if(songFile.isDirectory()) { + if (songFile.isDirectory()) { recursiveAlbumSearch(artistName, songFile, criteria, context, albums, songs); - } - else if((closeness = matchCriteria(criteria, songName)) > 0){ + } else if ((closeness = matchCriteria(criteria, songName)) > 0) { Entry song = createEntry(context, albumFile, songName); song.setArtist(artistName); song.setAlbum(albumName); @@ -317,10 +294,9 @@ public class OfflineMusicService implements MusicService { songs.add(song); } } - } - else { + } else { String songName = getName(albumFile); - if((closeness = matchCriteria(criteria, songName)) > 0) { + if ((closeness = matchCriteria(criteria, songName)) > 0) { Entry song = createEntry(context, albumFile, songName); song.setArtist(artistName); song.setAlbum(songName); @@ -330,11 +306,12 @@ public class OfflineMusicService implements MusicService { } } } + private int matchCriteria(SearchCritera criteria, String name) { if (criteria.getPattern().matcher(name).matches()) { return Util.getStringDistance( - criteria.getQuery().toLowerCase(), - name.toLowerCase()); + criteria.getQuery().toLowerCase(), + name.toLowerCase()); } else { return 0; } @@ -342,16 +319,16 @@ public class OfflineMusicService implements MusicService { @Override public List getPlaylists(boolean refresh, Context context, ProgressListener progressListener) throws Exception { - List playlists = new ArrayList(); + List playlists = new ArrayList<>(); File root = FileUtil.getPlaylistDirectory(context); String lastServer = null; boolean removeServer = true; for (File folder : FileUtil.listFiles(root)) { - if(folder.isDirectory()) { + if (folder.isDirectory()) { String server = folder.getName(); SortedSet fileList = FileUtil.listFiles(folder); - for(File file: fileList) { - if(FileUtil.isPlaylistFile(file)) { + for (File file : fileList) { + if (FileUtil.isPlaylistFile(file)) { String id = file.getName(); String filename = FileUtil.getBaseName(id); String name = server + ": " + filename; @@ -366,41 +343,41 @@ public class OfflineMusicService implements MusicService { buffer = new BufferedReader(reader); String line = buffer.readLine(); - while( (line = buffer.readLine()) != null ){ + while ((line = buffer.readLine()) != null) { // No matter what, end file can't have .complete in it line = line.replace(".complete", ""); File entryFile = new File(line); // Don't add file to playlist if it doesn't exist as cached or pinned! File checkFile = entryFile; - if(!checkFile.exists()) { + if (!checkFile.exists()) { // If normal file doens't exist, check if .complete version does checkFile = new File(entryFile.getParent(), FileUtil.getBaseName(entryFile.getName()) + ".complete." + FileUtil.getExtension(entryFile.getName())); } String entryName = getName(entryFile); - if(checkFile.exists() && entryName != null){ + if (checkFile.exists() && entryName != null) { songCount++; } } playlist.setSongCount(Integer.toString(songCount)); - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to count songs in playlist", e); } finally { Util.close(buffer); Util.close(reader); } - if(songCount > 0) { + if (songCount > 0) { playlists.add(playlist); } } } - if(!server.equals(lastServer) && fileList.size() > 0) { - if(lastServer != null) { + if (!server.equals(lastServer) && fileList.size() > 0) { + if (lastServer != null) { removeServer = false; } lastServer = server; @@ -409,14 +386,14 @@ public class OfflineMusicService implements MusicService { // Delete legacy playlist files try { folder.delete(); - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to delete old playlist file: " + folder.getName()); } } } - if(removeServer) { - for(Playlist playlist: playlists) { + if (removeServer) { + for (Playlist playlist : playlists) { playlist.setName(playlist.getName().substring(playlist.getId().length() + 2)); } } @@ -434,7 +411,7 @@ public class OfflineMusicService implements MusicService { BufferedReader buffer = null; try { int firstIndex = name.indexOf(id); - if(firstIndex != -1) { + if (firstIndex != -1) { name = name.substring(id.length() + 2); } @@ -444,23 +421,23 @@ public class OfflineMusicService implements MusicService { MusicDirectory playlist = new MusicDirectory(); String line = buffer.readLine(); - if(!"#EXTM3U".equals(line)) return playlist; + if (!"#EXTM3U".equals(line)) return playlist; - while( (line = buffer.readLine()) != null ){ + while ((line = buffer.readLine()) != null) { // No matter what, end file can't have .complete in it line = line.replace(".complete", ""); File entryFile = new File(line); // Don't add file to playlist if it doesn't exist as cached or pinned! File checkFile = entryFile; - if(!checkFile.exists()) { + if (!checkFile.exists()) { // If normal file doens't exist, check if .complete version does checkFile = new File(entryFile.getParent(), FileUtil.getBaseName(entryFile.getName()) - + ".complete." + FileUtil.getExtension(entryFile.getName())); + + ".complete." + FileUtil.getExtension(entryFile.getName())); } String entryName = getName(entryFile); - if(checkFile.exists() && entryName != null){ + if (checkFile.exists() && entryName != null) { playlist.addChild(createEntry(context, entryFile, entryName, false)); } } @@ -474,68 +451,63 @@ public class OfflineMusicService implements MusicService { @Override public void createPlaylist(String id, String name, List entries, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); + throw new OfflineException(); } @Override public void deletePlaylist(String id, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); + throw new OfflineException(); } @Override public void addToPlaylist(String id, List toAdd, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); + throw new OfflineException(); } @Override public void removeFromPlaylist(String id, List toRemove, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); + throw new OfflineException(); } @Override public void overwritePlaylist(String id, String name, int toRemove, List toAdd, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); + throw new OfflineException(); } @Override public void updatePlaylist(String id, String name, String comment, boolean pub, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); + throw new OfflineException(); } @Override public MusicDirectory getAlbumList(String type, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); + throw new OfflineException(); } @Override public MusicDirectory getAlbumList(String type, String extra, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); + throw new OfflineException(); } @Override public MusicDirectory getSongList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); - } - - @Override - public MusicDirectory getRandomSongs(int size, String artistId, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); + throw new OfflineException(); } @Override public List getGenres(boolean refresh, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); + throw new OfflineException(); } @Override public MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); + throw new OfflineException(); } @Override public MusicDirectory getRandomSongs(int size, String folder, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception { File root = FileUtil.getMusicDirectory(context); - List children = new LinkedList(); + List children = new LinkedList<>(); listFilesRecursively(root, children); MusicDirectory result = new MusicDirectory(); @@ -552,27 +524,12 @@ public class OfflineMusicService implements MusicService { @Override public User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); + throw new OfflineException(); } @Override - public Bitmap getBitmap(String url, int size, Context context, ProgressListener progressListener, SilentBackgroundTask task) throws Exception { - throw new OfflineException(ERRORMSG); - } - - @Override - public void savePlayQueue(List songs, Entry currentPlaying, int position, Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); - } - - @Override - public PlayerQueue getPlayQueue(Context context, ProgressListener progressListener) throws Exception { - throw new OfflineException(ERRORMSG); - } - - @Override - public void setInstance(Integer instance) throws Exception{ - throw new OfflineException(ERRORMSG); + public void setInstance(Integer instance) throws Exception { + throw new OfflineException(); } private void listFilesRecursively(File parent, List children) { diff --git a/app/src/main/java/net/nullsum/audinaut/service/RESTMusicService.java b/app/src/main/java/net/nullsum/audinaut/service/RESTMusicService.java index 0c70591..8a40781 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/RESTMusicService.java +++ b/app/src/main/java/net/nullsum/audinaut/service/RESTMusicService.java @@ -18,28 +18,19 @@ */ package net.nullsum.audinaut.service; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import okhttp3.FormBody; -import okhttp3.FormBody.Builder; -import okhttp3.RequestBody; -import okhttp3.Call; -import okhttp3.Credentials; - import android.content.Context; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.util.Log; -import net.nullsum.audinaut.R; -import net.nullsum.audinaut.domain.*; +import net.nullsum.audinaut.domain.Genre; +import net.nullsum.audinaut.domain.Indexes; +import net.nullsum.audinaut.domain.MusicDirectory; +import net.nullsum.audinaut.domain.MusicFolder; +import net.nullsum.audinaut.domain.Playlist; +import net.nullsum.audinaut.domain.SearchCritera; +import net.nullsum.audinaut.domain.SearchResult; +import net.nullsum.audinaut.domain.User; import net.nullsum.audinaut.fragments.MainFragment; import net.nullsum.audinaut.service.parser.EntryListParser; import net.nullsum.audinaut.service.parser.ErrorParser; @@ -47,29 +38,39 @@ import net.nullsum.audinaut.service.parser.GenreParser; import net.nullsum.audinaut.service.parser.IndexesParser; import net.nullsum.audinaut.service.parser.MusicDirectoryParser; import net.nullsum.audinaut.service.parser.MusicFoldersParser; -import net.nullsum.audinaut.service.parser.PlayQueueParser; import net.nullsum.audinaut.service.parser.PlaylistParser; import net.nullsum.audinaut.service.parser.PlaylistsParser; import net.nullsum.audinaut.service.parser.RandomSongsParser; import net.nullsum.audinaut.service.parser.SearchResult2Parser; import net.nullsum.audinaut.service.parser.UserParser; -import net.nullsum.audinaut.util.BackgroundTask; -import net.nullsum.audinaut.util.Pair; -import net.nullsum.audinaut.util.SilentBackgroundTask; import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.FileUtil; +import net.nullsum.audinaut.util.Pair; import net.nullsum.audinaut.util.ProgressListener; +import net.nullsum.audinaut.util.SilentBackgroundTask; import net.nullsum.audinaut.util.SongDBHandler; import net.nullsum.audinaut.util.Util; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import okhttp3.FormBody; +import okhttp3.FormBody.Builder; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + /** * @author Sindre Mehus */ public class RESTMusicService implements MusicService { - private static OkHttpClient client = new OkHttpClient(); private static final String TAG = RESTMusicService.class.getSimpleName(); - + private static final OkHttpClient client = new OkHttpClient(); private Integer instance; @Override @@ -77,8 +78,8 @@ public class RESTMusicService implements MusicService { String url = getRestUrl(context, "ping"); Request request = new Request.Builder() - .url(url) - .build(); + .url(url) + .build(); try (Response response = client.newCall(request).execute()) { new ErrorParser(context, getInstance(context)).parse(response.body().byteStream()); @@ -89,11 +90,11 @@ public class RESTMusicService implements MusicService { String url = getRestUrl(context, "getMusicFolders"); Request request = new Request.Builder() - .url(url) - .build(); + .url(url) + .build(); try (Response response = client.newCall(request).execute()) { - return new MusicFoldersParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener); + return new MusicFoldersParser(context, getInstance(context)).parse(response.body().byteStream()); } } @@ -101,7 +102,7 @@ public class RESTMusicService implements MusicService { public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception { String url = getRestUrl(context, "getArtists"); - Builder builder= new FormBody.Builder(); + Builder builder = new FormBody.Builder(); if (musicFolderId != null) { builder.add("musicFolderId", musicFolderId); @@ -110,9 +111,9 @@ public class RESTMusicService implements MusicService { RequestBody formBody = builder.build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { return new IndexesParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener); @@ -123,22 +124,22 @@ public class RESTMusicService implements MusicService { public MusicDirectory getMusicDirectory(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception { SharedPreferences prefs = Util.getPreferences(context); String cacheLocn = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null); - if(cacheLocn != null && id.indexOf(cacheLocn) != -1) { - String search = Util.parseOfflineIDSearch(context, id, cacheLocn); + if (cacheLocn != null && id.contains(cacheLocn)) { + String search = Util.parseOfflineIDSearch(id, cacheLocn); SearchCritera critera = new SearchCritera(search, 1, 1, 0); SearchResult result = search(critera, context, progressListener); - if(result.getArtists().size() == 1) { + if (result.getArtists().size() == 1) { id = result.getArtists().get(0).getId(); - } else if(result.getAlbums().size() == 1) { + } else if (result.getAlbums().size() == 1) { id = result.getAlbums().get(0).getId(); } } MusicDirectory dir = null; int index, start = 0; - while((index = id.indexOf(';', start)) != -1) { - MusicDirectory extra = getMusicDirectoryImpl(id.substring(start, index), name, refresh, context, progressListener); - if(dir == null) { + while ((index = id.indexOf(';', start)) != -1) { + MusicDirectory extra = getMusicDirectoryImpl(id.substring(start, index), name, context); + if (dir == null) { dir = extra; } else { dir.addChildren(extra.getChildren()); @@ -146,8 +147,8 @@ public class RESTMusicService implements MusicService { start = index + 1; } - MusicDirectory extra = getMusicDirectoryImpl(id.substring(start), name, refresh, context, progressListener); - if(dir == null) { + MusicDirectory extra = getMusicDirectoryImpl(id.substring(start), name, context); + if (dir == null) { dir = extra; } else { dir.addChildren(extra.getChildren()); @@ -156,20 +157,20 @@ public class RESTMusicService implements MusicService { return dir; } - private MusicDirectory getMusicDirectoryImpl(String id, String name, boolean refresh, Context context, ProgressListener progressListener) throws Exception { + private MusicDirectory getMusicDirectoryImpl(String id, String name, Context context) throws Exception { String url = getRestUrl(context, "getMusicDirectory"); RequestBody formBody = new FormBody.Builder() - .add("id", id) - .build(); + .add("id", id) + .build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { - return new MusicDirectoryParser(context, getInstance(context)).parse(name, response.body().byteStream(), progressListener); + return new MusicDirectoryParser(context, getInstance(context)).parse(name, response.body().byteStream()); } } @@ -178,16 +179,16 @@ public class RESTMusicService implements MusicService { String url = getRestUrl(context, "getArtist"); RequestBody formBody = new FormBody.Builder() - .add("id", id) - .build(); + .add("id", id) + .build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { - return new MusicDirectoryParser(context, getInstance(context)).parse(name, response.body().byteStream(), progressListener); + return new MusicDirectoryParser(context, getInstance(context)).parse(name, response.body().byteStream()); } } @@ -196,16 +197,16 @@ public class RESTMusicService implements MusicService { String url = getRestUrl(context, "getAlbum"); RequestBody formBody = new FormBody.Builder() - .add("id", id) - .build(); + .add("id", id) + .build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { - return new MusicDirectoryParser(context, getInstance(context)).parse(name, response.body().byteStream(), progressListener); + return new MusicDirectoryParser(context, getInstance(context)).parse(name, response.body().byteStream()); } } @@ -213,7 +214,7 @@ public class RESTMusicService implements MusicService { public SearchResult search(SearchCritera critera, Context context, ProgressListener progressListener) throws Exception { String url = getRestUrl(context, "search3"); - Builder builder= new FormBody.Builder(); + Builder builder = new FormBody.Builder(); builder.add("query", critera.getQuery()); builder.add("artistCount", Integer.toString(critera.getArtistCount())); @@ -223,12 +224,12 @@ public class RESTMusicService implements MusicService { RequestBody formBody = builder.build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { - return new SearchResult2Parser(context, getInstance(context)).parse(response.body().byteStream(), progressListener); + return new SearchResult2Parser(context, getInstance(context)).parse(response.body().byteStream()); } } @@ -237,16 +238,16 @@ public class RESTMusicService implements MusicService { String url = getRestUrl(context, "getPlaylist"); RequestBody formBody = new FormBody.Builder() - .add("id", id) - .build(); + .add("id", id) + .build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { - return new PlaylistParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener); + return new PlaylistParser(context, getInstance(context)).parse(response.body().byteStream()); } } @@ -255,11 +256,11 @@ public class RESTMusicService implements MusicService { String url = getRestUrl(context, "getPlaylists"); Request request = new Request.Builder() - .url(url) - .build(); + .url(url) + .build(); try (Response response = client.newCall(request).execute()) { - return new PlaylistsParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener); + return new PlaylistsParser(context, getInstance(context)).parse(response.body().byteStream()); } } @@ -267,7 +268,7 @@ public class RESTMusicService implements MusicService { public void createPlaylist(String id, String name, List entries, Context context, ProgressListener progressListener) throws Exception { String url = getRestUrl(context, "createPlaylist"); - Builder builder= new FormBody.Builder(); + Builder builder = new FormBody.Builder(); if (id != null) { builder.add("playlistId", id); @@ -284,9 +285,9 @@ public class RESTMusicService implements MusicService { RequestBody formBody = builder.build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { new ErrorParser(context, getInstance(context)).parse(response.body().byteStream()); @@ -298,13 +299,13 @@ public class RESTMusicService implements MusicService { String url = getRestUrl(context, "deletePlaylist"); RequestBody formBody = new FormBody.Builder() - .add("id", id) - .build(); + .add("id", id) + .build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { new ErrorParser(context, getInstance(context)).parse(response.body().byteStream()); @@ -315,18 +316,18 @@ public class RESTMusicService implements MusicService { public void addToPlaylist(String id, List toAdd, Context context, ProgressListener progressListener) throws Exception { String url = getRestUrl(context, "updatePlaylist"); - Builder builder= new FormBody.Builder(); + Builder builder = new FormBody.Builder(); builder.add("playlistId", id); - for(MusicDirectory.Entry song: toAdd) { + for (MusicDirectory.Entry song : toAdd) { builder.add("songIdToAdd", getOfflineSongId(song.getId(), context, progressListener)); } RequestBody formBody = builder.build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { new ErrorParser(context, getInstance(context)).parse(response.body().byteStream()); @@ -337,19 +338,19 @@ public class RESTMusicService implements MusicService { public void removeFromPlaylist(String id, List toRemove, Context context, ProgressListener progressListener) throws Exception { String url = getRestUrl(context, "updatePlaylist"); - Builder builder= new FormBody.Builder(); + Builder builder = new FormBody.Builder(); builder.add("playlistId", id); - for(Integer song: toRemove) { + for (Integer song : toRemove) { builder.add("songIndexToRemove", Integer.toString(song)); } RequestBody formBody = builder.build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { new ErrorParser(context, getInstance(context)).parse(response.body().byteStream()); @@ -360,24 +361,24 @@ public class RESTMusicService implements MusicService { public void overwritePlaylist(String id, String name, int toRemove, List toAdd, Context context, ProgressListener progressListener) throws Exception { String url = getRestUrl(context, "updatePlaylist"); - Builder builder= new FormBody.Builder(); + Builder builder = new FormBody.Builder(); builder.add("playlistId", id); builder.add("name", name); - for(MusicDirectory.Entry song: toAdd) { + for (MusicDirectory.Entry song : toAdd) { builder.add("songIdToAdd", getOfflineSongId(song.getId(), context, progressListener)); } - for(int i = 0; i < toRemove; i++) { + for (int i = 0; i < toRemove; i++) { builder.add("songIndexToRemove", Integer.toString(i)); } RequestBody formBody = builder.build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { new ErrorParser(context, getInstance(context)).parse(response.body().byteStream()); @@ -388,7 +389,7 @@ public class RESTMusicService implements MusicService { public void updatePlaylist(String id, String name, String comment, boolean pub, Context context, ProgressListener progressListener) throws Exception { String url = getRestUrl(context, "updatePlaylist"); - Builder builder= new FormBody.Builder(); + Builder builder = new FormBody.Builder(); builder.add("playlistId", id); builder.add("name", name); builder.add("comment", comment); @@ -397,9 +398,9 @@ public class RESTMusicService implements MusicService { RequestBody formBody = builder.build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { new ErrorParser(context, getInstance(context)).parse(response.body().byteStream()); @@ -410,16 +411,16 @@ public class RESTMusicService implements MusicService { public MusicDirectory getAlbumList(String type, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception { String url = getRestUrl(context, "getAlbumList2"); - Builder builder= new FormBody.Builder(); + Builder builder = new FormBody.Builder(); builder.add("type", type); builder.add("size", Integer.toString(size)); builder.add("offset", Integer.toString(offset)); // Add folder if it was set and is non null int instance = getInstance(context); - if(Util.getAlbumListsPerFolder(context, instance)) { + if (Util.getAlbumListsPerFolder(context, instance)) { String folderId = Util.getSelectedMusicFolderId(context, instance); - if(folderId != null) { + if (folderId != null) { builder.add("musicFolderId", folderId); } } @@ -427,12 +428,12 @@ public class RESTMusicService implements MusicService { RequestBody formBody = builder.build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { - return new EntryListParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener); + return new EntryListParser(context, getInstance(context)).parse(response.body().byteStream()); } } @@ -440,15 +441,15 @@ public class RESTMusicService implements MusicService { public MusicDirectory getAlbumList(String type, String extra, int size, int offset, boolean refresh, Context context, ProgressListener progressListener) throws Exception { String url = getRestUrl(context, "getAlbumList2"); - Builder builder= new FormBody.Builder(); + Builder builder = new FormBody.Builder(); builder.add("size", Integer.toString(size)); builder.add("offset", Integer.toString(offset)); int instance = getInstance(context); - if("genres".equals(type)) { + if ("genres".equals(type)) { builder.add("type", "byGenre"); builder.add("genre", extra); - } else if("years".equals(type)) { + } else if ("years".equals(type)) { int decade = Integer.parseInt(extra); builder.add("type", "byYear"); @@ -457,9 +458,9 @@ public class RESTMusicService implements MusicService { } // Add folder if it was set and is non null - if(Util.getAlbumListsPerFolder(context, instance)) { + if (Util.getAlbumListsPerFolder(context, instance)) { String folderId = Util.getSelectedMusicFolderId(context, instance); - if(folderId != null) { + if (folderId != null) { builder.add("musicFolderId", folderId); } } @@ -467,23 +468,23 @@ public class RESTMusicService implements MusicService { RequestBody formBody = builder.build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { - return new EntryListParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener); + return new EntryListParser(context, getInstance(context)).parse(response.body().byteStream()); } } @Override public MusicDirectory getSongList(String type, int size, int offset, Context context, ProgressListener progressListener) throws Exception { - Builder builder= new FormBody.Builder(); + Builder builder = new FormBody.Builder(); builder.add("size", Integer.toString(size)); builder.add("offset", Integer.toString(offset)); String method; - switch(type) { + switch (type) { case MainFragment.SONGS_NEWEST: method = "getNewaddedSongs"; break; @@ -505,66 +506,43 @@ public class RESTMusicService implements MusicService { RequestBody formBody = builder.build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { - return new EntryListParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener); - } - } - - @Override - public MusicDirectory getRandomSongs(int size, String artistId, Context context, ProgressListener progressListener) throws Exception { - Builder builder= new FormBody.Builder(); - builder.add("id", artistId); - builder.add("count", Integer.toString(size)); - - String url = getRestUrl(context, "getSimilarSongs2"); - - RequestBody formBody = builder.build(); - - Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); - - try (Response response = client.newCall(request).execute()) { - return new RandomSongsParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener); + return new EntryListParser(context, getInstance(context)).parse(response.body().byteStream()); } } @Override public MusicDirectory getRandomSongs(int size, String musicFolderId, String genre, String startYear, String endYear, Context context, ProgressListener progressListener) throws Exception { - Builder builder= new FormBody.Builder(); + Builder builder = new FormBody.Builder(); builder.add("size", Integer.toString(size)); - if (musicFolderId != null && !"".equals(musicFolderId) && !Util.isTagBrowsing(context, getInstance(context))) { - builder.add("musicFolderId", musicFolderId); - } - if(genre != null && !"".equals(genre)) { + if (genre != null && !"".equals(genre)) { builder.add("genre", genre); } - if(startYear != null && !"".equals(startYear)) { + if (startYear != null && !"".equals(startYear)) { // Check to make sure user isn't doing 2015 -> 2010 since Subsonic will return no results - if(endYear != null && !"".equals(endYear)) { + if (endYear != null && !"".equals(endYear)) { try { int startYearInt = Integer.parseInt(startYear); int endYearInt = Integer.parseInt(endYear); - if(startYearInt > endYearInt) { + if (startYearInt > endYearInt) { String tmp = startYear; startYear = endYear; endYear = tmp; } - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to convert start/end year into ints", e); } } builder.add("fromYear", startYear); } - if(endYear != null && !"".equals(endYear)) { + if (endYear != null && !"".equals(endYear)) { builder.add("toYear", endYear); } @@ -573,12 +551,12 @@ public class RESTMusicService implements MusicService { RequestBody formBody = builder.build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { - return new RandomSongsParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener); + return new RandomSongsParser(context, getInstance(context)).parse(response.body().byteStream()); } } @@ -596,15 +574,15 @@ public class RESTMusicService implements MusicService { String url = getRestUrl(context, "getCoverArt"); - Builder builder= new FormBody.Builder(); + Builder builder = new FormBody.Builder(); builder.add("id", entry.getCoverArt()); RequestBody formBody = builder.build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { InputStream in = response.body().byteStream(); @@ -612,7 +590,7 @@ public class RESTMusicService implements MusicService { byte[] bytes = Util.toByteArray(in); // Handle case where partial was downloaded before being cancelled - if(task != null && task.isCancelled()) { + if (task != null && task.isCancelled()) { return null; } @@ -625,7 +603,7 @@ public class RESTMusicService implements MusicService { } // Size == 0 -> only want to download - if(size == 0) { + if (size == 0) { return null; } else { return FileUtil.getSampledBitmap(bytes, size); @@ -638,8 +616,8 @@ public class RESTMusicService implements MusicService { public Response getDownloadInputStream(Context context, MusicDirectory.Entry song, long offset, int maxBitrate, SilentBackgroundTask task) throws Exception { OkHttpClient eagerClient = client.newBuilder() - .readTimeout(30, TimeUnit.SECONDS) - .build(); + .readTimeout(30, TimeUnit.SECONDS) + .build(); String url = getRestUrl(context, "stream"); @@ -649,7 +627,7 @@ public class RESTMusicService implements MusicService { RequestBody formBody = builder.build(); - Request.Builder requestBuilder= new Request.Builder(); + Request.Builder requestBuilder = new Request.Builder(); if (offset > 0) { requestBuilder.header("Range", "bytes=" + offset + "-"); } @@ -659,8 +637,7 @@ public class RESTMusicService implements MusicService { Request request = requestBuilder.build(); - Response response = eagerClient.newCall(request).execute(); - return response; + return eagerClient.newCall(request).execute(); } @@ -669,26 +646,26 @@ public class RESTMusicService implements MusicService { String url = getRestUrl(context, "getGenres"); Request request = new Request.Builder() - .url(url) - .build(); + .url(url) + .build(); try (Response response = client.newCall(request).execute()) { - return new GenreParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener); + return new GenreParser(context, getInstance(context)).parse(response.body().byteStream()); } } @Override public MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception { - Builder builder= new FormBody.Builder(); + Builder builder = new FormBody.Builder(); builder.add("genre", genre); builder.add("count", Integer.toString(count)); builder.add("offset", Integer.toString(offset)); // Add folder if it was set and is non null int instance = getInstance(context); - if(Util.getAlbumListsPerFolder(context, instance)) { + if (Util.getAlbumListsPerFolder(context, instance)) { String folderId = Util.getSelectedMusicFolderId(context, instance); - if(folderId != null) { + if (folderId != null) { builder.add("musicFolderId", folderId); } } @@ -698,12 +675,12 @@ public class RESTMusicService implements MusicService { RequestBody formBody = builder.build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { - return new RandomSongsParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener); + return new RandomSongsParser(context, getInstance(context)).parse(response.body().byteStream()); } } @@ -712,17 +689,17 @@ public class RESTMusicService implements MusicService { String url = getRestUrl(context, "getUser"); RequestBody formBody = new FormBody.Builder() - .add("username", username) - .build(); + .add("username", username) + .build(); Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); + .url(url) + .post(formBody) + .build(); try (Response response = client.newCall(request).execute()) { - List users = new UserParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener); - if(users.size() > 0) { + List users = new UserParser(context, getInstance(context)).parse(response.body().byteStream()); + if (users.size() > 0) { // Should only have returned one anyways return users.get(0); } else { @@ -731,91 +708,15 @@ public class RESTMusicService implements MusicService { } } - @Override - public Bitmap getBitmap(String method, int size, Context context, ProgressListener progressListener, SilentBackgroundTask task) throws Exception { - // Synchronize on the url so that we don't download concurrently - synchronized (method) { - // Use cached file, if existing. - Bitmap bitmap = FileUtil.getMiscBitmap(context, method, size); - if(bitmap != null) { - return bitmap; - } - - String url = getRestUrl(context, method); - - Request request = new Request.Builder() - .url(url) - .build(); - - try (Response response = client.newCall(request).execute()) { - InputStream in = response.body().byteStream(); - - byte[] bytes = Util.toByteArray(in); - if(task != null && task.isCancelled()) { - // Handle case where partial is downloaded and cancelled - return null; - } - - OutputStream out = null; - try { - out = new FileOutputStream(FileUtil.getMiscFile(context, url)); - out.write(bytes); - } finally { - Util.close(out); - } - - return FileUtil.getSampledBitmap(bytes, size, false); - } - } - } - - @Override - public void savePlayQueue(List songs, MusicDirectory.Entry currentPlaying, int position, Context context, ProgressListener progressListener) throws Exception { - String url = getRestUrl(context, "savePlayQueue"); - - Builder builder= new FormBody.Builder(); - - builder.add("current", currentPlaying.getId()); - builder.add("position", Integer.toString(position)); - - for(MusicDirectory.Entry song: songs) { - builder.add("id", song.getId()); - } - - RequestBody formBody = builder.build(); - - Request request = new Request.Builder() - .url(url) - .post(formBody) - .build(); - - try (Response response = client.newCall(request).execute()) { - new ErrorParser(context, getInstance(context)).parse(response.body().byteStream()); - } - } - - @Override - public PlayerQueue getPlayQueue(Context context, ProgressListener progressListener) throws Exception { - String url = getRestUrl(context, "getPlayQueue"); - - Request request = new Request.Builder() - .url(url) - .build(); - - try (Response response = client.newCall(request).execute()) { - return new PlayQueueParser(context, getInstance(context)).parse(response.body().byteStream(), progressListener); - } - } - private String getOfflineSongId(String id, Context context, ProgressListener progressListener) throws Exception { SharedPreferences prefs = Util.getPreferences(context); String cacheLocn = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null); - if(cacheLocn != null && id.indexOf(cacheLocn) != -1) { + if (cacheLocn != null && id.contains(cacheLocn)) { Pair cachedSongId = SongDBHandler.getHandler(context).getIdFromPath(Util.getRestUrlHash(context, getInstance(context)), id); - if(cachedSongId != null) { + if (cachedSongId != null) { id = cachedSongId.getSecond(); } else { - String searchCriteria = Util.parseOfflineIDSearch(context, id, cacheLocn); + String searchCriteria = Util.parseOfflineIDSearch(id, cacheLocn); SearchCritera critera = new SearchCritera(searchCriteria, 0, 0, 1); SearchResult result = search(critera, context, progressListener); if (result.getSongs().size() == 1) { @@ -828,12 +729,12 @@ public class RESTMusicService implements MusicService { } @Override - public void setInstance(Integer instance) throws Exception { + public void setInstance(Integer instance) throws Exception { this.instance = instance; } public int getInstance(Context context) { - if(instance == null) { + if (instance == null) { return Util.getActiveServer(context); } else { return instance; @@ -846,7 +747,7 @@ public class RESTMusicService implements MusicService { } public String getRestUrl(Context context, String method, boolean allowAltAddress) { - if(instance == null) { + if (instance == null) { return Util.getRestUrl(context, method, allowAltAddress); } else { return Util.getRestUrl(context, method, instance, allowAltAddress); diff --git a/app/src/main/java/net/nullsum/audinaut/service/parser/AbstractParser.java b/app/src/main/java/net/nullsum/audinaut/service/parser/AbstractParser.java index b693a53..69d25e1 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/parser/AbstractParser.java +++ b/app/src/main/java/net/nullsum/audinaut/service/parser/AbstractParser.java @@ -18,41 +18,41 @@ */ package net.nullsum.audinaut.service.parser; -import java.io.IOException; -import java.io.InputStream; - -import org.xmlpull.v1.XmlPullParser; - import android.content.Context; import android.util.Log; import android.util.Xml; + import net.nullsum.audinaut.R; import net.nullsum.audinaut.util.ProgressListener; import net.nullsum.audinaut.util.Util; +import org.xmlpull.v1.XmlPullParser; + +import java.io.IOException; +import java.io.InputStream; + /** * @author Sindre Mehus */ -public abstract class AbstractParser { +abstract class AbstractParser { private static final String TAG = AbstractParser.class.getSimpleName(); private static final String SUBSONIC_RESPONSE = "subsonic-response"; - private static final String SUBSONIC = "subsonic"; - protected final Context context; - protected final int instance; + final Context context; + private final int instance; private XmlPullParser parser; private boolean rootElementFound; - public AbstractParser(Context context, int instance) { + AbstractParser(Context context, int instance) { this.context = context; this.instance = instance; } - protected Context getContext() { + Context getContext() { return context; } - protected void handleError() throws Exception { + void handleError() throws Exception { int code = getInteger("code"); String message; switch (code) { @@ -69,7 +69,7 @@ public abstract class AbstractParser { message = context.getResources().getString(R.string.parser_not_authenticated); break; case 41: - Util.setBlockTokenUse(context, instance, true); + Util.setBlockTokenUse(context, instance); // Throw IOException so RESTMusicService knows to retry throw new IOException(); @@ -80,77 +80,56 @@ public abstract class AbstractParser { message = get("message"); break; } - throw new SubsonicRESTException(code, message); + throw new SubsonicRESTException(message); } - protected void updateProgress(ProgressListener progressListener, int messageId) { - if (progressListener != null) { - progressListener.updateProgress(messageId); - } - } - - protected void updateProgress(ProgressListener progressListener, String message) { + void updateProgress(ProgressListener progressListener, String message) { if (progressListener != null) { progressListener.updateProgress(message); } } - protected String getText() { + String getText() { return parser.getText(); } - protected String get(String name) { + String get(String name) { return parser.getAttributeValue(null, name); } - protected boolean getBoolean(String name) { - return "true".equals(get(name)); + boolean getBoolean() { + return "true".equals(get("isDir")); } - protected Integer getInteger(String name) { + Integer getInteger(String name) { String s = get(name); try { return (s == null || "".equals(s)) ? null : Integer.valueOf(s); - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to parse " + s + " into integer"); return null; } } - protected Long getLong(String name) { - String s = get(name); - return s == null ? null : Long.valueOf(s); - } - - protected Float getFloat(String name) { - String s = get(name); - return s == null ? null : Float.valueOf(s); - } - - protected void init(InputStream inputStream) throws Exception { + void init(InputStream inputStream) throws Exception { parser = Xml.newPullParser(); parser.setInput(inputStream, "UTF-8"); rootElementFound = false; } - protected int nextParseEvent() throws Exception { - try { - return parser.next(); - } catch(Exception e) { - throw e; - } + int nextParseEvent() throws Exception { + return parser.next(); } - protected String getElementName() { + String getElementName() { String name = parser.getName(); if (SUBSONIC_RESPONSE.equals(name)) { rootElementFound = true; - String version = get("version"); } return name; } - protected void validate() throws Exception { + void validate() throws Exception { if (!rootElementFound) { throw new Exception(context.getResources().getString(R.string.background_task_parse_error)); } diff --git a/app/src/main/java/net/nullsum/audinaut/service/parser/EntryListParser.java b/app/src/main/java/net/nullsum/audinaut/service/parser/EntryListParser.java index 62bea2c..058d7c5 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/parser/EntryListParser.java +++ b/app/src/main/java/net/nullsum/audinaut/service/parser/EntryListParser.java @@ -19,9 +19,9 @@ package net.nullsum.audinaut.service.parser; import android.content.Context; -import net.nullsum.audinaut.R; + import net.nullsum.audinaut.domain.MusicDirectory; -import net.nullsum.audinaut.util.ProgressListener; + import org.xmlpull.v1.XmlPullParser; import java.io.InputStream; @@ -35,7 +35,7 @@ public class EntryListParser extends MusicDirectoryEntryParser { super(context, instance); } - public MusicDirectory parse(InputStream inputStream, ProgressListener progressListener) throws Exception { + public MusicDirectory parse(InputStream inputStream) throws Exception { init(inputStream); MusicDirectory dir = new MusicDirectory(); @@ -46,7 +46,7 @@ public class EntryListParser extends MusicDirectoryEntryParser { String name = getElementName(); if ("album".equals(name)) { MusicDirectory.Entry entry = parseEntry(""); - if(get("isDir") == null) { + if (get("isDir") == null) { entry.setDirectory(true); } dir.addChild(entry); diff --git a/app/src/main/java/net/nullsum/audinaut/service/parser/ErrorParser.java b/app/src/main/java/net/nullsum/audinaut/service/parser/ErrorParser.java index c6a866c..bef43f8 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/parser/ErrorParser.java +++ b/app/src/main/java/net/nullsum/audinaut/service/parser/ErrorParser.java @@ -19,6 +19,7 @@ package net.nullsum.audinaut.service.parser; import android.content.Context; + import org.xmlpull.v1.XmlPullParser; import java.io.InputStream; diff --git a/app/src/main/java/net/nullsum/audinaut/service/parser/GenreParser.java b/app/src/main/java/net/nullsum/audinaut/service/parser/GenreParser.java index d10c9ec..4451268 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/parser/GenreParser.java +++ b/app/src/main/java/net/nullsum/audinaut/service/parser/GenreParser.java @@ -20,34 +20,29 @@ package net.nullsum.audinaut.service.parser; import android.content.Context; import android.text.Html; -import android.util.Log; -import net.nullsum.audinaut.R; + import net.nullsum.audinaut.domain.Genre; -import net.nullsum.audinaut.util.ProgressListener; import org.xmlpull.v1.XmlPullParser; -import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.List; /** * @author Joshua Bahnsen */ public class GenreParser extends AbstractParser { - private static final String TAG = GenreParser.class.getSimpleName(); public GenreParser(Context context, int instance) { super(context, instance); } - public List parse(InputStream inputStream, ProgressListener progressListener) throws Exception { + public List parse(InputStream inputStream) throws Exception { init(inputStream); - List result = new ArrayList(); + List result = new ArrayList<>(); Genre genre = null; @@ -80,12 +75,7 @@ public class GenreParser extends AbstractParser { validate(); - Collections.sort(result, new Comparator() { - @Override - public int compare(Genre genre1, Genre genre2) { - return genre1.getName().compareTo(genre2.getName()); - } - }); + Collections.sort(result, (genre1, genre2) -> genre1.getName().compareTo(genre2.getName())); return result; } } diff --git a/app/src/main/java/net/nullsum/audinaut/service/parser/IndexesParser.java b/app/src/main/java/net/nullsum/audinaut/service/parser/IndexesParser.java index 2ec8b0d..26266f1 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/parser/IndexesParser.java +++ b/app/src/main/java/net/nullsum/audinaut/service/parser/IndexesParser.java @@ -18,25 +18,26 @@ */ package net.nullsum.audinaut.service.parser; -import java.io.InputStream; -import java.util.HashMap; -import java.util.List; -import java.util.ArrayList; -import java.util.Map; - -import org.xmlpull.v1.XmlPullParser; - import android.content.Context; import android.content.SharedPreferences; +import android.util.Log; + import net.nullsum.audinaut.R; import net.nullsum.audinaut.domain.Artist; import net.nullsum.audinaut.domain.Indexes; import net.nullsum.audinaut.domain.MusicDirectory; -import net.nullsum.audinaut.util.ProgressListener; -import android.util.Log; import net.nullsum.audinaut.util.Constants; +import net.nullsum.audinaut.util.ProgressListener; import net.nullsum.audinaut.util.Util; +import org.xmlpull.v1.XmlPullParser; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * @author Sindre Mehus */ @@ -51,15 +52,14 @@ public class IndexesParser extends MusicDirectoryEntryParser { long t0 = System.currentTimeMillis(); init(inputStream); - List artists = new ArrayList(); - List shortcuts = new ArrayList(); - List entries = new ArrayList(); - Long lastModified = null; + List artists = new ArrayList<>(); + List shortcuts = new ArrayList<>(); + List entries = new ArrayList<>(); int eventType; String index = "#"; String ignoredArticles = null; boolean changed = false; - Map artistList = new HashMap(); + Map artistList = new HashMap<>(); do { eventType = nextParseEvent(); @@ -67,7 +67,6 @@ public class IndexesParser extends MusicDirectoryEntryParser { String name = getElementName(); if ("indexes".equals(name) || "artists".equals(name)) { changed = true; - lastModified = getLong("lastModified"); ignoredArticles = get("ignoredArticles"); } else if ("index".equals(name)) { index = get("name"); @@ -79,7 +78,7 @@ public class IndexesParser extends MusicDirectoryEntryParser { artist.setIndex(index); // Combine the id's for the two artists - if(artistList.containsKey(artist.getName())) { + if (artistList.containsKey(artist.getName())) { Artist originalArtist = artistList.get(artist.getName()); originalArtist.setId(originalArtist.getId() + ";" + artist.getId()); } else { @@ -97,7 +96,7 @@ public class IndexesParser extends MusicDirectoryEntryParser { shortcut.setName(get("name")); shortcut.setIndex("*"); shortcuts.add(shortcut); - } else if("child".equals(name)) { + } else if ("child".equals(name)) { MusicDirectory.Entry entry = parseEntry(""); entries.add(entry); } else if ("error".equals(name)) { @@ -108,7 +107,7 @@ public class IndexesParser extends MusicDirectoryEntryParser { validate(); - if(ignoredArticles != null) { + if (ignoredArticles != null) { SharedPreferences.Editor prefs = Util.getPreferences(context).edit(); prefs.putString(Constants.CACHE_KEY_IGNORE, ignoredArticles); prefs.apply(); @@ -124,6 +123,6 @@ public class IndexesParser extends MusicDirectoryEntryParser { String msg = getContext().getResources().getString(R.string.parser_artist_count, artists.size()); updateProgress(progressListener, msg); - return new Indexes(lastModified == null ? 0L : lastModified, shortcuts, artists, entries); + return new Indexes(shortcuts, artists, entries); } } diff --git a/app/src/main/java/net/nullsum/audinaut/service/parser/MusicDirectoryEntryParser.java b/app/src/main/java/net/nullsum/audinaut/service/parser/MusicDirectoryEntryParser.java index a669308..cbafc78 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/parser/MusicDirectoryEntryParser.java +++ b/app/src/main/java/net/nullsum/audinaut/service/parser/MusicDirectoryEntryParser.java @@ -25,21 +25,21 @@ import net.nullsum.audinaut.domain.MusicDirectory; /** * @author Sindre Mehus */ -public class MusicDirectoryEntryParser extends AbstractParser { - public MusicDirectoryEntryParser(Context context, int instance) { +class MusicDirectoryEntryParser extends AbstractParser { + MusicDirectoryEntryParser(Context context, int instance) { super(context, instance); } - protected MusicDirectory.Entry parseEntry(String artist) { + MusicDirectory.Entry parseEntry(String artist) { MusicDirectory.Entry entry = new MusicDirectory.Entry(); entry.setId(get("id")); entry.setParent(get("parent")); entry.setArtistId(get("artistId")); entry.setTitle(get("title")); - if(entry.getTitle() == null) { + if (entry.getTitle() == null) { entry.setTitle(get("name")); } - entry.setDirectory(getBoolean("isDir")); + entry.setDirectory(getBoolean()); entry.setCoverArt(get("coverArt")); entry.setArtist(get("artist")); entry.setYear(getInteger("year")); @@ -53,27 +53,14 @@ public class MusicDirectoryEntryParser extends AbstractParser { entry.setSuffix(get("suffix")); entry.setTranscodedContentType(get("transcodedContentType")); entry.setTranscodedSuffix(get("transcodedSuffix")); - entry.setSize(getLong("size")); entry.setDuration(getInteger("duration")); entry.setBitRate(getInteger("bitRate")); entry.setPath(get("path")); entry.setDiscNumber(getInteger("discNumber")); - - String type = get("type"); - } else if(!"".equals(artist)) { + } else if (!"".equals(artist)) { entry.setPath(artist + "/" + entry.getTitle()); } return entry; } - protected MusicDirectory.Entry parseArtist() { - MusicDirectory.Entry entry = new MusicDirectory.Entry(); - - entry.setId(get("id")); - entry.setTitle(get("name")); - entry.setPath(entry.getTitle()); - entry.setDirectory(true); - - return entry; - } } diff --git a/app/src/main/java/net/nullsum/audinaut/service/parser/MusicDirectoryParser.java b/app/src/main/java/net/nullsum/audinaut/service/parser/MusicDirectoryParser.java index 8cde6ed..b482de4 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/parser/MusicDirectoryParser.java +++ b/app/src/main/java/net/nullsum/audinaut/service/parser/MusicDirectoryParser.java @@ -19,48 +19,42 @@ package net.nullsum.audinaut.service.parser; import android.content.Context; -import android.util.Log; -import net.nullsum.audinaut.R; + import net.nullsum.audinaut.domain.MusicDirectory; -import net.nullsum.audinaut.util.Constants; -import net.nullsum.audinaut.util.ProgressListener; -import net.nullsum.audinaut.util.Util; + import org.xmlpull.v1.XmlPullParser; import java.io.InputStream; import java.util.HashMap; import java.util.Map; -import static net.nullsum.audinaut.domain.MusicDirectory.*; +import static net.nullsum.audinaut.domain.MusicDirectory.Entry; /** * @author Sindre Mehus */ public class MusicDirectoryParser extends MusicDirectoryEntryParser { - private static final String TAG = MusicDirectoryParser.class.getSimpleName(); - public MusicDirectoryParser(Context context, int instance) { super(context, instance); } - public MusicDirectory parse(String artist, InputStream inputStream, ProgressListener progressListener) throws Exception { + public MusicDirectory parse(String artist, InputStream inputStream) throws Exception { init(inputStream); MusicDirectory dir = new MusicDirectory(); int eventType; boolean isArtist = false; - Map titleMap = new HashMap(); + Map titleMap = new HashMap<>(); do { eventType = nextParseEvent(); if (eventType == XmlPullParser.START_TAG) { String name = getElementName(); if ("child".equals(name) || "song".equals(name)) { Entry entry = parseEntry(artist); - entry.setGrandParent(dir.getParent()); // Only check for songs - if(!entry.isDirectory()) { + if (!entry.isDirectory()) { // Check if duplicates String disc = (entry.getDiscNumber() != null) ? Integer.toString(entry.getDiscNumber()) : ""; String track = (entry.getTrack() != null) ? Integer.toString(entry.getTrack()) : ""; @@ -84,13 +78,9 @@ public class MusicDirectoryParser extends MusicDirectoryEntryParser { } else if ("directory".equals(name) || "artist".equals(name) || ("album".equals(name) && !isArtist)) { dir.setName(get("name")); dir.setId(get("id")); - if(Util.isTagBrowsing(context, instance)) { - dir.setParent(get("artistId")); - } else { - dir.setParent(get("parent")); - } + dir.setParent(get("artistId")); isArtist = true; - } else if("album".equals(name)) { + } else if ("album".equals(name)) { Entry entry = parseEntry(artist); entry.setDirectory(true); dir.addChild(entry); diff --git a/app/src/main/java/net/nullsum/audinaut/service/parser/MusicFoldersParser.java b/app/src/main/java/net/nullsum/audinaut/service/parser/MusicFoldersParser.java index 6f02a69..0a9bce1 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/parser/MusicFoldersParser.java +++ b/app/src/main/java/net/nullsum/audinaut/service/parser/MusicFoldersParser.java @@ -18,16 +18,15 @@ */ package net.nullsum.audinaut.service.parser; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; +import android.content.Context; + +import net.nullsum.audinaut.domain.MusicFolder; import org.xmlpull.v1.XmlPullParser; -import android.content.Context; -import net.nullsum.audinaut.R; -import net.nullsum.audinaut.domain.MusicFolder; -import net.nullsum.audinaut.util.ProgressListener; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; /** * @author Sindre Mehus @@ -38,10 +37,10 @@ public class MusicFoldersParser extends AbstractParser { super(context, instance); } - public List parse(InputStream inputStream, ProgressListener progressListener) throws Exception { + public List parse(InputStream inputStream) throws Exception { init(inputStream); - List result = new ArrayList(); + List result = new ArrayList<>(); int eventType; do { eventType = nextParseEvent(); diff --git a/app/src/main/java/net/nullsum/audinaut/service/parser/PlayQueueParser.java b/app/src/main/java/net/nullsum/audinaut/service/parser/PlayQueueParser.java deleted file mode 100644 index 9b86944..0000000 --- a/app/src/main/java/net/nullsum/audinaut/service/parser/PlayQueueParser.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - This file is part of Subsonic. - Subsonic is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - Subsonic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with Subsonic. If not, see . - Copyright 2015 (C) Scott Jackson -*/ - -package net.nullsum.audinaut.service.parser; - -import android.content.Context; - -import org.xmlpull.v1.XmlPullParser; - -import java.io.InputStream; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Locale; -import java.util.TimeZone; - -import net.nullsum.audinaut.domain.MusicDirectory; -import net.nullsum.audinaut.domain.PlayerQueue; -import net.nullsum.audinaut.util.ProgressListener; - -public class PlayQueueParser extends MusicDirectoryEntryParser { - private static final String TAG = PlayQueueParser.class.getSimpleName(); - - public PlayQueueParser(Context context, int instance) { - super(context, instance); - } - - public PlayerQueue parse(InputStream inputStream, ProgressListener progressListener) throws Exception { - init(inputStream); - - PlayerQueue state = new PlayerQueue(); - String currentId = null; - int eventType; - do { - eventType = nextParseEvent(); - if (eventType == XmlPullParser.START_TAG) { - String name = getElementName(); - if("playQueue".equals(name)) { - currentId = get("current"); - state.currentPlayingPosition = getInteger("position"); - try { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ENGLISH); - dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); - state.changed = dateFormat.parse(get("changed")); - } catch (ParseException e) { - state.changed = null; - } - } else if ("entry".equals(name)) { - MusicDirectory.Entry entry = parseEntry(""); - // Only add songs - state.songs.add(entry); - } else if ("error".equals(name)) { - handleError(); - } - } - } while (eventType != XmlPullParser.END_DOCUMENT); - - if(currentId != null) { - for (MusicDirectory.Entry entry : state.songs) { - if (entry.getId().equals(currentId)) { - state.currentPlayingIndex = state.songs.indexOf(entry); - } - } - } else { - state.currentPlayingIndex = 0; - state.currentPlayingPosition = 0; - } - - validate(); - return state; - } -} diff --git a/app/src/main/java/net/nullsum/audinaut/service/parser/PlaylistParser.java b/app/src/main/java/net/nullsum/audinaut/service/parser/PlaylistParser.java index 7add8ce..21dfbbc 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/parser/PlaylistParser.java +++ b/app/src/main/java/net/nullsum/audinaut/service/parser/PlaylistParser.java @@ -19,9 +19,9 @@ package net.nullsum.audinaut.service.parser; import android.content.Context; -import net.nullsum.audinaut.R; + import net.nullsum.audinaut.domain.MusicDirectory; -import net.nullsum.audinaut.util.ProgressListener; + import org.xmlpull.v1.XmlPullParser; import java.io.InputStream; @@ -35,7 +35,7 @@ public class PlaylistParser extends MusicDirectoryEntryParser { super(context, instance); } - public MusicDirectory parse(InputStream inputStream, ProgressListener progressListener) throws Exception { + public MusicDirectory parse(InputStream inputStream) throws Exception { init(inputStream); MusicDirectory dir = new MusicDirectory(); diff --git a/app/src/main/java/net/nullsum/audinaut/service/parser/PlaylistsParser.java b/app/src/main/java/net/nullsum/audinaut/service/parser/PlaylistsParser.java index 5444819..e31b794 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/parser/PlaylistsParser.java +++ b/app/src/main/java/net/nullsum/audinaut/service/parser/PlaylistsParser.java @@ -21,7 +21,7 @@ package net.nullsum.audinaut.service.parser; import android.content.Context; import net.nullsum.audinaut.domain.Playlist; -import net.nullsum.audinaut.util.ProgressListener; + import org.xmlpull.v1.XmlPullParser; import java.io.InputStream; @@ -37,10 +37,10 @@ public class PlaylistsParser extends AbstractParser { super(context, instance); } - public List parse(InputStream inputStream, ProgressListener progressListener) throws Exception { + public List parse(InputStream inputStream) throws Exception { init(inputStream); - List result = new ArrayList(); + List result = new ArrayList<>(); int eventType; do { eventType = nextParseEvent(); diff --git a/app/src/main/java/net/nullsum/audinaut/service/parser/RandomSongsParser.java b/app/src/main/java/net/nullsum/audinaut/service/parser/RandomSongsParser.java index 20691a3..4919ff0 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/parser/RandomSongsParser.java +++ b/app/src/main/java/net/nullsum/audinaut/service/parser/RandomSongsParser.java @@ -19,9 +19,9 @@ package net.nullsum.audinaut.service.parser; import android.content.Context; -import net.nullsum.audinaut.R; + import net.nullsum.audinaut.domain.MusicDirectory; -import net.nullsum.audinaut.util.ProgressListener; + import org.xmlpull.v1.XmlPullParser; import java.io.InputStream; @@ -35,7 +35,7 @@ public class RandomSongsParser extends MusicDirectoryEntryParser { super(context, instance); } - public MusicDirectory parse(InputStream inputStream, ProgressListener progressListener) throws Exception { + public MusicDirectory parse(InputStream inputStream) throws Exception { init(inputStream); MusicDirectory dir = new MusicDirectory(); diff --git a/app/src/main/java/net/nullsum/audinaut/service/parser/SearchResult2Parser.java b/app/src/main/java/net/nullsum/audinaut/service/parser/SearchResult2Parser.java index 59c9298..5d68efb 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/parser/SearchResult2Parser.java +++ b/app/src/main/java/net/nullsum/audinaut/service/parser/SearchResult2Parser.java @@ -19,16 +19,16 @@ package net.nullsum.audinaut.service.parser; import android.content.Context; -import net.nullsum.audinaut.R; + +import net.nullsum.audinaut.domain.Artist; import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.domain.SearchResult; -import net.nullsum.audinaut.domain.Artist; -import net.nullsum.audinaut.util.ProgressListener; + import org.xmlpull.v1.XmlPullParser; import java.io.InputStream; -import java.util.List; import java.util.ArrayList; +import java.util.List; /** * @author Sindre Mehus @@ -39,12 +39,12 @@ public class SearchResult2Parser extends MusicDirectoryEntryParser { super(context, instance); } - public SearchResult parse(InputStream inputStream, ProgressListener progressListener) throws Exception { + public SearchResult parse(InputStream inputStream) throws Exception { init(inputStream); - List artists = new ArrayList(); - List albums = new ArrayList(); - List songs = new ArrayList(); + List artists = new ArrayList<>(); + List albums = new ArrayList<>(); + List songs = new ArrayList<>(); int eventType; do { eventType = nextParseEvent(); diff --git a/app/src/main/java/net/nullsum/audinaut/service/parser/SubsonicRESTException.java b/app/src/main/java/net/nullsum/audinaut/service/parser/SubsonicRESTException.java index 4381197..be1654e 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/parser/SubsonicRESTException.java +++ b/app/src/main/java/net/nullsum/audinaut/service/parser/SubsonicRESTException.java @@ -4,16 +4,10 @@ package net.nullsum.audinaut.service.parser; * @author Sindre Mehus * @version $Id$ */ -public class SubsonicRESTException extends Exception { +class SubsonicRESTException extends Exception { - private final int code; - - public SubsonicRESTException(int code, String message) { + public SubsonicRESTException(String message) { super(message); - this.code = code; } - public int getCode() { - return code; - } } diff --git a/app/src/main/java/net/nullsum/audinaut/service/parser/UserParser.java b/app/src/main/java/net/nullsum/audinaut/service/parser/UserParser.java index efe5c33..da4952e 100644 --- a/app/src/main/java/net/nullsum/audinaut/service/parser/UserParser.java +++ b/app/src/main/java/net/nullsum/audinaut/service/parser/UserParser.java @@ -16,7 +16,12 @@ package net.nullsum.audinaut.service.parser; import android.content.Context; -import android.util.Log; + +import net.nullsum.audinaut.domain.MusicFolder; +import net.nullsum.audinaut.domain.User; +import net.nullsum.audinaut.domain.User.Setting; +import net.nullsum.audinaut.service.MusicService; +import net.nullsum.audinaut.service.MusicServiceFactory; import org.xmlpull.v1.XmlPullParser; @@ -24,24 +29,15 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.List; -import net.nullsum.audinaut.domain.MusicFolder; -import net.nullsum.audinaut.domain.User; -import net.nullsum.audinaut.domain.User.MusicFolderSetting; -import net.nullsum.audinaut.domain.User.Setting; -import net.nullsum.audinaut.service.MusicService; -import net.nullsum.audinaut.service.MusicServiceFactory; -import net.nullsum.audinaut.util.ProgressListener; - public class UserParser extends AbstractParser { - private static final String TAG = UserParser.class.getSimpleName(); public UserParser(Context context, int instance) { super(context, instance); } - public List parse(InputStream inputStream, ProgressListener progressListener) throws Exception { + public List parse(InputStream inputStream) throws Exception { init(inputStream); - List result = new ArrayList(); + List result = new ArrayList<>(); List musicFolders = null; User user = null; int eventType; @@ -54,9 +50,7 @@ public class UserParser extends AbstractParser { if ("user".equals(tagName)) { user = new User(); - user.setUsername(get("username")); - user.setEmail(get("email")); - for(String role: User.ROLES) { + for (String role : User.ROLES) { parseSetting(user, role); } @@ -64,22 +58,22 @@ public class UserParser extends AbstractParser { } else if ("error".equals(tagName)) { handleError(); } - } else if(eventType == XmlPullParser.TEXT) { - if("folder".equals(tagName)) { + } else if (eventType == XmlPullParser.TEXT) { + if ("folder".equals(tagName)) { String id = getText(); - if(musicFolders == null) { + if (musicFolders == null) { musicFolders = getMusicFolders(); } - if(user != null) { - if(user.getMusicFolderSettings() == null) { + if (user != null) { + if (user.getMusicFolderSettings() == null) { for (MusicFolder musicFolder : musicFolders) { user.addMusicFolder(musicFolder); } } - for(Setting musicFolder: user.getMusicFolderSettings()) { - if(musicFolder.getName().equals(id)) { + for (Setting musicFolder : user.getMusicFolderSettings()) { + if (musicFolder.getName().equals(id)) { musicFolder.setValue(true); break; } @@ -94,14 +88,14 @@ public class UserParser extends AbstractParser { return result; } - private List getMusicFolders() throws Exception{ + private List getMusicFolders() throws Exception { MusicService musicService = MusicServiceFactory.getMusicService(context); return musicService.getMusicFolders(false, context, null); } private void parseSetting(User user, String name) { String value = get(name); - if(value != null) { + if (value != null) { user.addSetting(name, "true".equals(value)); } } diff --git a/app/src/main/java/net/nullsum/audinaut/updates/Updater.java b/app/src/main/java/net/nullsum/audinaut/updates/Updater.java index 4e9a8da..ed07fd3 100644 --- a/app/src/main/java/net/nullsum/audinaut/updates/Updater.java +++ b/app/src/main/java/net/nullsum/audinaut/updates/Updater.java @@ -21,24 +21,25 @@ package net.nullsum.audinaut.updates; import android.content.Context; import android.content.SharedPreferences; import android.util.Log; + import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.SilentBackgroundTask; import net.nullsum.audinaut.util.Util; + import java.util.ArrayList; import java.util.List; /** - * * @author Scott */ public class Updater { - protected String TAG = Updater.class.getSimpleName(); - protected int version; - protected Context context; + private final int version; + String TAG = Updater.class.getSimpleName(); + private Context context; public Updater(int version) { // 5.2 should show as 520 instead of 52 - if(version < 100) { + if (version < 100) { version *= 10; } this.version = version; @@ -46,34 +47,41 @@ public class Updater { public void checkUpdates(Context context) { this.context = context; - List updaters = new ArrayList(); + List updaters = new ArrayList<>(); updaters.add(new UpdaterSongPress()); SharedPreferences prefs = Util.getPreferences(context); int lastVersion = prefs.getInt(Constants.LAST_VERSION, 0); - if(lastVersion == 0) { + if (lastVersion == 0) { SharedPreferences.Editor editor = prefs.edit(); editor.putInt(Constants.LAST_VERSION, version); editor.apply(); - } - else if(version > lastVersion) { + } else if (version > lastVersion) { SharedPreferences.Editor editor = prefs.edit(); editor.putInt(Constants.LAST_VERSION, version); editor.apply(); Log.i(TAG, "Updating from version " + lastVersion + " to " + version); - for(Updater updater: updaters) { - if(updater.shouldUpdate(lastVersion)) { + for (Updater updater : updaters) { + if (updater.shouldUpdate(lastVersion)) { new BackgroundUpdate(context, updater).execute(); } } } } - public String getName() { + private String getName() { return this.TAG; } + private boolean shouldUpdate(int version) { + return this.version > version; + } + + void update(Context context) { + + } + private class BackgroundUpdate extends SilentBackgroundTask { private final Updater updater; @@ -86,17 +94,10 @@ public class Updater { protected Void doInBackground() { try { updater.update(context); - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to run update for " + updater.getName()); } return null; } } - - public boolean shouldUpdate(int version) { - return this.version > version; - } - public void update(Context context) { - - } } diff --git a/app/src/main/java/net/nullsum/audinaut/updates/UpdaterSongPress.java b/app/src/main/java/net/nullsum/audinaut/updates/UpdaterSongPress.java index 81673c2..c1b66a5 100644 --- a/app/src/main/java/net/nullsum/audinaut/updates/UpdaterSongPress.java +++ b/app/src/main/java/net/nullsum/audinaut/updates/UpdaterSongPress.java @@ -21,7 +21,7 @@ import android.content.SharedPreferences; import net.nullsum.audinaut.util.Constants; import net.nullsum.audinaut.util.Util; -public class UpdaterSongPress extends Updater { +class UpdaterSongPress extends Updater { public UpdaterSongPress() { super(521); TAG = this.getClass().getSimpleName(); @@ -33,7 +33,7 @@ public class UpdaterSongPress extends Updater { boolean playNowAfter = prefs.getBoolean("playNowAfter", true); // Migrate the old preference so behavior stays the same - if(playNowAfter == false) { + if (!playNowAfter) { SharedPreferences.Editor editor = prefs.edit(); editor.putString(Constants.PREFERENCES_KEY_SONG_PRESS_ACTION, "single"); editor.apply(); diff --git a/app/src/main/java/net/nullsum/audinaut/util/BackgroundTask.java b/app/src/main/java/net/nullsum/audinaut/util/BackgroundTask.java index 9147581..f1b5ea5 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/BackgroundTask.java +++ b/app/src/main/java/net/nullsum/audinaut/util/BackgroundTask.java @@ -18,85 +18,73 @@ */ package net.nullsum.audinaut.util; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.xmlpull.v1.XmlPullParserException; - import android.app.Activity; import android.content.Context; import android.os.Handler; import android.os.Looper; import android.util.Log; + import net.nullsum.audinaut.R; import net.nullsum.audinaut.view.ErrorDialog; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.atomic.AtomicBoolean; + /** * @author Sindre Mehus */ public abstract class BackgroundTask implements ProgressListener { + static final BlockingQueue queue = new LinkedBlockingQueue<>(10); private static final String TAG = BackgroundTask.class.getSimpleName(); - - private final Context context; - protected AtomicBoolean cancelled = new AtomicBoolean(false); - protected OnCancelListener cancelListener; - protected Runnable onCompletionListener = null; - protected Task task; - private static final int DEFAULT_CONCURRENCY = 8; private static final Collection threads = Collections.synchronizedCollection(new ArrayList()); - protected static final BlockingQueue queue = new LinkedBlockingQueue(10); private static Handler handler = null; + static { try { handler = new Handler(Looper.getMainLooper()); - } catch(Exception e) { + } catch (Exception e) { // Not called from main thread } } - public BackgroundTask(Context context) { + final AtomicBoolean cancelled = new AtomicBoolean(false); + private final Context context; + private final Runnable onCompletionListener = null; + Task task; + + BackgroundTask(Context context) { this.context = context; - if(threads.size() < DEFAULT_CONCURRENCY) { - for(int i = threads.size(); i < DEFAULT_CONCURRENCY; i++) { + if (threads.size() < DEFAULT_CONCURRENCY) { + for (int i = threads.size(); i < DEFAULT_CONCURRENCY; i++) { Thread thread = new Thread(new TaskRunnable(), String.format("BackgroundTask_%d", i)); threads.add(thread); thread.start(); } } - if(handler == null) { + if (handler == null) { try { handler = new Handler(Looper.getMainLooper()); - } catch(Exception e) { + } catch (Exception e) { // Not called from main thread } } } - public static void stopThreads() { - for(Thread thread: threads) { - thread.interrupt(); - } - threads.clear(); - queue.clear(); - } - - protected Activity getActivity() { + private Activity getActivity() { return (context instanceof Activity) ? ((Activity) context) : null; } - protected Context getContext() { - return context; - } - protected Handler getHandler() { + Handler getHandler() { return handler; } @@ -109,7 +97,7 @@ public abstract class BackgroundTask implements ProgressListener { protected void error(Throwable error) { Log.w(TAG, "Got exception: " + error, error); Activity activity = getActivity(); - if(activity != null) { + if (activity != null) { new ErrorDialog(activity, getErrorMessage(error), true); } } @@ -140,39 +128,27 @@ public abstract class BackgroundTask implements ProgressListener { } public void cancel() { - if(cancelled.compareAndSet(false, true)) { - if(isRunning()) { - if(cancelListener != null) { - cancelListener.onCancel(); - } else { - task.cancel(); - } + if (cancelled.compareAndSet(false, true)) { + if (isRunning()) { + task.cancel(); } - task = null; } } + public boolean isCancelled() { return cancelled.get(); } - public void setOnCancelListener(OnCancelListener listener) { - cancelListener = listener; - } public boolean isRunning() { - if(task == null) { - return false; - } else { - return task.isRunning(); - } + return task != null && task.isRunning(); } @Override public abstract void updateProgress(final String message); - @Override - public void updateProgress(int messageId) { - updateProgress(context.getResources().getString(messageId)); + public void updateProgress() { + updateProgress(context.getResources().getString(R.string.settings_testing_connection)); } @Override @@ -180,17 +156,13 @@ public abstract class BackgroundTask implements ProgressListener { } - public void setOnCompletionListener(Runnable onCompletionListener) { - this.onCompletionListener = onCompletionListener; - } - - protected class Task { + class Task { + private final AtomicBoolean taskStart = new AtomicBoolean(false); private Thread thread; - private AtomicBoolean taskStart = new AtomicBoolean(false); private void execute() throws Exception { // Don't run if cancelled already - if(isCancelled()) { + if (isCancelled()) { return; } @@ -199,60 +171,54 @@ public abstract class BackgroundTask implements ProgressListener { taskStart.set(true); final T result = doInBackground(); - if(isCancelled()) { + if (isCancelled()) { taskStart.set(false); return; } - if(handler != null) { - handler.post(new Runnable() { - @Override - public void run() { - if (!isCancelled()) { - try { - onDone(result); - } catch (Throwable t) { - if(!isCancelled()) { - try { - onError(t); - } catch(Exception e) { - // Don't care - } + if (handler != null) { + handler.post(() -> { + if (!isCancelled()) { + try { + onDone(result); + } catch (Throwable t) { + if (!isCancelled()) { + try { + onError(t); + } catch (Exception e) { + // Don't care } } } - - taskStart.set(false); } + + taskStart.set(false); }); } else { taskStart.set(false); } - } catch(InterruptedException interrupt) { - if(taskStart.get()) { + } catch (InterruptedException interrupt) { + if (taskStart.get()) { // Don't exit root thread if task cancelled throw interrupt; } - } catch(final Throwable t) { - if(isCancelled()) { + } catch (final Throwable t) { + if (isCancelled()) { taskStart.set(false); return; } - if(handler != null) { - handler.post(new Runnable() { - @Override - public void run() { - if(!isCancelled()) { - try { - onError(t); - } catch(Exception e) { - // Don't care - } + if (handler != null) { + handler.post(() -> { + if (!isCancelled()) { + try { + onError(t); + } catch (Exception e) { + // Don't care } - - taskStart.set(false); } + + taskStart.set(false); }); } else { taskStart.set(false); @@ -263,28 +229,25 @@ public abstract class BackgroundTask implements ProgressListener { } public void cancel() { - if(taskStart.compareAndSet(true, false)) { + if (taskStart.compareAndSet(true, false)) { if (thread != null) { thread.interrupt(); } } } + public boolean isCancelled() { - if(Thread.interrupted()) { - return true; - } else if(BackgroundTask.this.isCancelled()) { - return true; - } else { - return false; - } + return Thread.interrupted() || BackgroundTask.this.isCancelled(); } + public void onDone(T result) { done(result); - if(onCompletionListener != null) { + if (onCompletionListener != null) { onCompletionListener.run(); } } + public void onError(Throwable t) { error(t); } @@ -304,22 +267,18 @@ public abstract class BackgroundTask implements ProgressListener { @Override public void run() { Looper.prepare(); - while(running) { + while (running) { try { Task task = queue.take(); task.execute(); - } catch(InterruptedException stop) { + } catch (InterruptedException stop) { Log.e(TAG, "Thread died"); running = false; threads.remove(Thread.currentThread()); - } catch(Throwable t) { + } catch (Throwable t) { Log.e(TAG, "Unexpected crash in BackgroundTask thread", t); } } } } - - public static interface OnCancelListener { - void onCancel(); - } } diff --git a/app/src/main/java/net/nullsum/audinaut/util/BufferFile.java b/app/src/main/java/net/nullsum/audinaut/util/BufferFile.java index ac18403..37e72ee 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/BufferFile.java +++ b/app/src/main/java/net/nullsum/audinaut/util/BufferFile.java @@ -19,10 +19,16 @@ import java.io.File; public interface BufferFile { File getFile(); + Long getContentLength(); + long getEstimatedSize(); + boolean isWorkDone(); + void onStart(); + void onStop(); + void onResume(); } diff --git a/app/src/main/java/net/nullsum/audinaut/util/BufferProxy.java b/app/src/main/java/net/nullsum/audinaut/util/BufferProxy.java index 907a0b5..e700ed8 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/BufferProxy.java +++ b/app/src/main/java/net/nullsum/audinaut/util/BufferProxy.java @@ -18,17 +18,8 @@ package net.nullsum.audinaut.util; import java.io.File; import java.net.Socket; -import android.content.Context; - -import net.nullsum.audinaut.util.FileProxy; - public class BufferProxy extends FileProxy { - private static final String TAG = BufferProxy.class.getSimpleName(); - protected BufferFile progress; - - public BufferProxy(Context context) { - super(context); - } + private BufferFile progress; protected ProxyTask getTask(Socket client) { return new BufferFileTask(client); @@ -51,11 +42,12 @@ public class BufferProxy extends FileProxy { @Override Long getContentLength() { Long contentLength = progress.getContentLength(); - if(contentLength == null && progress.isWorkDone()) { + if (contentLength == null && progress.isWorkDone()) { contentLength = file.length(); } return contentLength; } + @Override long getFileSize() { return progress.getEstimatedSize(); @@ -65,10 +57,12 @@ public class BufferProxy extends FileProxy { public void onStart() { progress.onStart(); } + @Override public void onStop() { progress.onStop(); } + @Override public void onResume() { progress.onResume(); diff --git a/app/src/main/java/net/nullsum/audinaut/util/CacheCleaner.java b/app/src/main/java/net/nullsum/audinaut/util/CacheCleaner.java index b275c68..5e55cca 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/CacheCleaner.java +++ b/app/src/main/java/net/nullsum/audinaut/util/CacheCleaner.java @@ -1,22 +1,21 @@ package net.nullsum.audinaut.util; -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - import android.content.Context; -import android.util.Log; import android.os.StatFs; +import android.util.Log; + import net.nullsum.audinaut.domain.Playlist; import net.nullsum.audinaut.service.DownloadFile; import net.nullsum.audinaut.service.DownloadService; import net.nullsum.audinaut.service.MediaStoreService; -import java.util.*; +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.SortedSet; /** * @author Sindre Mehus @@ -41,9 +40,11 @@ public class CacheCleaner { public void clean() { new BackgroundCleanup(context).execute(); } + public void cleanSpace() { new BackgroundSpaceCleanup(context).execute(); } + public void cleanPlaylists(List playlists) { new BackgroundPlaylistsCleanup(context, playlists).execute(); } @@ -59,7 +60,7 @@ public class CacheCleaner { } private long getMinimumDelete(List files, List pinned) { - if(files.size() == 0) { + if (files.size() == 0) { return 0L; } @@ -75,8 +76,8 @@ public class CacheCleaner { // Ensure that file system is not more than 95% full. StatFs stat = new StatFs(files.get(0).getPath()); - long bytesTotalFs = (long) stat.getBlockCount() * (long) stat.getBlockSize(); - long bytesAvailableFs = (long) stat.getAvailableBlocks() * (long) stat.getBlockSize(); + long bytesTotalFs = stat.getBlockCountLong() * stat.getBlockSizeLong(); + long bytesAvailableFs = stat.getAvailableBlocksLong() * stat.getBlockSizeLong(); long bytesUsedFs = bytesTotalFs - bytesAvailableFs; long minFsAvailability = bytesTotalFs - MIN_FREE_SPACE; @@ -99,7 +100,7 @@ public class CacheCleaner { long bytesDeleted = 0L; for (File file : files) { - if(!deletePartials && bytesDeleted > bytesToDelete) break; + if (!deletePartials && bytesDeleted > bytesToDelete) break; if (bytesToDelete > bytesDeleted || (deletePartials && (file.getName().endsWith(".partial") || file.getName().contains(".partial.")))) { if (!undeletable.contains(file) && !file.getName().equals(Constants.ALBUM_ART_FILE)) { @@ -134,22 +135,19 @@ public class CacheCleaner { } private void sortByAscendingModificationTime(List files) { - Collections.sort(files, new Comparator() { - @Override - public int compare(File a, File b) { - if (a.lastModified() < b.lastModified()) { - return -1; - } - if (a.lastModified() > b.lastModified()) { - return 1; - } - return 0; + Collections.sort(files, (a, b) -> { + if (a.lastModified() < b.lastModified()) { + return -1; } + if (a.lastModified() > b.lastModified()) { + return 1; + } + return 0; }); } private Set findUndeletableFiles() { - Set undeletable = new HashSet(5); + Set undeletable = new HashSet<>(5); for (DownloadFile downloadFile : downloadService.getDownloads()) { undeletable.add(downloadFile.getPartialFile()); @@ -163,30 +161,30 @@ public class CacheCleaner { private void cleanupCoverArt(Context context) { File dir = FileUtil.getAlbumArtDirectory(context); - List files = new ArrayList(); + List files = new ArrayList<>(); long bytesUsed = 0L; - for(File file: dir.listFiles()) { - if(file.isFile()) { + for (File file : dir.listFiles()) { + if (file.isFile()) { files.add(file); bytesUsed += file.length(); } } // Don't waste time sorting if under limit already - if(bytesUsed < MAX_COVER_ART_SPACE) { + if (bytesUsed < MAX_COVER_ART_SPACE) { return; } sortByAscendingModificationTime(files); long bytesDeleted = 0L; - for(File file: files) { + for (File file : files) { // End as soon as the space used is below the threshold - if(bytesUsed < MAX_COVER_ART_SPACE) { + if (bytesUsed < MAX_COVER_ART_SPACE) { break; } long bytes = file.length(); - if(file.delete()) { + if (file.delete()) { bytesUsed -= bytes; bytesDeleted += bytes; } @@ -208,9 +206,9 @@ public class CacheCleaner { } try { - List files = new ArrayList(); - List pinned = new ArrayList(); - List dirs = new ArrayList(); + List files = new ArrayList<>(); + List pinned = new ArrayList<>(); + List dirs = new ArrayList<>(); findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, pinned, dirs); sortByAscendingModificationTime(files); @@ -243,13 +241,13 @@ public class CacheCleaner { } try { - List files = new ArrayList(); - List pinned = new ArrayList(); - List dirs = new ArrayList(); + List files = new ArrayList<>(); + List pinned = new ArrayList<>(); + List dirs = new ArrayList<>(); findCandidatesForDeletion(FileUtil.getMusicDirectory(context), files, pinned, dirs); long bytesToDelete = getMinimumDelete(files, pinned); - if(bytesToDelete > 0L) { + if (bytesToDelete > 0L) { sortByAscendingModificationTime(files); Set undeletable = findUndeletableFiles(); deleteFiles(files, undeletable, bytesToDelete, false); @@ -279,7 +277,7 @@ public class CacheCleaner { playlistFiles.remove(FileUtil.getPlaylistFile(context, server, playlist.getName())); } - for(File playlist : playlistFiles) { + for (File playlist : playlistFiles) { playlist.delete(); } } catch (RuntimeException x) { diff --git a/app/src/main/java/net/nullsum/audinaut/util/Constants.java b/app/src/main/java/net/nullsum/audinaut/util/Constants.java index 283dc5a..ce00a09 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/Constants.java +++ b/app/src/main/java/net/nullsum/audinaut/util/Constants.java @@ -37,7 +37,6 @@ public final class Constants { public static final String INTENT_EXTRA_NAME_DIRECTORY = "subsonic.directory"; public static final String INTENT_EXTRA_NAME_CHILD_ID = "subsonic.child.id"; public static final String INTENT_EXTRA_NAME_ARTIST = "subsonic.artist"; - public static final String INTENT_EXTRA_NAME_TITLE = "subsonic.title"; public static final String INTENT_EXTRA_NAME_AUTOPLAY = "subsonic.playall"; public static final String INTENT_EXTRA_NAME_QUERY = "subsonic.query"; public static final String INTENT_EXTRA_NAME_PLAYLIST_ID = "subsonic.playlist.id"; @@ -48,18 +47,14 @@ public final class Constants { public static final String INTENT_EXTRA_NAME_ALBUM_LIST_SIZE = "subsonic.albumlistsize"; public static final String INTENT_EXTRA_NAME_ALBUM_LIST_OFFSET = "subsonic.albumlistoffset"; public static final String INTENT_EXTRA_NAME_SHUFFLE = "subsonic.shuffle"; - public static final String INTENT_EXTRA_REQUEST_SEARCH = "subsonic.requestsearch"; - public static final String INTENT_EXTRA_NAME_EXIT = "subsonic.exit" ; + public static final String INTENT_EXTRA_NAME_EXIT = "subsonic.exit"; public static final String INTENT_EXTRA_NAME_DOWNLOAD = "subsonic.download"; public static final String INTENT_EXTRA_NAME_DOWNLOAD_VIEW = "subsonic.download_view"; public static final String INTENT_EXTRA_VIEW_ALBUM = "subsonic.view_album"; - public static final String INTENT_EXTRA_NAME_SHARE = "subsonic.share"; public static final String INTENT_EXTRA_FRAGMENT_TYPE = "fragmentType"; public static final String INTENT_EXTRA_REFRESH_LISTINGS = "refreshListings"; public static final String INTENT_EXTRA_SEARCH_SONG = "searchSong"; public static final String INTENT_EXTRA_TOP_TRACKS = "topTracks"; - public static final String INTENT_EXTRA_PLAY_LAST = "playLast"; - public static final String INTENT_EXTRA_ENTRY = "passedEntry"; // Preferences keys. public static final String PREFERENCES_KEY_SERVER_KEY = "server"; @@ -76,7 +71,6 @@ public final class Constants { public static final String PREFERENCES_KEY_MUSIC_FOLDER_ID = "musicFolderId"; public static final String PREFERENCES_KEY_USERNAME = "username"; public static final String PREFERENCES_KEY_PASSWORD = "password"; - public static final String PREFERENCES_KEY_INSTALL_TIME = "installTime"; public static final String PREFERENCES_KEY_THEME = "theme"; public static final String PREFERENCES_KEY_FULL_SCREEN = "fullScreen"; public static final String PREFERENCES_KEY_DISPLAY_TRACK = "displayTrack"; @@ -98,7 +92,6 @@ public final class Constants { public static final String PREFERENCES_KEY_SHUFFLE_START_YEAR = "startYear"; public static final String PREFERENCES_KEY_SHUFFLE_END_YEAR = "endYear"; public static final String PREFERENCES_KEY_SHUFFLE_GENRE = "genre"; - public static final String PREFERENCES_KEY_KEEP_SCREEN_ON = "keepScreenOn"; public static final String PREFERENCES_EQUALIZER_ON = "equalizerOn"; public static final String PREFERENCES_EQUALIZER_SETTINGS = "equalizerSettings"; public static final String PREFERENCES_KEY_PERSISTENT_NOTIFICATION = "persistentNotification"; @@ -106,7 +99,6 @@ public final class Constants { public static final String PREFERENCES_KEY_REMOVE_PLAYED = "removePlayed"; public static final String PREFERENCES_KEY_KEEP_PLAYED_CNT = "keepPlayedCount"; public static final String PREFERENCES_KEY_SHUFFLE_MODE = "shuffleMode2"; - public static final String PREFERENCES_KEY_SHUFFLE_MODE_EXTRA = "shuffleModeExtra"; public static final String PREFERENCES_KEY_SYNC_ENABLED = "syncEnabled"; public static final String PREFERENCES_KEY_SYNC_INTERVAL = "syncInterval"; public static final String PREFERENCES_KEY_SYNC_WIFI = "syncWifi"; @@ -115,8 +107,6 @@ public final class Constants { public static final String PREFERENCES_KEY_PAUSE_DISCONNECT = "pauseOnDisconnect"; public static final String PREFERENCES_KEY_HIDE_WIDGET = "hideWidget"; public static final String PREFERENCES_KEY_CUSTOM_SORT_ENABLED = "customSortEnabled"; - public static final String PREFERENCES_KEY_SHARED_ENABLED = "sharedEnabled"; - public static final String PREFERENCES_KEY_OPEN_TO_TAB = "openToTab"; // public static final String PREFERENCES_KEY_PLAY_NOW_AFTER = "playNowAfter"; public static final String PREFERENCES_KEY_SONG_PRESS_ACTION = "songPressAction"; public static final String PREFERENCES_KEY_LARGE_ALBUM_ART = "largeAlbumArt"; @@ -126,7 +116,7 @@ public final class Constants { public static final String PREFERENCES_KEY_REPLAY_GAIN = "replayGain"; public static final String PREFERENCES_KEY_REPLAY_GAIN_BUMP = "replayGainBump2"; public static final String PREFERENCES_KEY_REPLAY_GAIN_UNTAGGED = "replayGainUntagged2"; - public static final String PREFERENCES_KEY_REPLAY_GAIN_TYPE= "replayGainType"; + public static final String PREFERENCES_KEY_REPLAY_GAIN_TYPE = "replayGainType"; public static final String PREFERENCES_KEY_ALBUMS_PER_FOLDER = "albumsPerFolder"; public static final String PREFERENCES_KEY_FIRST_LEVEL_ARTIST = "firstLevelArtist"; public static final String PREFERENCES_KEY_START_ON_HEADPHONES = "startOnHeadphones"; @@ -134,12 +124,6 @@ public final class Constants { public static final String PREFERENCES_KEY_SHUFFLE_BY_ALBUM = "shuffleByAlbum"; public static final String PREFERENCES_KEY_RESUME_PLAY_QUEUE_NEVER = "neverResumePlayQueue"; public static final String PREFERENCES_KEY_BATCH_MODE = "batchMode"; - public static final String PREFERENCES_KEY_HEADS_UP_NOTIFICATION = "headsUpNotification"; - - public static final String OFFLINE_STAR_COUNT = "starCount"; - public static final String OFFLINE_STAR_ID = "starID"; - public static final String OFFLINE_STAR_SEARCH = "starTitle"; - public static final String OFFLINE_STAR_SETTING = "starSetting"; public static final String CACHE_KEY_IGNORE = "ignoreArticles"; public static final String CACHE_AUDIO_SESSION_ID = "audioSessionId"; @@ -152,21 +136,17 @@ public final class Constants { public static final String MAIN_SLIDE_PANEL_STATE = "slidePanelState"; public static final String FRAGMENT_LIST = "fragmentList"; public static final String FRAGMENT_LIST2 = "fragmentList2"; - public static final String FRAGMENT_EXTRA = "fragmentExtra"; public static final String FRAGMENT_DOWNLOAD_FLIPPER = "fragmentDownloadFlipper"; public static final String FRAGMENT_NAME = "fragmentName"; public static final String FRAGMENT_POSITION = "fragmentPosition"; // Name of the preferences file. public static final String PREFERENCES_FILE_NAME = "net.nullsum.audinaut_preferences"; - public static final String OFFLINE_SYNC_NAME = "net.nullsum.audinaut.offline"; - public static final String OFFLINE_SYNC_DEFAULT = "syncDefaults"; // Account prefs public static final String SYNC_ACCOUNT_NAME = "Subsonic Account"; public static final String SYNC_ACCOUNT_TYPE = "Audinaut"; public static final String SYNC_ACCOUNT_PLAYLIST_AUTHORITY = "net.nullsum.audinaut.playlists.provider"; - public static final String SYNC_ACCOUNT_MOST_RECENT_AUTHORITY = "net.nullsum.audinaut.mostrecent.provider"; public static final String TASKER_EXTRA_BUNDLE = "com.twofortyfouram.locale.intent.extra.BUNDLE"; diff --git a/app/src/main/java/net/nullsum/audinaut/util/DownloadFileItemHelperCallback.java b/app/src/main/java/net/nullsum/audinaut/util/DownloadFileItemHelperCallback.java index 8db0310..4bd2958 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/DownloadFileItemHelperCallback.java +++ b/app/src/main/java/net/nullsum/audinaut/util/DownloadFileItemHelperCallback.java @@ -2,10 +2,6 @@ package net.nullsum.audinaut.util; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; -import android.util.Log; - -import java.util.ArrayDeque; -import java.util.Deque; import net.nullsum.audinaut.adapter.SectionAdapter; import net.nullsum.audinaut.fragments.SubsonicFragment; @@ -14,14 +10,15 @@ import net.nullsum.audinaut.service.DownloadService; import net.nullsum.audinaut.view.SongView; import net.nullsum.audinaut.view.UpdateView; +import java.util.ArrayDeque; +import java.util.Deque; + public class DownloadFileItemHelperCallback extends ItemTouchHelper.SimpleCallback { - private static final String TAG = DownloadFileItemHelperCallback.class.getSimpleName(); - - private SubsonicFragment fragment; - private boolean mainList; + private final SubsonicFragment fragment; + private final boolean mainList; + private final Deque pendingOperations = new ArrayDeque(); private BackgroundTask pendingTask = null; - private Deque pendingOperations = new ArrayDeque(); public DownloadFileItemHelperCallback(SubsonicFragment fragment, boolean mainList) { super(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT); @@ -54,17 +51,18 @@ public class DownloadFileItemHelperCallback extends ItemTouchHelper.SimpleCallba } } - public DownloadService getDownloadService() { + private DownloadService getDownloadService() { return fragment.getDownloadService(); } - public SectionAdapter getSectionAdapter() { + + private SectionAdapter getSectionAdapter() { return fragment.getCurrentAdapter(); } private void updateDownloadService() { - if(pendingTask == null) { + if (pendingTask == null) { final DownloadService downloadService = getDownloadService(); - if(downloadService == null) { + if (downloadService == null) { return; } @@ -72,21 +70,21 @@ public class DownloadFileItemHelperCallback extends ItemTouchHelper.SimpleCallba @Override protected Void doInBackground() throws Throwable { boolean running = true; - while(running) { + while (running) { Object nextOperation = null; synchronized (pendingOperations) { - if(!pendingOperations.isEmpty()) { + if (!pendingOperations.isEmpty()) { nextOperation = pendingOperations.remove(); } } - if(nextOperation != null) { - if(nextOperation instanceof Pair) { + if (nextOperation != null) { + if (nextOperation instanceof Pair) { Pair swap = (Pair) nextOperation; downloadService.swap(mainList, swap.getFirst(), swap.getSecond()); - } else if(nextOperation instanceof DownloadFile) { + } else if (nextOperation instanceof DownloadFile) { DownloadFile downloadFile = (DownloadFile) nextOperation; - if(mainList) { + if (mainList) { downloadService.remove(downloadFile); } else { downloadService.removeBackground(downloadFile); @@ -101,7 +99,7 @@ public class DownloadFileItemHelperCallback extends ItemTouchHelper.SimpleCallba pendingTask = null; // Start a task if this is non-empty. Means someone added while we were running operations - if(!pendingOperations.isEmpty()) { + if (!pendingOperations.isEmpty()) { updateDownloadService(); } } diff --git a/app/src/main/java/net/nullsum/audinaut/util/DrawableTint.java b/app/src/main/java/net/nullsum/audinaut/util/DrawableTint.java index 76678ca..2fa9360 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/DrawableTint.java +++ b/app/src/main/java/net/nullsum/audinaut/util/DrawableTint.java @@ -21,48 +21,46 @@ import android.content.res.TypedArray; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.support.annotation.AttrRes; -import android.support.annotation.ColorRes; import android.support.annotation.DrawableRes; import android.util.TypedValue; +import net.nullsum.audinaut.R; + import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; -import net.nullsum.audinaut.R; - public class DrawableTint { private static final Map attrMap = new HashMap<>(); private static final WeakHashMap tintedDrawables = new WeakHashMap<>(); - public static Drawable getTintedDrawable(Context context, @DrawableRes int drawableRes) { - return getTintedDrawable(context, drawableRes, R.attr.colorAccent); - } - public static Drawable getTintedDrawable(Context context, @DrawableRes int drawableRes, @AttrRes int colorAttr) { - if(tintedDrawables.containsKey(drawableRes)) { - return tintedDrawables.get(drawableRes); + public static Drawable getTintedDrawable(Context context) { + if (tintedDrawables.containsKey(R.drawable.ic_toggle_played)) { + return tintedDrawables.get(R.drawable.ic_toggle_played); } - int color = getColorRes(context, colorAttr); - Drawable background = context.getResources().getDrawable(drawableRes); + int color = getColorRes(context, R.attr.colorAccent); + Drawable background = context.getResources().getDrawable(R.drawable.ic_toggle_played); background.setColorFilter(color, PorterDuff.Mode.SRC_IN); - tintedDrawables.put(drawableRes, background); + tintedDrawables.put(R.drawable.ic_toggle_played, background); return background; } - public static Drawable getTintedDrawableFromColor(Context context, @DrawableRes int drawableRes, @ColorRes int colorRes) { - if(tintedDrawables.containsKey(drawableRes)) { - return tintedDrawables.get(drawableRes); + + public static Drawable getTintedDrawableFromColor(Context context) { + if (tintedDrawables.containsKey(R.drawable.abc_spinner_mtrl_am_alpha)) { + return tintedDrawables.get(R.drawable.abc_spinner_mtrl_am_alpha); } - int color = context.getResources().getColor(colorRes); - Drawable background = context.getResources().getDrawable(drawableRes); + int color = context.getResources().getColor(android.R.color.white); + Drawable background = context.getResources().getDrawable(R.drawable.abc_spinner_mtrl_am_alpha); background.setColorFilter(color, PorterDuff.Mode.SRC_IN); - tintedDrawables.put(drawableRes, background); + tintedDrawables.put(R.drawable.abc_spinner_mtrl_am_alpha, background); return background; } + public static int getColorRes(Context context, @AttrRes int colorAttr) { int color; - if(attrMap.containsKey(colorAttr)) { + if (attrMap.containsKey(colorAttr)) { color = attrMap.get(colorAttr); } else { TypedValue typedValue = new TypedValue(); @@ -74,8 +72,9 @@ public class DrawableTint { return color; } + public static int getDrawableRes(Context context, @AttrRes int drawableAttr) { - if(attrMap.containsKey(drawableAttr)) { + if (attrMap.containsKey(drawableAttr)) { return attrMap.get(drawableAttr); } else { int[] attrs = new int[]{drawableAttr}; @@ -86,14 +85,6 @@ public class DrawableTint { return drawableRes; } } - public static Drawable getTintedAttrDrawable(Context context, @AttrRes int drawableAttr, @AttrRes int colorAttr) { - if(tintedDrawables.containsKey(drawableAttr)) { - return getTintedDrawable(context, attrMap.get(drawableAttr), colorAttr); - } - - @DrawableRes int drawableRes = getDrawableRes(context, drawableAttr); - return getTintedDrawable(context, drawableRes, colorAttr); - } public static void wipeTintCache() { attrMap.clear(); diff --git a/app/src/main/java/net/nullsum/audinaut/util/EnvironmentVariables.java b/app/src/main/java/net/nullsum/audinaut/util/EnvironmentVariables.java deleted file mode 100644 index bbecfed..0000000 --- a/app/src/main/java/net/nullsum/audinaut/util/EnvironmentVariables.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - This file is part of Subsonic. - Subsonic is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - Subsonic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with Subsonic. If not, see . - Copyright 2016 (C) Scott Jackson -*/ - -package net.nullsum.audinaut.util; - -public final class EnvironmentVariables { - public static final String PASTEBIN_DEV_KEY = ""; -} diff --git a/app/src/main/java/net/nullsum/audinaut/util/FileProxy.java b/app/src/main/java/net/nullsum/audinaut/util/FileProxy.java index 1fb284d..ab151a0 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/FileProxy.java +++ b/app/src/main/java/net/nullsum/audinaut/util/FileProxy.java @@ -15,6 +15,8 @@ package net.nullsum.audinaut.util; +import android.util.Log; + import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; @@ -23,18 +25,9 @@ import java.io.OutputStream; import java.net.Socket; import java.net.SocketException; -import android.content.Context; -import android.util.Log; - -import net.nullsum.audinaut.util.ServerProxy; - public class FileProxy extends ServerProxy { private static final String TAG = FileProxy.class.getSimpleName(); - public FileProxy(Context context) { - super(context); - } - protected ProxyTask getTask(Socket client) { return new StreamFileTask(client); } @@ -48,7 +41,7 @@ public class FileProxy extends ServerProxy { @Override public boolean processRequest() { - if(!super.processRequest()) { + if (!super.processRequest()) { return false; } @@ -60,11 +53,7 @@ public class FileProxy extends ServerProxy { } // Make sure to not try to read past where the file is downloaded - if(cbSkip != 0 && cbSkip >= file.length()) { - return false; - } - - return true; + return !(cbSkip != 0 && cbSkip >= file.length()); } File getFile(String path) { @@ -74,6 +63,7 @@ public class FileProxy extends ServerProxy { Long getContentLength() { return file.length(); } + long getFileSize() { return file.length(); } @@ -84,12 +74,12 @@ public class FileProxy extends ServerProxy { // Create HTTP header String headers; - if(cbSkip == 0) { + if (cbSkip == 0) { headers = "HTTP/1.0 200 OK\r\n"; } else { headers = "HTTP/1.0 206 OK\r\n"; headers += "Content-Range: bytes " + cbSkip + "-" + (file.length() - 1) + "/"; - if(contentLength == null) { + if (contentLength == null) { headers += "*"; } else { headers += contentLength; @@ -102,21 +92,21 @@ public class FileProxy extends ServerProxy { String name = file.getPath(); int index = name.lastIndexOf('.'); String ext = ""; - if(index != -1) { + if (index != -1) { ext = name.substring(index + 1).toLowerCase(); } - if("mp3".equals(ext)) { + if ("mp3".equals(ext)) { headers += "Content-Type: audio/mpeg\r\n"; } else { headers += "Content-Type: " + "application/octet-stream" + "\r\n"; } long fileSize; - if(contentLength == null) { + if (contentLength == null) { fileSize = getFileSize(); } else { fileSize = contentLength; - if(cbSkip > 0) { + if (cbSkip > 0) { headers += "Content-Length: " + (fileSize - cbSkip) + "\r\n"; } else { headers += "Content-Length: " + fileSize + "\r\n"; @@ -132,7 +122,7 @@ public class FileProxy extends ServerProxy { OutputStream output = null; byte[] buff = new byte[64 * 1024]; try { - output = new BufferedOutputStream(client.getOutputStream(), 32*1024); + output = new BufferedOutputStream(client.getOutputStream(), 32 * 1024); output.write(headers.getBytes()); // Make sure to have file lock @@ -165,7 +155,7 @@ public class FileProxy extends ServerProxy { } // Done regardless of whether or not it thinks it is - if(isWorkDone()) { + if (isWorkDone()) { break; } @@ -178,14 +168,12 @@ public class FileProxy extends ServerProxy { // Release file lock, use of stream proxy means nothing else is using it onStop(); - } - catch (SocketException socketException) { + } catch (SocketException socketException) { Log.e(TAG, "SocketException() thrown, proxy client has probably closed. This can exit harmlessly"); // Release file lock, use of stream proxy means nothing else is using it onStop(); - } - catch (Exception e) { + } catch (Exception e) { Log.e(TAG, "Exception thrown from streaming task:"); Log.e(TAG, e.getClass().getName() + " : " + e.getLocalizedMessage()); } @@ -196,8 +184,7 @@ public class FileProxy extends ServerProxy { output.close(); } client.close(); - } - catch (IOException e) { + } catch (IOException e) { Log.e(TAG, "IOException while cleaning up streaming task:"); Log.e(TAG, e.getClass().getName() + " : " + e.getLocalizedMessage()); } @@ -206,12 +193,15 @@ public class FileProxy extends ServerProxy { public void onStart() { } + public void onStop() { } + public void onResume() { } + public boolean isWorkDone() { return cbSkip >= file.length(); } diff --git a/app/src/main/java/net/nullsum/audinaut/util/FileUtil.java b/app/src/main/java/net/nullsum/audinaut/util/FileUtil.java index c8cbd48..4cc9f96 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/FileUtil.java +++ b/app/src/main/java/net/nullsum/audinaut/util/FileUtil.java @@ -18,6 +18,26 @@ */ package net.nullsum.audinaut.util; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Build; +import android.os.Environment; +import android.support.v4.content.ContextCompat; +import android.util.Log; + +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; + +import net.nullsum.audinaut.domain.Artist; +import net.nullsum.audinaut.domain.Genre; +import net.nullsum.audinaut.domain.Indexes; +import net.nullsum.audinaut.domain.MusicDirectory; +import net.nullsum.audinaut.domain.MusicFolder; +import net.nullsum.audinaut.domain.Playlist; +import net.nullsum.audinaut.service.MediaStoreService; + import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; @@ -28,34 +48,16 @@ import java.io.IOException; import java.io.RandomAccessFile; import java.io.Serializable; import java.util.Arrays; +import java.util.Collections; import java.util.Date; import java.util.HashMap; -import java.util.SortedSet; -import java.util.TreeSet; import java.util.Iterator; import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.zip.DeflaterOutputStream; import java.util.zip.InflaterInputStream; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.os.Build; -import android.os.Environment; -import android.support.v4.content.ContextCompat; -import android.util.Log; -import net.nullsum.audinaut.domain.Artist; -import net.nullsum.audinaut.domain.Genre; -import net.nullsum.audinaut.domain.Indexes; -import net.nullsum.audinaut.domain.Playlist; -import net.nullsum.audinaut.domain.MusicDirectory; -import net.nullsum.audinaut.domain.MusicFolder; -import net.nullsum.audinaut.service.MediaStoreService; - -import com.esotericsoftware.kryo.Kryo; -import com.esotericsoftware.kryo.io.Input; -import com.esotericsoftware.kryo.io.Output; - /** * @author Sindre Mehus */ @@ -65,10 +67,10 @@ public class FileUtil { private static final String[] FILE_SYSTEM_UNSAFE = {"/", "\\", "..", ":", "\"", "?", "*", "<", ">", "|"}; private static final String[] FILE_SYSTEM_UNSAFE_DIR = {"\\", "..", ":", "\"", "?", "*", "<", ">", "|"}; private static final List MUSIC_FILE_EXTENSIONS = Arrays.asList("mp3", "ogg", "aac", "flac", "m4a", "wav", "wma"); - private static final List PLAYLIST_FILE_EXTENSIONS = Arrays.asList("m3u"); + private static final List PLAYLIST_FILE_EXTENSIONS = Collections.singletonList("m3u"); private static final int MAX_FILENAME_LENGTH = 254 - ".complete.mp3".length(); - private static File DEFAULT_MUSIC_DIR; private static final Kryo kryo = new Kryo(); + private static File DEFAULT_MUSIC_DIR; private static HashMap entryLookup; static { @@ -80,27 +82,8 @@ public class FileUtil { kryo.register(Genre.class); } - public static File getAnySong(Context context) { - File dir = getMusicDirectory(context); - return getAnySong(context, dir); - } - private static File getAnySong(Context context, File dir) { - for(File file: dir.listFiles()) { - if(file.isDirectory()) { - return getAnySong(context, file); - } - - String extension = getExtension(file.getName()); - if(MUSIC_FILE_EXTENSIONS.contains(extension)) { - return file; - } - } - - return null; - } - public static File getEntryFile(Context context, MusicDirectory.Entry entry) { - if(entry.isDirectory()) { + if (entry.isDirectory()) { return getAlbumDirectory(context, entry); } else { return getSongFile(context, entry); @@ -120,7 +103,7 @@ public class FileUtil { } fileName.append(fileSystemSafe(song.getTitle())); - if(fileName.length() >= MAX_FILENAME_LENGTH) { + if (fileName.length() >= MAX_FILENAME_LENGTH) { fileName.setLength(MAX_FILENAME_LENGTH); } @@ -138,6 +121,7 @@ public class FileUtil { File playlistDir = getPlaylistDirectory(context, server); return new File(playlistDir, fileSystemSafe(name) + ".m3u"); } + public static void writePlaylistFile(Context context, File file, MusicDirectory playlist) throws IOException { FileWriter fw = new FileWriter(file); BufferedWriter bw = new BufferedWriter(fw); @@ -145,25 +129,27 @@ public class FileUtil { fw.write("#EXTM3U\n"); for (MusicDirectory.Entry e : playlist.getChildren()) { String filePath = FileUtil.getSongFile(context, e).getAbsolutePath(); - if(! new File(filePath).exists()){ + if (!new File(filePath).exists()) { String ext = FileUtil.getExtension(filePath); String base = FileUtil.getBaseName(filePath); filePath = base + ".complete." + ext; } fw.write(filePath + "\n"); } - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to save playlist: " + playlist.getName()); } finally { bw.close(); fw.close(); } } + public static File getPlaylistDirectory(Context context) { File playlistDir = new File(getSubsonicDirectory(context), "playlists"); ensureDirectoryExistsAndIsReadWritable(playlistDir); return playlistDir; } + public static File getPlaylistDirectory(Context context, String server) { File playlistDir = new File(getPlaylistDirectory(context), server); ensureDirectoryExistsAndIsReadWritable(playlistDir); @@ -171,9 +157,9 @@ public class FileUtil { } public static File getAlbumArtFile(Context context, MusicDirectory.Entry entry) { - if(entry.getId().indexOf(ImageLoader.PLAYLIST_PREFIX) != -1) { + if (entry.getId().contains(ImageLoader.PLAYLIST_PREFIX)) { File dir = getAlbumArtDirectory(context); - return new File(dir, Util.md5Hex(ImageLoader.PLAYLIST_PREFIX + entry.getTitle()) + ".jpeg"); + return new File(dir, Util.md5Hex(ImageLoader.PLAYLIST_PREFIX + entry.getTitle()) + ".jpeg"); } else { File albumDir = getAlbumDirectory(context, entry); File artFile; @@ -191,10 +177,11 @@ public class FileUtil { } } - public static File getAlbumArtFile(File albumDir) { + private static File getAlbumArtFile(File albumDir) { return new File(albumDir, Constants.ALBUM_ART_FILE); } - public static File getHexAlbumArtFile(Context context, File albumDir) { + + private static File getHexAlbumArtFile(Context context, File albumDir) { return new File(getAlbumArtDirectory(context), Util.md5Hex(albumDir.getPath()) + ".jpeg"); } @@ -214,25 +201,7 @@ public class FileUtil { return null; } - public static File getMiscDirectory(Context context) { - File dir = new File(getSubsonicDirectory(context), "misc"); - ensureDirectoryExistsAndIsReadWritable(dir); - ensureDirectoryExistsAndIsReadWritable(new File(dir, ".nomedia")); - return dir; - } - - public static File getMiscFile(Context context, String url) { - return new File(getMiscDirectory(context), Util.md5Hex(url) + ".jpeg"); - } - - public static Bitmap getMiscBitmap(Context context, String url, int size) { - return null; - } - public static Bitmap getSampledBitmap(byte[] bytes, int size) { - return getSampledBitmap(bytes, size, true); - } - public static Bitmap getSampledBitmap(byte[] bytes, int size, boolean allowUnscaled) { final BitmapFactory.Options opt = new BitmapFactory.Options(); opt.inJustDecodeBounds = true; BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opt); @@ -240,19 +209,17 @@ public class FileUtil { opt.inSampleSize = Util.calculateInSampleSize(opt, size, Util.getScaledHeight(opt.outHeight, opt.outWidth, size)); opt.inJustDecodeBounds = false; Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opt); - if(bitmap == null) { + if (bitmap == null) { return null; } else { - return getScaledBitmap(bitmap, size, allowUnscaled); + return getScaledBitmap(bitmap, size); } } - public static Bitmap getScaledBitmap(Bitmap bitmap, int size) { - return getScaledBitmap(bitmap, size, true); - } - public static Bitmap getScaledBitmap(Bitmap bitmap, int size, boolean allowUnscaled) { + + private static Bitmap getScaledBitmap(Bitmap bitmap, int size) { // Don't waste time scaling if the difference is minor // Large album arts still need to be scaled since displayed as is on now playing! - if(allowUnscaled && size < 400 && bitmap.getWidth() < (size * 1.1)) { + if (size < 400 && bitmap.getWidth() < (size * 1.1)) { return bitmap; } else { return Bitmap.createScaledBitmap(bitmap, size, Util.getScaledHeight(bitmap, size), true); @@ -267,12 +234,11 @@ public class FileUtil { } public static File getArtistDirectory(Context context, Artist artist) { - File dir = new File(getMusicDirectory(context).getPath() + "/" + fileSystemSafe(artist.getName())); - return dir; + return new File(getMusicDirectory(context).getPath() + "/" + fileSystemSafe(artist.getName())); } + public static File getArtistDirectory(Context context, MusicDirectory.Entry artist) { - File dir = new File(getMusicDirectory(context).getPath() + "/" + fileSystemSafe(artist.getTitle())); - return dir; + return new File(getMusicDirectory(context).getPath() + "/" + fileSystemSafe(artist.getTitle())); } public static File getAlbumDirectory(Context context, MusicDirectory.Entry entry) { @@ -280,26 +246,26 @@ public class FileUtil { if (entry.getPath() != null) { File f = new File(fileSystemSafeDir(entry.getPath())); String folder = getMusicDirectory(context).getPath(); - if(entry.isDirectory()) { + if (entry.isDirectory()) { folder += "/" + f.getPath(); - } else if(f.getParent() != null) { + } else if (f.getParent() != null) { folder += "/" + f.getParent(); } dir = new File(folder); } else { MusicDirectory.Entry firstSong; - if(!Util.isOffline(context)) { + if (!Util.isOffline(context)) { firstSong = lookupChild(context, entry, false); - if(firstSong != null) { + if (firstSong != null) { File songFile = FileUtil.getSongFile(context, firstSong); dir = songFile.getParentFile(); } } - if(dir == null) { + if (dir == null) { String artist = fileSystemSafe(entry.getArtist()); String album = fileSystemSafe(entry.getAlbum()); - if("unnamed".equals(album)) { + if ("unnamed".equals(album)) { album = fileSystemSafe(entry.getTitle()); } dir = new File(getMusicDirectory(context).getPath() + "/" + artist + "/" + album); @@ -310,30 +276,30 @@ public class FileUtil { public static MusicDirectory.Entry lookupChild(Context context, MusicDirectory.Entry entry, boolean allowDir) { // Initialize lookupMap if first time called - String lookupName = Util.getCacheName(context, "entryLookup"); - if(entryLookup == null) { + String lookupName = Util.getCacheName(context); + if (entryLookup == null) { entryLookup = deserialize(context, lookupName, HashMap.class); // Create it if - if(entryLookup == null) { - entryLookup = new HashMap(); + if (entryLookup == null) { + entryLookup = new HashMap<>(); } } // Check if this lookup has already been done before MusicDirectory.Entry child = entryLookup.get(entry.getId()); - if(child != null) { + if (child != null) { return child; } // Do a special lookup since 4.7+ doesn't match artist/album to entry.getPath String s = Util.getRestUrl(context, null, false) + entry.getId(); - String cacheName = (Util.isTagBrowsing(context) ? "album-" : "directory-") + s.hashCode() + ".ser"; + String cacheName = "album-" + s.hashCode() + ".ser"; MusicDirectory entryDir = FileUtil.deserialize(context, cacheName, MusicDirectory.class); - if(entryDir != null) { + if (entryDir != null) { List songs = entryDir.getChildren(allowDir, true); - if(songs.size() > 0) { + if (songs.size() > 0) { child = songs.get(0); entryLookup.put(entry.getId(), child); serialize(context, entryLookup, lookupName); @@ -353,22 +319,14 @@ public class FileUtil { } } - private static File createDirectory(Context context, String name) { - File dir = new File(getSubsonicDirectory(context), name); - if (!dir.exists() && !dir.mkdirs()) { - Log.e(TAG, "Failed to create " + name); - } - return dir; - } - public static File getSubsonicDirectory(Context context) { return context.getExternalFilesDir(null); } public static File getDefaultMusicDirectory(Context context) { - if(DEFAULT_MUSIC_DIR == null) { + if (DEFAULT_MUSIC_DIR == null) { File[] dirs; - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { dirs = context.getExternalMediaDirs(); } else { dirs = ContextCompat.getExternalFilesDirs(context, null); @@ -380,7 +338,7 @@ public class FileUtil { Log.e(TAG, "Failed to create default dir " + DEFAULT_MUSIC_DIR); // Some devices seem to have screwed up the new media directory API. Go figure. Try again with standard locations - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { dirs = ContextCompat.getExternalFilesDirs(context, null); DEFAULT_MUSIC_DIR = new File(getBestDir(dirs), "music"); @@ -395,13 +353,14 @@ public class FileUtil { return DEFAULT_MUSIC_DIR; } + private static File getBestDir(File[] dirs) { // Past 5.0 we can query directly for SD Card - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - for(int i = 0; i < dirs.length; i++) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + for (File dir : dirs) { try { - if (dirs[i] != null && Environment.isExternalStorageRemovable(dirs[i])) { - return dirs[i]; + if (dir != null && Environment.isExternalStorageRemovable(dir)) { + return dir; } } catch (Exception e) { Log.e(TAG, "Failed to check if is external", e); @@ -410,8 +369,8 @@ public class FileUtil { } // Before 5.0, we have to guess. Most of the time the SD card is last - for(int i = dirs.length - 1; i >= 0; i--) { - if(dirs[i] != null) { + for (int i = dirs.length - 1; i >= 0; i--) { + if (dirs[i] != null) { return dirs[i]; } } @@ -425,38 +384,43 @@ public class FileUtil { File dir = new File(path); return ensureDirectoryExistsAndIsReadWritable(dir) ? dir : getDefaultMusicDirectory(context); } - public static boolean deleteMusicDirectory(Context context) { + + public static void deleteMusicDirectory(Context context) { File musicDirectory = FileUtil.getMusicDirectory(context); MediaStoreService mediaStore = new MediaStoreService(context); - return recursiveDelete(musicDirectory, mediaStore); + recursiveDelete(musicDirectory, mediaStore); } + public static void deleteSerializedCache(Context context) { - for(File file: context.getCacheDir().listFiles()) { - if(file.getName().indexOf(".ser") != -1) { + for (File file : context.getCacheDir().listFiles()) { + if (file.getName().contains(".ser")) { file.delete(); } } } - public static boolean deleteArtworkCache(Context context) { + + public static void deleteArtworkCache(Context context) { File artDirectory = FileUtil.getAlbumArtDirectory(context); - return recursiveDelete(artDirectory); + recursiveDelete(artDirectory); } - public static boolean recursiveDelete(File dir) { - return recursiveDelete(dir, null); + + private static void recursiveDelete(File dir) { + recursiveDelete(dir, null); } + public static boolean recursiveDelete(File dir, MediaStoreService mediaStore) { if (dir != null && dir.exists()) { File[] list = dir.listFiles(); - if(list != null) { - for(File file: list) { - if(file.isDirectory()) { - if(!recursiveDelete(file, mediaStore)) { + if (list != null) { + for (File file : list) { + if (file.isDirectory()) { + if (!recursiveDelete(file, mediaStore)) { return false; } - } else if(file.exists()) { - if(!file.delete()) { + } else if (file.exists()) { + if (!file.delete()) { return false; - } else if(mediaStore != null) { + } else if (mediaStore != null) { mediaStore.deleteFromMediaStore(file); } } @@ -470,7 +434,7 @@ public class FileUtil { public static void deleteEmptyDir(File dir) { try { File[] children = dir.listFiles(); - if(children == null) { + if (children == null) { return; } @@ -484,33 +448,12 @@ public class FileUtil { if (children.length == 0) { Util.delete(dir); } - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Error while trying to delete empty dir", e); } } - public static void unpinSong(Context context, File saveFile) { - // Don't try to unpin a song which isn't actually pinned - if(saveFile.getName().contains(".complete")) { - return; - } - - // Unpin file, rename to .complete - File completeFile = new File(saveFile.getParent(), FileUtil.getBaseName(saveFile.getName()) + - ".complete." + FileUtil.getExtension(saveFile.getName())); - - if(!saveFile.renameTo(completeFile)) { - Log.w(TAG, "Failed to upin " + saveFile + " to " + completeFile); - } else { - try { - new MediaStoreService(context).renameInMediaStore(completeFile, saveFile); - } catch(Exception e) { - Log.w(TAG, "Failed to write to media store"); - } - } - } - - public static boolean ensureDirectoryExistsAndIsReadWritable(File dir) { + private static boolean ensureDirectoryExistsAndIsReadWritable(File dir) { if (dir == null) { return false; } @@ -540,13 +483,14 @@ public class FileUtil { } return true; } + public static boolean verifyCanWrite(File dir) { - if(ensureDirectoryExistsAndIsReadWritable(dir)) { + if (ensureDirectoryExistsAndIsReadWritable(dir)) { try { File tmp = new File(dir, "checkWrite"); tmp.createNewFile(); - if(tmp.exists()) { - if(tmp.delete()) { + if (tmp.exists()) { + if (tmp.delete()) { return true; } else { Log.w(TAG, "Failed to delete temp file, retrying"); @@ -554,7 +498,7 @@ public class FileUtil { // This should never be reached since this is a file Audinaut created! Thread.sleep(100L); tmp = new File(dir, "checkWrite"); - if(tmp.delete()) { + if (tmp.delete()) { return true; } else { Log.w(TAG, "Failed retry to delete temp file"); @@ -565,7 +509,7 @@ public class FileUtil { Log.w(TAG, "Temp file does not actually exist"); return false; } - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to create tmp file", e); return false; } @@ -575,12 +519,12 @@ public class FileUtil { } /** - * Makes a given filename safe by replacing special characters like slashes ("/" and "\") - * with dashes ("-"). - * - * @param filename The filename in question. - * @return The filename with special characters replaced by hyphens. - */ + * Makes a given filename safe by replacing special characters like slashes ("/" and "\") + * with dashes ("-"). + * + * @param filename The filename in question. + * @return The filename with special characters replaced by hyphens. + */ private static String fileSystemSafe(String filename) { if (filename == null || filename.trim().length() == 0) { return "unnamed"; @@ -618,10 +562,10 @@ public class FileUtil { File[] files = dir.listFiles(); if (files == null) { Log.w(TAG, "Failed to list children for " + dir.getPath()); - return new TreeSet(); + return new TreeSet<>(); } - return new TreeSet(Arrays.asList(files)); + return new TreeSet<>(Arrays.asList(files)); } public static SortedSet listMediaFiles(File dir) { @@ -641,11 +585,6 @@ public class FileUtil { return MUSIC_FILE_EXTENSIONS.contains(extension); } - public static boolean isMusicFile(File file) { - String extension = getExtension(file.getName()); - return MUSIC_FILE_EXTENSIONS.contains(extension); - } - public static boolean isPlaylistFile(File file) { String extension = getExtension(file.getName()); return PLAYLIST_FILE_EXTENSIONS.contains(extension); @@ -675,32 +614,7 @@ public class FileUtil { return index == -1 ? name : name.substring(0, index); } - public static Long[] getUsedSize(Context context, File file) { - long number = 0L; - long permanent = 0L; - long size = 0L; - - if(file.isFile()) { - if(isMediaFile(file)) { - if(file.getAbsolutePath().indexOf(".complete") == -1) { - permanent++; - } - return new Long[] {1L, permanent, file.length()}; - } else { - return new Long[] {0L, 0L, 0L}; - } - } else { - for (File child : FileUtil.listFiles(file)) { - Long[] pair = getUsedSize(context, child); - number += pair[0]; - permanent += pair[1]; - size += pair[2]; - } - return new Long[] {number, permanent, size}; - } - } - - public static boolean serialize(Context context, T obj, String fileName) { + public static void serialize(Context context, T obj, String fileName) { Output out = null; try { RandomAccessFile file = new RandomAccessFile(context.getCacheDir() + "/" + fileName, "rw"); @@ -708,32 +622,26 @@ public class FileUtil { synchronized (kryo) { kryo.writeObject(out, obj); } - return true; } catch (Throwable x) { Log.w(TAG, "Failed to serialize object to " + fileName); - return false; } finally { Util.close(out); } } public static T deserialize(Context context, String fileName, Class tClass) { - return deserialize(context, fileName, tClass, 0); - } - - public static T deserialize(Context context, String fileName, Class tClass, int hoursOld) { Input in = null; try { File file = new File(context.getCacheDir(), fileName); - if(!file.exists()) { + if (!file.exists()) { return null; } - if(hoursOld != 0) { + if (0 != 0) { Date fileDate = new Date(file.lastModified()); // Convert into hours long age = (new Date().getTime() - fileDate.getTime()) / 1000 / 3600; - if(age > hoursOld) { + if (age > 0) { return null; } } @@ -742,10 +650,9 @@ public class FileUtil { in = new Input(new FileInputStream(randomFile.getFD())); synchronized (kryo) { - T result = kryo.readObject(in, tClass); - return result; + return kryo.readObject(in, tClass); } - } catch(FileNotFoundException e) { + } catch (FileNotFoundException e) { // Different error message Log.w(TAG, "No serialization for object from " + fileName); return null; @@ -757,7 +664,7 @@ public class FileUtil { } } - public static boolean serializeCompressed(Context context, T obj, String fileName) { + public static void serializeCompressed(Context context, T obj, String fileName) { Output out = null; try { RandomAccessFile file = new RandomAccessFile(context.getCacheDir() + "/" + fileName, "rw"); @@ -765,10 +672,8 @@ public class FileUtil { synchronized (kryo) { kryo.writeObject(out, obj); } - return true; } catch (Throwable x) { Log.w(TAG, "Failed to serialize compressed object to " + fileName); - return false; } finally { Util.close(out); } @@ -781,10 +686,9 @@ public class FileUtil { in = new Input(new InflaterInputStream(new FileInputStream(file.getFD()))); synchronized (kryo) { - T result = kryo.readObject(in, tClass); - return result; + return kryo.readObject(in, tClass); } - } catch(FileNotFoundException e) { + } catch (FileNotFoundException e) { // Different error message Log.w(TAG, "No serialization compressed for object from " + fileName); return null; diff --git a/app/src/main/java/net/nullsum/audinaut/util/ImageLoader.java b/app/src/main/java/net/nullsum/audinaut/util/ImageLoader.java index 35dae3c..85b446b 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/ImageLoader.java +++ b/app/src/main/java/net/nullsum/audinaut/util/ImageLoader.java @@ -28,18 +28,15 @@ import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.TransitionDrawable; -import android.os.Build; import android.os.Handler; import android.os.Looper; +import android.support.v4.util.LruCache; import android.util.DisplayMetrics; import android.util.Log; -import android.support.v4.util.LruCache; import android.view.View; import android.widget.ImageView; import android.widget.TextView; -import java.lang.ref.WeakReference; - import net.nullsum.audinaut.R; import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.domain.Playlist; @@ -54,20 +51,18 @@ import net.nullsum.audinaut.service.MusicServiceFactory; * @author Sindre Mehus */ public class ImageLoader { - private static final String TAG = ImageLoader.class.getSimpleName(); public static final String PLAYLIST_PREFIX = "pl-"; - - private Context context; - private LruCache cache; - private Handler handler; - private Bitmap nowPlaying; - private Bitmap nowPlayingSmall; + private static final String TAG = ImageLoader.class.getSimpleName(); + private final static int[] COLORS = {0xFF33B5E5, 0xFFAA66CC, 0xFF99CC00, 0xFFFFBB33, 0xFFFF4444}; private final int imageSizeDefault; private final int imageSizeLarge; - private boolean clearingCache = false; private final int cacheSize; - - private final static int[] COLORS = {0xFF33B5E5, 0xFFAA66CC, 0xFF99CC00, 0xFFFFBB33, 0xFFFF4444}; + private final Context context; + private final Handler handler; + private LruCache cache; + private Bitmap nowPlaying; + private Bitmap nowPlayingSmall; + private boolean clearingCache = false; public ImageLoader(Context context) { this.context = context; @@ -88,10 +83,10 @@ public class ImageLoader { @Override protected void entryRemoved(boolean evicted, String key, Bitmap oldBitmap, Bitmap newBitmap) { - if(evicted) { - if((oldBitmap != nowPlaying && oldBitmap != nowPlayingSmall) || clearingCache) { + if (evicted) { + if ((oldBitmap != nowPlaying && oldBitmap != nowPlayingSmall) || clearingCache) { oldBitmap.recycle(); - } else if(oldBitmap != newBitmap) { + } else if (oldBitmap != newBitmap) { cache.put(key, oldBitmap); } } @@ -112,12 +107,14 @@ public class ImageLoader { } }.execute(); } + public void onLowMemory(float percent) { Log.i(TAG, "Cache size: " + cache.size() + " => " + Math.round(cacheSize * (1 - percent)) + " out of " + cache.maxSize()); cache.resize(Math.round(cacheSize * (1 - percent))); } + public void onUIVisible() { - if(cache.maxSize() != cacheSize) { + if (cache.maxSize() != cacheSize) { Log.i(TAG, "Returned to full cache size"); cache.resize(cacheSize); } @@ -130,7 +127,7 @@ public class ImageLoader { private Bitmap getUnknownImage(MusicDirectory.Entry entry, int size) { String key; int color; - if(entry == null) { + if (entry == null) { key = getKey("unknown", size); color = COLORS[0]; @@ -138,9 +135,9 @@ public class ImageLoader { } else { key = getKey(entry.getId() + "unknown", size); String hash; - if(entry.getAlbum() != null) { + if (entry.getAlbum() != null) { hash = entry.getAlbum(); - } else if(entry.getArtist() != null) { + } else if (entry.getArtist() != null) { hash = entry.getArtist(); } else { hash = entry.getId(); @@ -150,15 +147,17 @@ public class ImageLoader { return getUnknownImage(key, size, color, entry.getAlbum(), entry.getArtist()); } } + private Bitmap getUnknownImage(String key, int size, int color, String topText, String bottomText) { Bitmap bitmap = cache.get(key); - if(bitmap == null) { + if (bitmap == null) { bitmap = createUnknownImage(size, color, topText, bottomText); cache.put(key, bitmap); } return bitmap; } + private Bitmap createUnknownImage(int size, int primaryColor, String topText, String bottomText) { Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); @@ -170,17 +169,17 @@ public class ImageLoader { color.setShader(new LinearGradient(0, 0, 0, size / 3.0f, Color.rgb(82, 82, 82), Color.BLACK, Shader.TileMode.MIRROR)); canvas.drawRect(0, size * 2.0f / 3.0f, size, size, color); - if(topText != null || bottomText != null) { + if (topText != null || bottomText != null) { Paint font = new Paint(); font.setFlags(Paint.ANTI_ALIAS_FLAG); font.setColor(Color.WHITE); font.setTextSize(3.0f + size * 0.07f); - if(topText != null) { + if (topText != null) { canvas.drawText(topText, size * 0.05f, size * 0.6f, font); } - if(bottomText != null) { + if (bottomText != null) { canvas.drawText(bottomText, size * 0.05f, size * 0.8f, font); } } @@ -190,19 +189,19 @@ public class ImageLoader { public Bitmap getCachedImage(Context context, MusicDirectory.Entry entry, boolean large) { int size = large ? imageSizeLarge : imageSizeDefault; - if(entry == null || entry.getCoverArt() == null) { + if (entry == null || entry.getCoverArt() == null) { return getUnknownImage(entry, size); } Bitmap bitmap = cache.get(getKey(entry.getCoverArt(), size)); - if(bitmap == null || bitmap.isRecycled()) { + if (bitmap == null || bitmap.isRecycled()) { bitmap = FileUtil.getAlbumArtBitmap(context, entry, size); String key = getKey(entry.getCoverArt(), size); cache.put(key, bitmap); cache.get(key); } - if(bitmap != null && bitmap.isRecycled()) { + if (bitmap != null && bitmap.isRecycled()) { bitmap = null; } return bitmap; @@ -212,16 +211,17 @@ public class ImageLoader { int size = large ? imageSizeLarge : imageSizeDefault; return loadImage(view, entry, large, size, crossfade); } + public SilentBackgroundTask loadImage(View view, MusicDirectory.Entry entry, boolean large, int size, boolean crossfade) { // If we know this a artist, try to load artist info instead - if(entry != null && !entry.isAlbum() && !Util.isOffline(context)) { - SilentBackgroundTask task = new ArtistImageTask(view.getContext(), entry, size, imageSizeLarge, large, view, crossfade); + if (entry != null && !entry.isAlbum() && !Util.isOffline(context)) { + SilentBackgroundTask task = new ArtistImageTask(view.getContext(), entry, size, large, view, crossfade); task.execute(); return task; - } else if(entry != null && entry.getCoverArt() == null && entry.isDirectory() && !Util.isOffline(context)) { + } else if (entry != null && entry.getCoverArt() == null && entry.isDirectory() && !Util.isOffline(context)) { // Try to lookup child cover art MusicDirectory.Entry firstChild = FileUtil.lookupChild(context, entry, true); - if(firstChild != null) { + if (firstChild != null) { entry.setCoverArt(firstChild.getCoverArt()); } } @@ -237,7 +237,7 @@ public class ImageLoader { if (bitmap != null && !bitmap.isRecycled()) { final Drawable drawable = Util.createDrawableFromBitmap(this.context, bitmap); setImage(view, drawable, crossfade); - if(large) { + if (large) { nowPlaying = bitmap; } return null; @@ -246,39 +246,15 @@ public class ImageLoader { if (!large) { setImage(view, null, false); } - ImageTask task = new ViewImageTask(view.getContext(), entry, size, imageSizeLarge, large, view, crossfade); + ImageTask task = new ViewImageTask(view.getContext(), entry, size, large, view, crossfade); task.execute(); return task; } - public SilentBackgroundTask loadImage(View view, String url, boolean large) { - Bitmap bitmap; - int size = large ? imageSizeLarge : imageSizeDefault; - if (url == null) { - String key = getKey(url + "unknown", size); - int color = COLORS[Math.abs(key.hashCode()) % COLORS.length]; - bitmap = getUnknownImage(key, size, color, null, null); - setImage(view, Util.createDrawableFromBitmap(context, bitmap), true); - return null; - } - - bitmap = cache.get(getKey(url, size)); - if (bitmap != null && !bitmap.isRecycled()) { - final Drawable drawable = Util.createDrawableFromBitmap(this.context, bitmap); - setImage(view, drawable, true); - return null; - } - setImage(view, null, false); - - SilentBackgroundTask task = new ViewUrlTask(view.getContext(), view, url, size); - task.execute(); - return task; - } - - public SilentBackgroundTask loadImage(View view, Playlist playlist, boolean large, boolean crossfade) { + public SilentBackgroundTask loadImage(View view, Playlist playlist) { MusicDirectory.Entry entry = new MusicDirectory.Entry(); String id; - if(Util.isOffline(context)) { + if (Util.isOffline(context)) { id = PLAYLIST_PREFIX + playlist.getName(); entry.setTitle(playlist.getComment()); } else { @@ -290,7 +266,7 @@ public class ImageLoader { // So this isn't treated as a artist entry.setParent(""); - return loadImage(view, entry, large, crossfade); + return loadImage(view, entry, false, true); } private String getKey(String coverArtId, int size) { @@ -308,31 +284,28 @@ public class ImageLoader { Drawable existingDrawable = imageView.getDrawable(); if (existingDrawable == null) { Bitmap emptyImage; - if(drawable.getIntrinsicWidth() > 0 && drawable.getIntrinsicHeight() > 0) { + if (drawable.getIntrinsicWidth() > 0 && drawable.getIntrinsicHeight() > 0) { emptyImage = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); } else { emptyImage = Bitmap.createBitmap(imageSizeDefault, imageSizeDefault, Bitmap.Config.ARGB_8888); } existingDrawable = new BitmapDrawable(context.getResources(), emptyImage); - } else if(existingDrawable instanceof TransitionDrawable) { + } else if (existingDrawable instanceof TransitionDrawable) { // This should only ever be used if user is skipping through many songs quickly TransitionDrawable tmp = (TransitionDrawable) existingDrawable; existingDrawable = tmp.getDrawable(tmp.getNumberOfLayers() - 1); } - if(existingDrawable != null && drawable != null) { + if (existingDrawable != null && drawable != null) { Drawable[] layers = new Drawable[]{existingDrawable, drawable}; final TransitionDrawable transitionDrawable = new TransitionDrawable(layers); imageView.setImageDrawable(transitionDrawable); transitionDrawable.startTransition(250); // Get rid of transition drawable after transition occurs - handler.postDelayed(new Runnable() { - @Override - public void run() { - // Only execute if still on same transition drawable - if (imageView.getDrawable() == transitionDrawable) { - imageView.setImageDrawable(drawable); - } + handler.postDelayed(() -> { + // Only execute if still on same transition drawable + if (imageView.getDrawable() == transitionDrawable) { + imageView.setImageDrawable(drawable); } }, 500L); } else { @@ -345,19 +318,17 @@ public class ImageLoader { } public abstract class ImageTask extends SilentBackgroundTask { + final MusicDirectory.Entry mEntry; private final Context mContext; - protected final MusicDirectory.Entry mEntry; private final int mSize; - private final int mSaveSize; private final boolean mIsNowPlaying; - protected Drawable mDrawable; + Drawable mDrawable; - public ImageTask(Context context, MusicDirectory.Entry entry, int size, int saveSize, boolean isNowPlaying) { + public ImageTask(Context context, MusicDirectory.Entry entry, int size, boolean isNowPlaying) { super(context); mContext = context; mEntry = entry; mSize = size; - mSaveSize = saveSize; mIsNowPlaying = isNowPlaying; } @@ -366,7 +337,7 @@ public class ImageLoader { try { MusicService musicService = MusicServiceFactory.getMusicService(mContext); Bitmap bitmap = musicService.getCoverArt(mContext, mEntry, mSize, null, this); - if(bitmap != null) { + if (bitmap != null) { String key = getKey(mEntry.getCoverArt(), mSize); cache.put(key, bitmap); // Make sure key is the most recently "used" @@ -389,11 +360,11 @@ public class ImageLoader { } private class ViewImageTask extends ImageTask { - protected boolean mCrossfade; - private View mView; + final boolean mCrossfade; + private final View mView; - public ViewImageTask(Context context, MusicDirectory.Entry entry, int size, int saveSize, boolean isNowPlaying, View view, boolean crossfade) { - super(context, entry, size, saveSize, isNowPlaying); + public ViewImageTask(Context context, MusicDirectory.Entry entry, int size, boolean isNowPlaying, View view, boolean crossfade) { + super(context, entry, size, isNowPlaying); mView = view; mCrossfade = crossfade; @@ -409,20 +380,17 @@ public class ImageLoader { private final Context mContext; private final MusicDirectory.Entry mEntry; private final int mSize; - private final int mSaveSize; private final boolean mIsNowPlaying; + private final boolean mCrossfade; + private final View mView; private Drawable mDrawable; - private boolean mCrossfade; - private View mView; - private SilentBackgroundTask subTask; - public ArtistImageTask(Context context, MusicDirectory.Entry entry, int size, int saveSize, boolean isNowPlaying, View view, boolean crossfade) { + public ArtistImageTask(Context context, MusicDirectory.Entry entry, int size, boolean isNowPlaying, View view, boolean crossfade) { super(context); mContext = context; mEntry = entry; mSize = size; - mSaveSize = saveSize; mIsNowPlaying = isNowPlaying; mView = view; mCrossfade = crossfade; @@ -431,8 +399,6 @@ public class ImageLoader { @Override protected Void doInBackground() throws Throwable { try { - MusicService musicService = MusicServiceFactory.getMusicService(mContext); - // Figure out whether we are going to get a artist image or the standard image if (mEntry != null && mEntry.getCoverArt() == null && mEntry.isDirectory() && !Util.isOffline(context)) { // Try to lookup child cover art @@ -443,7 +409,7 @@ public class ImageLoader { } if (mEntry != null && mEntry.getCoverArt() != null) { - subTask = new ViewImageTask(mContext, mEntry, mSize, mSaveSize, mIsNowPlaying, mView, mCrossfade); + subTask = new ViewImageTask(mContext, mEntry, mSize, mIsNowPlaying, mView, mCrossfade); } else { // If entry is null as well, we need to just set as a blank image Bitmap bitmap = getUnknownImage(mEntry, mSize); @@ -462,61 +428,11 @@ public class ImageLoader { @Override public void done(Void result) { - if(subTask != null) { + if (subTask != null) { subTask.done(result); - } else if(mDrawable != null) { + } else if (mDrawable != null) { setImage(mView, mDrawable, mCrossfade); } } } - - private class ViewUrlTask extends SilentBackgroundTask { - private final Context mContext; - private final String mUrl; - private final ImageView mView; - private Drawable mDrawable; - private int mSize; - - public ViewUrlTask(Context context, View view, String url, int size) { - super(context); - mContext = context; - mView = (ImageView) view; - mUrl = url; - mSize = size; - } - - @Override - protected Void doInBackground() throws Throwable { - try { - MusicService musicService = MusicServiceFactory.getMusicService(mContext); - Bitmap bitmap = musicService.getBitmap(mUrl, mSize, mContext, null, this); - if(bitmap != null) { - String key = getKey(mUrl, mSize); - cache.put(key, bitmap); - // Make sure key is the most recently "used" - cache.get(key); - - mDrawable = Util.createDrawableFromBitmap(mContext, bitmap); - } - } catch (Throwable x) { - Log.e(TAG, "Failed to download from url " + mUrl, x); - cancelled.set(true); - } - - return null; - } - - @Override - protected void done(Void result) { - if(mDrawable != null) { - mView.setImageDrawable(mDrawable); - } else { - failedToDownload(); - } - } - - protected void failedToDownload() { - - } - } } diff --git a/app/src/main/java/net/nullsum/audinaut/util/LoadingTask.java b/app/src/main/java/net/nullsum/audinaut/util/LoadingTask.java index 5d34a62..1337081 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/LoadingTask.java +++ b/app/src/main/java/net/nullsum/audinaut/util/LoadingTask.java @@ -2,7 +2,6 @@ package net.nullsum.audinaut.util; import android.app.Activity; import android.app.ProgressDialog; -import android.content.DialogInterface; import net.nullsum.audinaut.activity.SubsonicActivity; @@ -13,14 +12,15 @@ import net.nullsum.audinaut.activity.SubsonicActivity; public abstract class LoadingTask extends BackgroundTask { private final Activity tabActivity; - private ProgressDialog loading; private final boolean cancellable; + private ProgressDialog loading; public LoadingTask(Activity activity) { super(activity); tabActivity = activity; this.cancellable = true; } + public LoadingTask(Activity activity, final boolean cancellable) { super(activity); tabActivity = activity; @@ -29,16 +29,12 @@ public abstract class LoadingTask extends BackgroundTask { @Override public void execute() { - loading = ProgressDialog.show(tabActivity, "", "Loading. Please Wait...", true, cancellable, new DialogInterface.OnCancelListener() { - public void onCancel(DialogInterface dialog) { - cancel(); - } - }); + loading = ProgressDialog.show(tabActivity, "", "Loading. Please Wait...", true, cancellable, dialog -> cancel()); queue.offer(task = new Task() { @Override public void onDone(T result) { - if(loading.isShowing()) { + if (loading.isShowing()) { loading.dismiss(); } done(result); @@ -46,7 +42,7 @@ public abstract class LoadingTask extends BackgroundTask { @Override public void onError(Throwable t) { - if(loading.isShowing()) { + if (loading.isShowing()) { loading.dismiss(); } error(t); @@ -61,13 +57,8 @@ public abstract class LoadingTask extends BackgroundTask { @Override public void updateProgress(final String message) { - if(!cancelled.get()) { - getHandler().post(new Runnable() { - @Override - public void run() { - loading.setMessage(message); - } - }); + if (!cancelled.get()) { + getHandler().post(() -> loading.setMessage(message)); } } } diff --git a/app/src/main/java/net/nullsum/audinaut/util/MenuUtil.java b/app/src/main/java/net/nullsum/audinaut/util/MenuUtil.java index 2566e23..ed5cf85 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/MenuUtil.java +++ b/app/src/main/java/net/nullsum/audinaut/util/MenuUtil.java @@ -16,12 +16,9 @@ package net.nullsum.audinaut.util; import android.content.Context; -import android.content.SharedPreferences; import android.util.Log; import android.view.Menu; -import java.io.File; - import net.nullsum.audinaut.R; import net.nullsum.audinaut.service.DownloadFile; import net.nullsum.audinaut.view.AlbumView; @@ -30,21 +27,23 @@ import net.nullsum.audinaut.view.ArtistView; import net.nullsum.audinaut.view.SongView; import net.nullsum.audinaut.view.UpdateView; +import java.io.File; + public final class MenuUtil { private final static String TAG = MenuUtil.class.getSimpleName(); public static void hideMenuItems(Context context, Menu menu, UpdateView updateView) { - if(!Util.isOffline(context)) { + if (!Util.isOffline(context)) { // If we are looking at a standard song view, get downloadFile to cache what options to show - if(updateView instanceof SongView) { + if (updateView instanceof SongView) { SongView songView = (SongView) updateView; DownloadFile downloadFile = songView.getDownloadFile(); try { - if(downloadFile != null) { - if(downloadFile.isWorkDone()) { + if (downloadFile != null) { + if (downloadFile.isWorkDone()) { // Remove permanent cache menu if already perma cached - if(downloadFile.isSaved()) { + if (downloadFile.isSaved()) { menu.setGroupVisible(R.id.hide_pin, false); } @@ -55,26 +54,26 @@ public final class MenuUtil { menu.setGroupVisible(R.id.hide_delete, false); } } - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to lookup downloadFile info", e); } } // Apply similar logic to album views - else if(updateView instanceof AlbumView || updateView instanceof ArtistView || updateView instanceof ArtistEntryView) { + else if (updateView instanceof AlbumView || updateView instanceof ArtistView || updateView instanceof ArtistEntryView) { File folder = null; - if(updateView instanceof AlbumView) { + if (updateView instanceof AlbumView) { folder = ((AlbumView) updateView).getFile(); - } else if(updateView instanceof ArtistView) { + } else if (updateView instanceof ArtistView) { folder = ((ArtistView) updateView).getFile(); - } else if(updateView instanceof ArtistEntryView) { + } else if (updateView instanceof ArtistEntryView) { folder = ((ArtistEntryView) updateView).getFile(); } try { - if(folder != null && !folder.exists()) { + if (folder != null && !folder.exists()) { menu.setGroupVisible(R.id.hide_delete, false); } - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Failed to lookup album directory info", e); } } diff --git a/app/src/main/java/net/nullsum/audinaut/util/Notifications.java b/app/src/main/java/net/nullsum/audinaut/util/Notifications.java index 941b452..54e678b 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/Notifications.java +++ b/app/src/main/java/net/nullsum/audinaut/util/Notifications.java @@ -43,14 +43,11 @@ import net.nullsum.audinaut.service.DownloadService; import static android.content.Context.NOTIFICATION_SERVICE; public final class Notifications { + private static final int NOTIFICATION_ID_PLAYING = 100; + private static final int NOTIFICATION_ID_DOWNLOADING = 102; + private static final String CHANNEL_PLAYING_ID = "playback_controls"; + private static final String CHANNEL_DOWNLOADING_ID = "media_download"; private static final String TAG = Notifications.class.getSimpleName(); - - public static final int NOTIFICATION_ID_PLAYING = 100; - public static final int NOTIFICATION_ID_DOWNLOADING = 102; - - public static final String CHANNEL_PLAYING_ID = "playback_controls"; - public static final String CHANNEL_DOWNLOADING_ID = "media_download"; - private static boolean playShowing = false; private static boolean downloadShowing = false; private static boolean downloadForeground = false; @@ -71,7 +68,7 @@ public final class Notifications { final boolean playing = downloadService.getPlayerState() == PlayerState.STARTED; RemoteViews expandedContentView = new RemoteViews(context.getPackageName(), R.layout.notification_expanded); - setupViews(expandedContentView ,context, song, true, playing); + setupViews(expandedContentView, context, song, true, playing); RemoteViews smallContentView = new RemoteViews(context.getPackageName(), R.layout.notification); setupViews(smallContentView, context, song, false, playing); @@ -93,29 +90,23 @@ public final class Notifications { .setPriority(NotificationCompat.PRIORITY_LOW).build(); playShowing = true; - if(downloadForeground && downloadShowing) { + if (downloadForeground && downloadShowing) { downloadForeground = false; - handler.post(new Runnable() { - @Override - public void run() { - downloadService.stopForeground(true); - showDownloadingNotification(context, downloadService, handler, downloadService.getCurrentDownloading(), downloadService.getBackgroundDownloads().size()); - downloadService.startForeground(NOTIFICATION_ID_PLAYING, notification); - } + handler.post(() -> { + downloadService.stopForeground(true); + showDownloadingNotification(context, downloadService, handler, downloadService.getCurrentDownloading(), downloadService.getBackgroundDownloads().size()); + downloadService.startForeground(NOTIFICATION_ID_PLAYING, notification); }); } else { - handler.post(new Runnable() { - @Override - public void run() { - if (playing) { - downloadService.startForeground(NOTIFICATION_ID_PLAYING, notification); - } else { - playShowing = false; - persistentPlayingShowing = true; - NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE); - downloadService.stopForeground(false); - notificationManager.notify(NOTIFICATION_ID_PLAYING, notification); - } + handler.post(() -> { + if (playing) { + downloadService.startForeground(NOTIFICATION_ID_PLAYING, notification); + } else { + playShowing = false; + persistentPlayingShowing = true; + NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE); + downloadService.stopForeground(false); + notificationManager.notify(NOTIFICATION_ID_PLAYING, notification); } }); } @@ -134,7 +125,7 @@ public final class Notifications { try { ImageLoader imageLoader = SubsonicActivity.getStaticImageLoader(context); Bitmap bitmap = null; - if(imageLoader != null) { + if (imageLoader != null) { bitmap = imageLoader.getCachedImage(context, song, false); } if (bitmap == null) { @@ -155,8 +146,8 @@ public final class Notifications { rv.setTextViewText(R.id.notification_album, album); boolean persistent = Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false); - if(persistent) { - if(expanded) { + if (persistent) { + if (expanded) { rv.setImageViewResource(R.id.control_pause, playing ? R.drawable.notification_pause : R.drawable.notification_start); rv.setImageViewResource(R.id.control_previous, R.drawable.notification_backward); @@ -174,8 +165,8 @@ public final class Notifications { // Create actions for media buttons PendingIntent pendingIntent; - int previous = 0, pause = 0, next = 0, close = 0, rewind = 0, fastForward = 0; - if(persistent && !expanded) { + int previous = 0, pause, next, close = 0, rewind = 0, fastForward = 0; + if (persistent && !expanded) { pause = R.id.control_previous; next = R.id.control_pause; close = R.id.control_next; @@ -185,27 +176,27 @@ public final class Notifications { next = R.id.control_next; } - if(persistent && close == 0 && expanded) { + if (persistent && close == 0 && expanded) { close = R.id.notification_close; rv.setViewVisibility(close, View.VISIBLE); } - if(previous > 0) { + if (previous > 0) { Intent prevIntent = new Intent("KEYCODE_MEDIA_PREVIOUS"); prevIntent.setComponent(new ComponentName(context, DownloadService.class)); prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PREVIOUS)); pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0); rv.setOnClickPendingIntent(previous, pendingIntent); } - if(rewind > 0) { + if (rewind > 0) { Intent rewindIntent = new Intent("KEYCODE_MEDIA_REWIND"); rewindIntent.setComponent(new ComponentName(context, DownloadService.class)); rewindIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_REWIND)); pendingIntent = PendingIntent.getService(context, 0, rewindIntent, 0); rv.setOnClickPendingIntent(rewind, pendingIntent); } - if(pause > 0) { - if(playing) { + if (pause > 0) { + if (playing) { Intent pauseIntent = new Intent("KEYCODE_MEDIA_PLAY_PAUSE"); pauseIntent.setComponent(new ComponentName(context, DownloadService.class)); pauseIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)); @@ -219,21 +210,21 @@ public final class Notifications { rv.setOnClickPendingIntent(pause, pendingIntent); } } - if(next > 0) { + if (next > 0) { Intent nextIntent = new Intent("KEYCODE_MEDIA_NEXT"); nextIntent.setComponent(new ComponentName(context, DownloadService.class)); nextIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT)); pendingIntent = PendingIntent.getService(context, 0, nextIntent, 0); rv.setOnClickPendingIntent(next, pendingIntent); } - if(fastForward > 0) { + if (fastForward > 0) { Intent fastForwardIntent = new Intent("KEYCODE_MEDIA_FAST_FORWARD"); fastForwardIntent.setComponent(new ComponentName(context, DownloadService.class)); fastForwardIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD)); pendingIntent = PendingIntent.getService(context, 0, fastForwardIntent, 0); rv.setOnClickPendingIntent(fastForward, pendingIntent); } - if(close > 0) { + if (close > 0) { Intent prevIntent = new Intent("KEYCODE_MEDIA_STOP"); prevIntent.setComponent(new ComponentName(context, DownloadService.class)); prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_STOP)); @@ -246,21 +237,18 @@ public final class Notifications { playShowing = false; // Remove notification and remove the service from the foreground - handler.post(new Runnable() { - @Override - public void run() { - downloadService.stopForeground(true); + handler.post(() -> { + downloadService.stopForeground(true); - if(persistentPlayingShowing) { - NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE); - notificationManager.cancel(NOTIFICATION_ID_PLAYING); - persistentPlayingShowing = false; - } + if (persistentPlayingShowing) { + NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE); + notificationManager.cancel(NOTIFICATION_ID_PLAYING); + persistentPlayingShowing = false; } }); // Get downloadNotification in foreground if playing - if(downloadShowing) { + if (downloadShowing) { showDownloadingNotification(context, downloadService, handler, downloadService.getCurrentDownloading(), downloadService.getBackgroundDownloads().size()); } @@ -274,7 +262,7 @@ public final class Notifications { PendingIntent cancelPI = PendingIntent.getService(context, 0, cancelIntent, 0); String currentDownloading, currentSize; - if(file != null) { + if (file != null) { currentDownloading = file.getSong().getTitle(); currentSize = Util.formatLocalizedBytes(file.getEstimatedSize(), context); } else { @@ -307,37 +295,28 @@ public final class Notifications { cancelPI) .setContentIntent(PendingIntent.getActivity(context, 2, notificationIntent, 0)) .setStyle(new NotificationCompat.BigTextStyle() - .bigText(context.getResources().getString(R.string.download_downloading_summary_expanded, currentDownloading, currentSize))) + .bigText(context.getResources().getString(R.string.download_downloading_summary_expanded, currentDownloading, currentSize))) .setProgress(10, 5, true).build(); downloadShowing = true; - if(playShowing) { + if (playShowing) { NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE); notificationManager.notify(NOTIFICATION_ID_DOWNLOADING, notification); } else { downloadForeground = true; - handler.post(new Runnable() { - @Override - public void run() { - downloadService.startForeground(NOTIFICATION_ID_DOWNLOADING, notification); - } - }); + handler.post(() -> downloadService.startForeground(NOTIFICATION_ID_DOWNLOADING, notification)); } } + public static void hideDownloadingNotification(final Context context, final DownloadService downloadService, Handler handler) { downloadShowing = false; - if(playShowing) { + if (playShowing) { NotificationManager notificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE); notificationManager.cancel(NOTIFICATION_ID_DOWNLOADING); } else { downloadForeground = false; - handler.post(new Runnable() { - @Override - public void run() { - downloadService.stopForeground(true); - } - }); + handler.post(() -> downloadService.stopForeground(true)); } } } diff --git a/app/src/main/java/net/nullsum/audinaut/util/Pair.java b/app/src/main/java/net/nullsum/audinaut/util/Pair.java index 0b7994f..e210702 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/Pair.java +++ b/app/src/main/java/net/nullsum/audinaut/util/Pair.java @@ -25,11 +25,8 @@ import java.io.Serializable; */ public class Pair implements Serializable { - private S first; - private T second; - - public Pair() { - } + private final S first; + private final T second; public Pair(S first, T second) { this.first = first; @@ -40,15 +37,8 @@ public class Pair implements Serializable { return first; } - public void setFirst(S first) { - this.first = first; - } - public T getSecond() { return second; } - public void setSecond(T second) { - this.second = second; - } } diff --git a/app/src/main/java/net/nullsum/audinaut/util/ProgressListener.java b/app/src/main/java/net/nullsum/audinaut/util/ProgressListener.java index 9f9dedd..f59d7d4 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/ProgressListener.java +++ b/app/src/main/java/net/nullsum/audinaut/util/ProgressListener.java @@ -23,6 +23,6 @@ package net.nullsum.audinaut.util; */ public interface ProgressListener { void updateProgress(String message); - void updateProgress(int messageId); + void updateCache(int changeCode); } diff --git a/app/src/main/java/net/nullsum/audinaut/util/ServerProxy.java b/app/src/main/java/net/nullsum/audinaut/util/ServerProxy.java index 04bf12f..c31fc71 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/ServerProxy.java +++ b/app/src/main/java/net/nullsum/audinaut/util/ServerProxy.java @@ -15,46 +15,36 @@ package net.nullsum.audinaut.util; +import android.util.Log; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; -import java.math.BigInteger; -import java.net.HttpURLConnection; -import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketTimeoutException; -import java.net.URL; import java.net.URLDecoder; import java.net.URLEncoder; import java.net.UnknownHostException; -import java.nio.ByteOrder; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; -import android.content.Context; -import android.net.wifi.WifiManager; -import android.util.Log; - public abstract class ServerProxy implements Runnable { private static final String TAG = ServerProxy.class.getSimpleName(); - + boolean isRunning; private Thread thread; - protected boolean isRunning; private ServerSocket socket; private int port; - private Context context; - public ServerProxy(Context context) { + ServerProxy() { // Create listening socket try { socket = new ServerSocket(0); socket.setSoTimeout(5000); port = socket.getLocalPort(); - this.context = context; } catch (UnknownHostException e) { // impossible } catch (IOException e) { Log.e(TAG, "IOException initializing server", e); @@ -62,7 +52,7 @@ public abstract class ServerProxy implements Runnable { } public void start() { - if(socket.isBound()) { + if (socket.isBound()) { thread = new Thread(this, "Socket Proxy"); thread.start(); } else { @@ -72,35 +62,18 @@ public abstract class ServerProxy implements Runnable { public void stop() { isRunning = false; - if(thread != null) { + if (thread != null) { thread.interrupt(); } } public String getPrivateAddress(String request) { - return getAddress("127.0.0.1", request); + return getAddress(request); } - public String getPublicAddress(String request) { - WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); - int ipAddress = wifiManager.getConnectionInfo().getIpAddress(); - if (ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN)) { - ipAddress = Integer.reverseBytes(ipAddress); - } - - byte[] ipByteArray = BigInteger.valueOf(ipAddress).toByteArray(); - String ipAddressString = null; + private String getAddress(String request) { try { - ipAddressString = InetAddress.getByAddress(ipByteArray).getHostAddress(); - } catch(UnknownHostException ex) { - Log.e(TAG, "Unable to get host address."); - } - - return getAddress(ipAddressString, request); - } - private String getAddress(String host, String request) { - try { - return String.format("http://%s:%d/%s", host, port, URLEncoder.encode(request, "UTF-8")); + return String.format("http://%s:%d/%s", "127.0.0.1", port, URLEncoder.encode(request, "UTF-8")); } catch (UnsupportedEncodingException e) { return null; } @@ -134,16 +107,16 @@ public abstract class ServerProxy implements Runnable { abstract ProxyTask getTask(Socket client); protected abstract class ProxyTask implements Runnable { - protected Socket client; - protected String path; - protected int cbSkip = 0; - protected Map requestHeaders = new HashMap<>(); + final Socket client; + final Map requestHeaders = new HashMap<>(); + String path; + int cbSkip = 0; public ProxyTask(Socket client) { this.client = client; } - protected boolean readRequest() { + boolean readRequest() { InputStream is; String firstLine; BufferedReader reader; @@ -162,14 +135,13 @@ public abstract class ServerProxy implements Runnable { } StringTokenizer st = new StringTokenizer(firstLine); - if(!st.hasMoreTokens()) { + if (!st.hasMoreTokens()) { Log.w(TAG, "Unknown request with no tokens"); return false; - } else if(st.countTokens() < 2) { + } else if (st.countTokens() < 2) { Log.w(TAG, "Unknown request with no uri: \"" + firstLine + '"'); return false; } - String method = st.nextToken(); String uri = st.nextToken(); String realUri = uri.substring(1); @@ -184,19 +156,19 @@ public abstract class ServerProxy implements Runnable { // Get all of the headers try { String line; - while((line = reader.readLine()) != null && !"".equals(line)) { + while ((line = reader.readLine()) != null && !"".equals(line)) { int index = line.indexOf(':'); // Ignore headers without ':' or where ':' is the last thing in the string - if(index != -1 && (index + 2) < line.length()) { + if (index != -1 && (index + 2) < line.length()) { String headerName = line.substring(0, index); String headerValue = line.substring(index + 2); requestHeaders.put(headerName, headerValue); } } - } catch(IOException e) { + } catch (IOException e) { // Don't really care once past first line - } catch(Exception e) { + } catch (Exception e) { Log.w(TAG, "Exception reading request", e); } @@ -211,13 +183,13 @@ public abstract class ServerProxy implements Runnable { // Try to get range requested String range = requestHeaders.get("Range"); - if(range != null) { + if (range != null) { int index = range.indexOf("="); - if(index >= 0) { + if (index >= 0) { range = range.substring(index + 1); index = range.indexOf("-"); - if(index > 0) { + if (index > 0) { range = range.substring(0, index); } diff --git a/app/src/main/java/net/nullsum/audinaut/util/SettingsBackupAgent.java b/app/src/main/java/net/nullsum/audinaut/util/SettingsBackupAgent.java index dd63fc9..d4fa82d 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/SettingsBackupAgent.java +++ b/app/src/main/java/net/nullsum/audinaut/util/SettingsBackupAgent.java @@ -23,11 +23,8 @@ import android.app.backup.BackupDataInput; import android.app.backup.SharedPreferencesBackupHelper; import android.os.ParcelFileDescriptor; -import java.io.IOError; import java.io.IOException; -import net.nullsum.audinaut.util.Constants; - public class SettingsBackupAgent extends BackupAgentHelper { @Override public void onCreate() { @@ -37,8 +34,8 @@ public class SettingsBackupAgent extends BackupAgentHelper { } @Override - public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException{ + public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException { super.onRestore(data, appVersionCode, newState); Util.getPreferences(this).edit().remove(Constants.PREFERENCES_KEY_CACHE_LOCATION).apply(); } - } +} diff --git a/app/src/main/java/net/nullsum/audinaut/util/ShufflePlayBuffer.java b/app/src/main/java/net/nullsum/audinaut/util/ShufflePlayBuffer.java index 67b6a98..049cb73 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/ShufflePlayBuffer.java +++ b/app/src/main/java/net/nullsum/audinaut/util/ShufflePlayBuffer.java @@ -18,6 +18,14 @@ */ package net.nullsum.audinaut.util; +import android.content.SharedPreferences; +import android.util.Log; + +import net.nullsum.audinaut.domain.MusicDirectory; +import net.nullsum.audinaut.service.DownloadService; +import net.nullsum.audinaut.service.MusicService; +import net.nullsum.audinaut.service.MusicServiceFactory; + import java.io.File; import java.util.ArrayList; import java.util.List; @@ -25,15 +33,6 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import android.content.Context; -import android.content.SharedPreferences; -import android.util.Log; -import net.nullsum.audinaut.domain.MusicDirectory; -import net.nullsum.audinaut.service.DownloadService; -import net.nullsum.audinaut.service.MusicService; -import net.nullsum.audinaut.service.MusicServiceFactory; -import net.nullsum.audinaut.util.FileUtil; - /** * @author Sindre Mehus * @version $Id$ @@ -42,17 +41,15 @@ public class ShufflePlayBuffer { private static final String TAG = ShufflePlayBuffer.class.getSimpleName(); private static final String CACHE_FILENAME = "shuffleBuffer.ser"; - + private final ArrayList buffer = new ArrayList<>(); + private final Runnable runnable; + private final DownloadService context; + private final int refillThreshold; private ScheduledExecutorService executorService; - private Runnable runnable; private boolean firstRun = true; - private final ArrayList buffer = new ArrayList(); private int lastCount = -1; - private DownloadService context; private boolean awaitingResults = false; private int capacity; - private int refillThreshold; - private SharedPreferences.OnSharedPreferenceChangeListener listener; private int currentServer; private String currentFolder = ""; @@ -64,12 +61,7 @@ public class ShufflePlayBuffer { this.context = context; executorService = Executors.newSingleThreadScheduledExecutor(); - runnable = new Runnable() { - @Override - public void run() { - refill(); - } - }; + runnable = this::refill; executorService.scheduleWithFixedDelay(runnable, 1, 10, TimeUnit.SECONDS); // Calculate out the capacity and refill threshold based on the user's random size preference @@ -87,7 +79,7 @@ public class ShufflePlayBuffer { // Make sure fetcher is running if needed restart(); - List result = new ArrayList(size); + List result = new ArrayList<>(size); synchronized (buffer) { boolean removed = false; while (!buffer.isEmpty() && result.size() < size) { @@ -96,12 +88,12 @@ public class ShufflePlayBuffer { } // Re-cache if anything is taken out - if(removed) { + if (removed) { FileUtil.serialize(context, buffer, CACHE_FILENAME); } } Log.i(TAG, "Taking " + result.size() + " songs from shuffle play buffer. " + buffer.size() + " remaining."); - if(result.isEmpty()) { + if (result.isEmpty()) { awaitingResults = true; } return result; @@ -113,8 +105,8 @@ public class ShufflePlayBuffer { } private void restart() { - synchronized(buffer) { - if(buffer.size() <= refillThreshold && lastCount != 0 && executorService.isShutdown()) { + synchronized (buffer) { + if (buffer.size() <= refillThreshold && lastCount != 0 && executorService.isShutdown()) { executorService = Executors.newSingleThreadScheduledExecutor(); executorService.scheduleWithFixedDelay(runnable, 0, 10, TimeUnit.SECONDS); } @@ -136,15 +128,12 @@ public class ShufflePlayBuffer { // Get capacity based int n = capacity - buffer.size(); String folder = null; - if(!Util.isTagBrowsing(context)) { - folder = Util.getSelectedMusicFolderId(context); - } MusicDirectory songs = service.getRandomSongs(n, folder, genre, startYear, endYear, context, null); synchronized (buffer) { lastCount = 0; - for(MusicDirectory.Entry entry: songs.getChildren()) { - if(!buffer.contains(entry)) { + for (MusicDirectory.Entry entry : songs.getChildren()) { + if (!buffer.contains(entry)) { buffer.add(entry); lastCount++; } @@ -156,15 +145,15 @@ public class ShufflePlayBuffer { } } catch (Exception x) { // Give it one more try before quitting - if(lastCount != -2) { + if (lastCount != -2) { lastCount = -2; - } else if(lastCount == -2) { + } else if (lastCount == -2) { lastCount = 0; } Log.w(TAG, "Failed to refill shuffle play buffer.", x); } - if(awaitingResults) { + if (awaitingResults) { awaitingResults = false; context.checkDownloads(); } @@ -186,18 +175,15 @@ public class ShufflePlayBuffer { endYear = prefs.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, ""); buffer.clear(); - if(firstRun) { + if (firstRun) { ArrayList cacheList = FileUtil.deserialize(context, CACHE_FILENAME, ArrayList.class); - if(cacheList != null) { + if (cacheList != null) { buffer.addAll(cacheList); } - listener = new SharedPreferences.OnSharedPreferenceChangeListener() { - @Override - public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { - clearBufferIfnecessary(); - restart(); - } + listener = (prefs1, key) -> { + clearBufferIfnecessary(); + restart(); }; prefs.registerOnSharedPreferenceChangeListener(listener); firstRun = false; diff --git a/app/src/main/java/net/nullsum/audinaut/util/SilentBackgroundTask.java b/app/src/main/java/net/nullsum/audinaut/util/SilentBackgroundTask.java index f37abc9..51894af 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/SilentBackgroundTask.java +++ b/app/src/main/java/net/nullsum/audinaut/util/SilentBackgroundTask.java @@ -38,10 +38,6 @@ public abstract class SilentBackgroundTask extends BackgroundTask { // Don't do anything unless overriden } - @Override - public void updateProgress(int messageId) { - } - @Override public void updateProgress(String message) { } diff --git a/app/src/main/java/net/nullsum/audinaut/util/SilentServiceTask.java b/app/src/main/java/net/nullsum/audinaut/util/SilentServiceTask.java deleted file mode 100644 index 990d7fd..0000000 --- a/app/src/main/java/net/nullsum/audinaut/util/SilentServiceTask.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - This file is part of Subsonic. - - Subsonic is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Subsonic is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Subsonic. If not, see . - - Copyright 2015 (C) Scott Jackson -*/ - -package net.nullsum.audinaut.util; - -import android.content.Context; - -import net.nullsum.audinaut.service.MusicService; -import net.nullsum.audinaut.service.MusicServiceFactory; - -public abstract class SilentServiceTask extends SilentBackgroundTask { - protected MusicService musicService; - - public SilentServiceTask(Context context) { - super(context); - } - - @Override - protected T doInBackground() throws Throwable { - musicService = MusicServiceFactory.getMusicService(getContext()); - return doInBackground(musicService); - } - - protected abstract T doInBackground(MusicService musicService) throws Throwable; -} diff --git a/app/src/main/java/net/nullsum/audinaut/util/SimpleServiceBinder.java b/app/src/main/java/net/nullsum/audinaut/util/SimpleServiceBinder.java index a7b12a0..82e5f97 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/SimpleServiceBinder.java +++ b/app/src/main/java/net/nullsum/audinaut/util/SimpleServiceBinder.java @@ -25,13 +25,7 @@ import android.os.Binder; */ public class SimpleServiceBinder extends Binder { - private final S service; - - public SimpleServiceBinder(S service) { - this.service = service; + public SimpleServiceBinder() { } - public S getService() { - return service; - } } diff --git a/app/src/main/java/net/nullsum/audinaut/util/SongDBHandler.java b/app/src/main/java/net/nullsum/audinaut/util/SongDBHandler.java index b97892a..a26b5e8 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/SongDBHandler.java +++ b/app/src/main/java/net/nullsum/audinaut/util/SongDBHandler.java @@ -22,34 +22,37 @@ import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; +import net.nullsum.audinaut.domain.MusicDirectory; + import java.util.ArrayList; import java.util.List; -import net.nullsum.audinaut.domain.MusicDirectory; -import net.nullsum.audinaut.service.DownloadFile; - public class SongDBHandler extends SQLiteOpenHelper { - private static final String TAG = SongDBHandler.class.getSimpleName(); - private static SongDBHandler dbHandler; - + private static final String DATABASE_NAME = "SongsDB"; + private static final String TABLE_SONGS = "RegisteredSongs"; + private static final String SONGS_ID = "id"; + private static final String SONGS_SERVER_KEY = "serverKey"; + private static final String SONGS_SERVER_ID = "serverId"; + private static final String SONGS_COMPLETE_PATH = "completePath"; + private static final String SONGS_LAST_PLAYED = "lastPlayed"; + private static final String SONGS_LAST_COMPLETED = "lastCompleted"; private static final int DATABASE_VERSION = 2; - public static final String DATABASE_NAME = "SongsDB"; - - public static final String TABLE_SONGS = "RegisteredSongs"; - public static final String SONGS_ID = "id"; - public static final String SONGS_SERVER_KEY = "serverKey"; - public static final String SONGS_SERVER_ID = "serverId"; - public static final String SONGS_COMPLETE_PATH = "completePath"; - public static final String SONGS_LAST_PLAYED = "lastPlayed"; - public static final String SONGS_LAST_COMPLETED = "lastCompleted"; - - private Context context; + private static SongDBHandler dbHandler; + private final Context context; private SongDBHandler(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); this.context = context; } + public static SongDBHandler getHandler(Context context) { + if (dbHandler == null) { + dbHandler = new SongDBHandler(context); + } + + return dbHandler; + } + @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE " + TABLE_SONGS + " ( " + @@ -68,51 +71,23 @@ public class SongDBHandler extends SQLiteOpenHelper { this.onCreate(db); } - public synchronized void addSong(DownloadFile downloadFile) { - addSong(Util.getMostRecentActiveServer(context), downloadFile); - } - public synchronized void addSong(int instance, DownloadFile downloadFile) { - SQLiteDatabase db = this.getWritableDatabase(); - addSong(db, instance, downloadFile); - db.close(); - } - protected synchronized void addSong(SQLiteDatabase db, DownloadFile downloadFile) { - addSong(db, Util.getMostRecentActiveServer(context), downloadFile); - } - protected synchronized void addSong(SQLiteDatabase db, int instance, DownloadFile downloadFile) { - addSong(db, instance, downloadFile.getSong().getId(), downloadFile.getSaveFile().getAbsolutePath()); - } - - protected synchronized void addSong(SQLiteDatabase db, String id, String absolutePath) { - addSong(db, Util.getMostRecentActiveServer(context), id, absolutePath); - } - protected synchronized void addSong(SQLiteDatabase db, int instance, String id, String absolutePath) { - addSongImpl(db, Util.getRestUrlHash(context, instance), id, absolutePath); - } - protected synchronized void addSongImpl(SQLiteDatabase db, int serverKey, String id, String absolutePath) { - ContentValues values = new ContentValues(); - values.put(SONGS_SERVER_KEY, serverKey); - values.put(SONGS_SERVER_ID, id); - values.put(SONGS_COMPLETE_PATH, absolutePath); - - db.insertWithOnConflict(TABLE_SONGS, null, values, SQLiteDatabase.CONFLICT_IGNORE); - } - public synchronized void addSongs(int instance, List entries) { SQLiteDatabase db = this.getWritableDatabase(); List> pairs = new ArrayList<>(); - for(MusicDirectory.Entry entry: entries) { + for (MusicDirectory.Entry entry : entries) { pairs.add(new Pair<>(entry.getId(), FileUtil.getSongFile(context, entry).getAbsolutePath())); } addSongs(db, instance, pairs); db.close(); } - public synchronized void addSongs(SQLiteDatabase db, int instance, List> entries) { + + private synchronized void addSongs(SQLiteDatabase db, int instance, List> entries) { addSongsImpl(db, Util.getRestUrlHash(context, instance), entries); } - protected synchronized void addSongsImpl(SQLiteDatabase db, int serverKey, List> entries) { + + private synchronized void addSongsImpl(SQLiteDatabase db, int serverKey, List> entries) { db.beginTransaction(); try { for (Pair entry : entries) { @@ -126,50 +101,25 @@ public class SongDBHandler extends SQLiteOpenHelper { } db.setTransactionSuccessful(); - } catch(Exception e) {} + } catch (Exception ignored) { + } db.endTransaction(); } - public synchronized void setSongPlayed(DownloadFile downloadFile, boolean submission) { - // TODO: In case of offline want to update all matches - Pair pair = getOnlineSongId(downloadFile); - if(pair == null) { - return; - } - int serverKey = pair.getFirst(); - String id = pair.getSecond(); - - // Open and make sure song is in db - SQLiteDatabase db = this.getWritableDatabase(); - addSongImpl(db, serverKey, id, downloadFile.getSaveFile().getAbsolutePath()); - - // Update song's last played - ContentValues values = new ContentValues(); - values.put(submission ? SONGS_LAST_COMPLETED : SONGS_LAST_PLAYED, System.currentTimeMillis()); - db.update(TABLE_SONGS, values, SONGS_SERVER_KEY + " = ? AND " + SONGS_SERVER_ID + " = ?", new String[]{Integer.toString(serverKey), id}); - db.close(); - } - - public boolean hasBeenPlayed(MusicDirectory.Entry entry) { - Long[] lastPlayed = getLastPlayed(entry); - return lastPlayed != null && lastPlayed[0] != null && lastPlayed[0] > 0; - } - public boolean hasBeenCompleted(MusicDirectory.Entry entry) { - Long[] lastPlayed = getLastPlayed(entry); - return lastPlayed != null && lastPlayed[1] != null && lastPlayed[1] > 0; - } public synchronized Long[] getLastPlayed(MusicDirectory.Entry entry) { return getLastPlayed(getOnlineSongId(entry)); } - protected synchronized Long[] getLastPlayed(Pair pair) { - if(pair == null) { + + private synchronized Long[] getLastPlayed(Pair pair) { + if (pair == null) { return null; } else { return getLastPlayed(pair.getFirst(), pair.getSecond()); } } - public synchronized Long[] getLastPlayed(int serverKey, String id) { + + private synchronized Long[] getLastPlayed(int serverKey, String id) { SQLiteDatabase db = this.getReadableDatabase(); String[] columns = {SONGS_LAST_PLAYED, SONGS_LAST_COMPLETED}; @@ -182,33 +132,23 @@ public class SongDBHandler extends SQLiteOpenHelper { dates[0] = cursor.getLong(0); dates[1] = cursor.getLong(1); return dates; - } catch(Exception e) { + } catch (Exception e) { return null; - } - finally { + } finally { cursor.close(); db.close(); } } - public synchronized Pair getOnlineSongId(MusicDirectory.Entry entry) { - return getOnlineSongId(Util.getRestUrlHash(context), entry.getId(), FileUtil.getSongFile(context, entry).getAbsolutePath(), Util.isOffline(context) ? false : true); - } - public synchronized Pair getOnlineSongId(DownloadFile downloadFile) { - return getOnlineSongId(Util.getRestUrlHash(context), downloadFile.getSong().getId(), downloadFile.getSaveFile().getAbsolutePath(), Util.isOffline(context) ? false : true); + private synchronized Pair getOnlineSongId(MusicDirectory.Entry entry) { + return getOnlineSongId(Util.getRestUrlHash(context), entry.getId(), FileUtil.getSongFile(context, entry).getAbsolutePath(), !Util.isOffline(context)); } - public synchronized Pair getOnlineSongId(int serverKey, MusicDirectory.Entry entry) { - return getOnlineSongId(serverKey, new DownloadFile(context, entry, true)); - } - public synchronized Pair getOnlineSongId(int serverKey, DownloadFile downloadFile) { - return getOnlineSongId(serverKey, downloadFile.getSong().getId(), downloadFile.getSaveFile().getAbsolutePath(), true); - } - public synchronized Pair getOnlineSongId(int serverKey, String id, String savePath, boolean requireServerKey) { + private synchronized Pair getOnlineSongId(int serverKey, String id, String savePath, boolean requireServerKey) { SharedPreferences prefs = Util.getPreferences(context); String cacheLocn = prefs.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, null); - if(cacheLocn != null && id.indexOf(cacheLocn) != -1) { - if(requireServerKey) { + if (cacheLocn != null && id.contains(cacheLocn)) { + if (requireServerKey) { return getIdFromPath(serverKey, savePath); } else { return getIdFromPath(savePath); @@ -218,46 +158,37 @@ public class SongDBHandler extends SQLiteOpenHelper { } } - public synchronized Pair getIdFromPath(String path) { + private synchronized Pair getIdFromPath(String path) { SQLiteDatabase db = this.getReadableDatabase(); String[] columns = {SONGS_SERVER_KEY, SONGS_SERVER_ID}; - Cursor cursor = db.query(TABLE_SONGS, columns, SONGS_COMPLETE_PATH + " = ?", new String[] { path }, null, null, SONGS_LAST_PLAYED + " DESC", null); + Cursor cursor = db.query(TABLE_SONGS, columns, SONGS_COMPLETE_PATH + " = ?", new String[]{path}, null, null, SONGS_LAST_PLAYED + " DESC", null); try { cursor.moveToFirst(); return new Pair(cursor.getInt(0), cursor.getString(1)); - } catch(Exception e) { + } catch (Exception e) { return null; - } - finally { + } finally { cursor.close(); db.close(); } } + public synchronized Pair getIdFromPath(int serverKey, String path) { SQLiteDatabase db = this.getReadableDatabase(); String[] columns = {SONGS_SERVER_KEY, SONGS_SERVER_ID}; - Cursor cursor = db.query(TABLE_SONGS, columns, SONGS_SERVER_KEY + " = ? AND " + SONGS_COMPLETE_PATH + " = ?", new String[] {Integer.toString(serverKey), path }, null, null, null, null); + Cursor cursor = db.query(TABLE_SONGS, columns, SONGS_SERVER_KEY + " = ? AND " + SONGS_COMPLETE_PATH + " = ?", new String[]{Integer.toString(serverKey), path}, null, null, null, null); try { cursor.moveToFirst(); return new Pair(cursor.getInt(0), cursor.getString(1)); - } catch(Exception e) { + } catch (Exception e) { return null; - } - finally { + } finally { cursor.close(); db.close(); } } - - public static SongDBHandler getHandler(Context context) { - if(dbHandler == null) { - dbHandler = new SongDBHandler(context); - } - - return dbHandler; - } } diff --git a/app/src/main/java/net/nullsum/audinaut/util/SyncUtil.java b/app/src/main/java/net/nullsum/audinaut/util/SyncUtil.java index 432fd8d..e694bfa 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/SyncUtil.java +++ b/app/src/main/java/net/nullsum/audinaut/util/SyncUtil.java @@ -1,31 +1,22 @@ package net.nullsum.audinaut.util; -import android.app.NotificationManager; -import android.app.PendingIntent; import android.content.Context; -import android.content.Intent; -import android.support.v4.app.NotificationCompat; import java.io.File; import java.io.Serializable; import java.util.ArrayList; -import java.util.List; - -import net.nullsum.audinaut.R; -import net.nullsum.audinaut.activity.SubsonicFragmentActivity; /** * Created by Scott on 11/24/13. */ public final class SyncUtil { - private static String TAG = SyncUtil.class.getSimpleName(); private static ArrayList syncedPlaylists; private static String url; private static void checkRestURL(Context context) { int instance = Util.getActiveServer(context); String newURL = Util.getRestUrl(context, null, instance, false); - if(url == null || !url.equals(newURL)) { + if (url == null || !url.equals(newURL)) { syncedPlaylists = null; url = newURL; } @@ -34,25 +25,27 @@ public final class SyncUtil { // Playlist sync public static boolean isSyncedPlaylist(Context context, String playlistId) { checkRestURL(context); - if(syncedPlaylists == null) { + if (syncedPlaylists == null) { syncedPlaylists = getSyncedPlaylists(context); } return syncedPlaylists.contains(new SyncSet(playlistId)); } - public static ArrayList getSyncedPlaylists(Context context) { + + private static ArrayList getSyncedPlaylists(Context context) { return getSyncedPlaylists(context, Util.getActiveServer(context)); } - public static ArrayList getSyncedPlaylists(Context context, int instance) { + + private static ArrayList getSyncedPlaylists(Context context, int instance) { String syncFile = getPlaylistSyncFile(context, instance); ArrayList playlists = FileUtil.deserializeCompressed(context, syncFile, ArrayList.class); - if(playlists == null) { - playlists = new ArrayList(); + if (playlists == null) { + playlists = new ArrayList<>(); // Try to convert old style into new style ArrayList oldPlaylists = FileUtil.deserialize(context, syncFile, ArrayList.class); // If exists, time to convert! - if(oldPlaylists != null) { - for(String id: oldPlaylists) { + if (oldPlaylists != null) { + for (String id : oldPlaylists) { playlists.add(new SyncSet(id)); } @@ -61,91 +54,49 @@ public final class SyncUtil { } return playlists; } - public static void setSyncedPlaylists(Context context, int instance, ArrayList playlists) { - FileUtil.serializeCompressed(context, playlists, getPlaylistSyncFile(context, instance)); - } - public static void addSyncedPlaylist(Context context, String playlistId) { - String playlistFile = getPlaylistSyncFile(context); - ArrayList playlists = getSyncedPlaylists(context); - SyncSet set = new SyncSet(playlistId); - if(!playlists.contains(set)) { - playlists.add(set); - } - FileUtil.serializeCompressed(context, playlists, playlistFile); - syncedPlaylists = playlists; - } + public static void removeSyncedPlaylist(Context context, String playlistId) { int instance = Util.getActiveServer(context); removeSyncedPlaylist(context, playlistId, instance); } - public static void removeSyncedPlaylist(Context context, String playlistId, int instance) { + + private static void removeSyncedPlaylist(Context context, String playlistId, int instance) { String playlistFile = getPlaylistSyncFile(context, instance); ArrayList playlists = getSyncedPlaylists(context, instance); SyncSet set = new SyncSet(playlistId); - if(playlists.contains(set)) { + if (playlists.contains(set)) { playlists.remove(set); FileUtil.serializeCompressed(context, playlists, playlistFile); syncedPlaylists = playlists; } } - public static String getPlaylistSyncFile(Context context) { - int instance = Util.getActiveServer(context); - return getPlaylistSyncFile(context, instance); - } - public static String getPlaylistSyncFile(Context context, int instance) { + + private static String getPlaylistSyncFile(Context context, int instance) { return "sync-playlist-" + (Util.getRestUrl(context, null, instance, false)).hashCode() + ".ser"; } - // Most Recently Added - public static ArrayList getSyncedMostRecent(Context context, int instance) { - ArrayList list = FileUtil.deserialize(context, getMostRecentSyncFile(context, instance), ArrayList.class); - if(list == null) { - list = new ArrayList(); - } - return list; - } public static void removeMostRecentSyncFiles(Context context) { int total = Util.getServerCount(context); - for(int i = 0; i < total; i++) { + for (int i = 0; i < total; i++) { File file = new File(context.getCacheDir(), getMostRecentSyncFile(context, i)); file.delete(); } } - public static String getMostRecentSyncFile(Context context, int instance) { + + private static String getMostRecentSyncFile(Context context, int instance) { return "sync-most_recent-" + (Util.getRestUrl(context, null, instance, false)).hashCode() + ".ser"; } - public static String joinNames(List names) { - StringBuilder builder = new StringBuilder(); - for (String val : names) { - builder.append(val).append(", "); - } - builder.setLength(builder.length() - 2); - return builder.toString(); - } - public static class SyncSet implements Serializable { - public String id; - public List synced; + public final String id; - protected SyncSet() { - - } public SyncSet(String id) { this.id = id; } - public SyncSet(String id, List synced) { - this.id = id; - this.synced = synced; - } @Override public boolean equals(Object obj) { - if(obj instanceof SyncSet) { - return this.id.equals(((SyncSet)obj).id); - } else { - return false; - } + return obj instanceof SyncSet && this.id.equals(((SyncSet) obj).id); } @Override diff --git a/app/src/main/java/net/nullsum/audinaut/util/TabBackgroundTask.java b/app/src/main/java/net/nullsum/audinaut/util/TabBackgroundTask.java index 91ea875..a1649ae 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/TabBackgroundTask.java +++ b/app/src/main/java/net/nullsum/audinaut/util/TabBackgroundTask.java @@ -41,11 +41,6 @@ public abstract class TabBackgroundTask extends BackgroundTask { @Override public void updateProgress(final String message) { - getHandler().post(new Runnable() { - @Override - public void run() { - tabFragment.updateProgress(message); - } - }); + getHandler().post(() -> tabFragment.updateProgress(message)); } } diff --git a/app/src/main/java/net/nullsum/audinaut/util/ThemeUtil.java b/app/src/main/java/net/nullsum/audinaut/util/ThemeUtil.java index 06c996d..981d0b4 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/ThemeUtil.java +++ b/app/src/main/java/net/nullsum/audinaut/util/ThemeUtil.java @@ -19,33 +19,31 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.res.Configuration; -import java.util.Locale; - import net.nullsum.audinaut.R; import net.nullsum.audinaut.activity.SettingsActivity; import net.nullsum.audinaut.activity.SubsonicFragmentActivity; public final class ThemeUtil { - public static final String THEME_DARK = "dark"; - public static final String THEME_BLACK = "black"; - public static final String THEME_LIGHT = "light"; - public static final String THEME_DAY_NIGHT = "day/night"; - public static final String THEME_DAY_BLACK_NIGHT = "day/black"; + private static final String THEME_DARK = "dark"; + private static final String THEME_BLACK = "black"; + private static final String THEME_LIGHT = "light"; + private static final String THEME_DAY_NIGHT = "day/night"; + private static final String THEME_DAY_BLACK_NIGHT = "day/black"; public static String getTheme(Context context) { SharedPreferences prefs = Util.getPreferences(context); String theme = prefs.getString(Constants.PREFERENCES_KEY_THEME, null); - if(THEME_DAY_NIGHT.equals(theme)) { + if (THEME_DAY_NIGHT.equals(theme)) { int currentNightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; - if(currentNightMode == Configuration.UI_MODE_NIGHT_YES) { + if (currentNightMode == Configuration.UI_MODE_NIGHT_YES) { theme = THEME_DARK; } else { theme = THEME_LIGHT; } - } else if(THEME_DAY_BLACK_NIGHT.equals(theme)) { + } else if (THEME_DAY_BLACK_NIGHT.equals(theme)) { int currentNightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; - if(currentNightMode == Configuration.UI_MODE_NIGHT_YES) { + if (currentNightMode == Configuration.UI_MODE_NIGHT_YES) { theme = THEME_BLACK; } else { theme = THEME_LIGHT; @@ -54,12 +52,14 @@ public final class ThemeUtil { return theme; } + public static int getThemeRes(Context context) { return getThemeRes(context, getTheme(context)); } - public static int getThemeRes(Context context, String theme) { - if(context instanceof SubsonicFragmentActivity || context instanceof SettingsActivity) { - if(Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_COLOR_ACTION_BAR, true)) { + + private static int getThemeRes(Context context, String theme) { + if (context instanceof SubsonicFragmentActivity || context instanceof SettingsActivity) { + if (Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_COLOR_ACTION_BAR, true)) { if (THEME_DARK.equals(theme)) { return R.style.Theme_Audinaut_Dark_No_Actionbar; } else if (THEME_BLACK.equals(theme)) { @@ -86,6 +86,7 @@ public final class ThemeUtil { } } } + public static void setTheme(Context context, String theme) { SharedPreferences.Editor editor = Util.getPreferences(context).edit(); editor.putString(Constants.PREFERENCES_KEY_THEME, theme); diff --git a/app/src/main/java/net/nullsum/audinaut/util/TimeLimitedCache.java b/app/src/main/java/net/nullsum/audinaut/util/TimeLimitedCache.java index 8884311..5505af3 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/TimeLimitedCache.java +++ b/app/src/main/java/net/nullsum/audinaut/util/TimeLimitedCache.java @@ -27,12 +27,12 @@ import java.util.concurrent.TimeUnit; */ public class TimeLimitedCache { - private SoftReference value; private final long ttlMillis; + private SoftReference value; private long expires; - public TimeLimitedCache(long ttl, TimeUnit timeUnit) { - this.ttlMillis = TimeUnit.MILLISECONDS.convert(ttl, timeUnit); + public TimeLimitedCache(long ttl) { + this.ttlMillis = TimeUnit.MILLISECONDS.convert(ttl, TimeUnit.SECONDS); } public T get() { @@ -40,12 +40,12 @@ public class TimeLimitedCache { } public void set(T value) { - set(value, ttlMillis, TimeUnit.MILLISECONDS); + set(value, ttlMillis); } - public void set(T value, long ttl, TimeUnit timeUnit) { - this.value = new SoftReference(value); - expires = System.currentTimeMillis() + timeUnit.toMillis(ttl); + private void set(T value, long ttl) { + this.value = new SoftReference<>(value); + expires = System.currentTimeMillis() + TimeUnit.MILLISECONDS.toMillis(ttl); } public void clear() { diff --git a/app/src/main/java/net/nullsum/audinaut/util/UpdateHelper.java b/app/src/main/java/net/nullsum/audinaut/util/UpdateHelper.java index 606b288..ffb8bff 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/UpdateHelper.java +++ b/app/src/main/java/net/nullsum/audinaut/util/UpdateHelper.java @@ -19,72 +19,51 @@ package net.nullsum.audinaut.util; -import android.app.Activity; -import android.content.Context; -import android.content.DialogInterface; -import android.support.v7.app.AlertDialog; -import android.util.Log; -import android.view.View; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import net.nullsum.audinaut.R; -import net.nullsum.audinaut.domain.Artist; -import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.domain.MusicDirectory.Entry; -import net.nullsum.audinaut.fragments.SubsonicFragment; import net.nullsum.audinaut.service.DownloadFile; import net.nullsum.audinaut.service.DownloadService; -import net.nullsum.audinaut.service.MusicService; -import net.nullsum.audinaut.service.MusicServiceFactory; -import net.nullsum.audinaut.service.OfflineException; import net.nullsum.audinaut.view.UpdateView; +import java.util.List; + public final class UpdateHelper { - private static final String TAG = UpdateHelper.class.getSimpleName(); public static abstract class EntryInstanceUpdater { - private Entry entry; + private final Entry entry; protected int metadataUpdate = DownloadService.METADATA_UPDATED_ALL; public EntryInstanceUpdater(Entry entry) { this.entry = entry; } - public EntryInstanceUpdater(Entry entry, int metadataUpdate) { - this.entry = entry; - this.metadataUpdate = metadataUpdate; - } public abstract void update(Entry found); public void execute() { DownloadService downloadService = DownloadService.getInstance(); - if(downloadService != null && !entry.isDirectory()) { + if (downloadService != null && !entry.isDirectory()) { boolean serializeChanges = false; List downloadFiles = downloadService.getDownloads(); DownloadFile currentPlaying = downloadService.getCurrentPlaying(); - for(DownloadFile file: downloadFiles) { + for (DownloadFile file : downloadFiles) { Entry check = file.getSong(); - if(entry.getId().equals(check.getId())) { + if (entry.getId().equals(check.getId())) { update(check); serializeChanges = true; - if(currentPlaying != null && currentPlaying.getSong() != null && currentPlaying.getSong().getId().equals(entry.getId())) { + if (currentPlaying != null && currentPlaying.getSong() != null && currentPlaying.getSong().getId().equals(entry.getId())) { downloadService.onMetadataUpdate(metadataUpdate); } } } - if(serializeChanges) { + if (serializeChanges) { downloadService.serializeQueue(); } } Entry find = UpdateView.findEntry(entry); - if(find != null) { + if (find != null) { update(find); } } diff --git a/app/src/main/java/net/nullsum/audinaut/util/UserUtil.java b/app/src/main/java/net/nullsum/audinaut/util/UserUtil.java index 7e0b332..814c652 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/UserUtil.java +++ b/app/src/main/java/net/nullsum/audinaut/util/UserUtil.java @@ -15,66 +15,36 @@ package net.nullsum.audinaut.util; -import android.app.Activity; -import android.support.v7.app.AlertDialog; import android.content.Context; -import android.content.DialogInterface; import android.content.SharedPreferences; import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.util.Log; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.WindowManager; -import android.widget.TextView; -import net.nullsum.audinaut.R; -import net.nullsum.audinaut.adapter.SectionAdapter; import net.nullsum.audinaut.domain.User; -import net.nullsum.audinaut.fragments.SubsonicFragment; -import net.nullsum.audinaut.service.DownloadService; -import net.nullsum.audinaut.service.MusicService; import net.nullsum.audinaut.service.MusicServiceFactory; -import net.nullsum.audinaut.service.OfflineException; -import net.nullsum.audinaut.adapter.SettingsAdapter; -import net.nullsum.audinaut.view.UpdateView; public final class UserUtil { private static final String TAG = UserUtil.class.getSimpleName(); - private static final long MIN_VERIFY_DURATION = 1000L * 60L * 60L; private static int instance = -1; private static int instanceHash = -1; private static User currentUser; - private static long lastVerifiedTime = 0; - public static void refreshCurrentUser(Context context, boolean forceRefresh) { - refreshCurrentUser(context, forceRefresh, false); - } - public static void refreshCurrentUser(Context context, boolean forceRefresh, boolean unAuth) { + public static void refreshCurrentUser(Context context) { currentUser = null; - if(unAuth) { - lastVerifiedTime = 0; - } - seedCurrentUser(context, forceRefresh); + seedCurrentUser(context); } public static void seedCurrentUser(Context context) { - seedCurrentUser(context, false); - } - public static void seedCurrentUser(final Context context, final boolean refresh) { // Only try to seed if online - if(Util.isOffline(context)) { + if (Util.isOffline(context)) { currentUser = null; return; } final int instance = Util.getActiveServer(context); - final int instanceHash = (instance == 0) ? 0 : Util.getRestUrl(context, null).hashCode(); - if(UserUtil.instance == instance && UserUtil.instanceHash == instanceHash && currentUser != null) { + final int instanceHash = (instance == 0) ? 0 : Util.getRestUrl(context).hashCode(); + if (UserUtil.instance == instance && UserUtil.instanceHash == instanceHash && currentUser != null) { return; } else { UserUtil.instance = instance; @@ -84,17 +54,13 @@ public final class UserUtil { new SilentBackgroundTask(context) { @Override protected Void doInBackground() throws Throwable { - currentUser = MusicServiceFactory.getMusicService(context).getUser(refresh, getCurrentUsername(context, instance), context, null); - - // If running, redo cast selector - DownloadService downloadService = DownloadService.getInstance(); - + currentUser = MusicServiceFactory.getMusicService(context).getUser(false, getCurrentUsername(context, instance), context, null); return null; } @Override protected void done(Void result) { - if(context instanceof AppCompatActivity) { + if (context instanceof AppCompatActivity) { ((AppCompatActivity) context).supportInvalidateOptionsMenu(); } } @@ -107,10 +73,7 @@ public final class UserUtil { }.execute(); } - public static User getCurrentUser() { - return currentUser; - } - public static String getCurrentUsername(Context context, int instance) { + private static String getCurrentUsername(Context context, int instance) { SharedPreferences prefs = Util.getPreferences(context); return prefs.getString(Constants.PREFERENCES_KEY_USERNAME + instance, null); } diff --git a/app/src/main/java/net/nullsum/audinaut/util/Util.java b/app/src/main/java/net/nullsum/audinaut/util/Util.java index 61950ae..59cd295 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/Util.java +++ b/app/src/main/java/net/nullsum/audinaut/util/Util.java @@ -18,18 +18,13 @@ package net.nullsum.audinaut.util; import android.app.Activity; -import android.graphics.Color; -import android.support.annotation.StringRes; -import android.support.v7.app.AlertDialog; -import android.content.ClipboardManager; import android.content.ClipData; +import android.content.ClipboardManager; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; @@ -41,23 +36,19 @@ import android.net.NetworkInfo; import android.net.wifi.WifiManager; import android.os.Build; import android.os.Environment; -import android.text.Html; +import android.support.annotation.StringRes; +import android.support.v7.app.AlertDialog; import android.text.SpannableString; import android.text.method.LinkMovementMethod; import android.text.util.Linkify; import android.util.Log; import android.util.SparseArray; -import android.view.View; import android.view.Gravity; -import android.view.Window; -import android.view.WindowManager; -import android.widget.AdapterView; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; + import net.nullsum.audinaut.R; -import net.nullsum.audinaut.activity.SettingsActivity; -import net.nullsum.audinaut.activity.SubsonicFragmentActivity; import net.nullsum.audinaut.adapter.DetailsAdapter; import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.domain.PlayerState; @@ -65,65 +56,48 @@ import net.nullsum.audinaut.domain.RepeatMode; import net.nullsum.audinaut.receiver.MediaButtonIntentReceiver; import net.nullsum.audinaut.service.DownloadService; -import okhttp3.HttpUrl; - import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; import java.math.BigInteger; import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.text.DecimalFormat; -import java.text.NumberFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; -import java.util.Date; import java.util.List; -import java.util.Locale; import java.util.Random; -import java.util.TimeZone; + +import okhttp3.HttpUrl; /** * @author Sindre Mehus * @version $Id$ */ public final class Util { + private static final String EVENT_META_CHANGED = "net.nullsum.audinaut.EVENT_META_CHANGED"; + private static final String EVENT_PLAYSTATE_CHANGED = "net.nullsum.audinaut.EVENT_PLAYSTATE_CHANGED"; + private static final String AVRCP_PLAYSTATE_CHANGED = "com.android.music.playstatechanged"; + private static final String AVRCP_METADATA_CHANGED = "com.android.music.metachanged"; private static final String TAG = Util.class.getSimpleName(); - private static final DecimalFormat GIGA_BYTE_FORMAT = new DecimalFormat("0.00 GB"); private static final DecimalFormat MEGA_BYTE_FORMAT = new DecimalFormat("0.00 MB"); private static final DecimalFormat KILO_BYTE_FORMAT = new DecimalFormat("0 KB"); - + // Used by hexEncode() + private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + // private static Map> tokens = new HashMap<>(); + private static final SparseArray> tokens = new SparseArray<>(); private static DecimalFormat GIGA_BYTE_LOCALIZED_FORMAT = null; private static DecimalFormat MEGA_BYTE_LOCALIZED_FORMAT = null; private static DecimalFormat KILO_BYTE_LOCALIZED_FORMAT = null; private static DecimalFormat BYTE_LOCALIZED_FORMAT = null; - - public static final String EVENT_META_CHANGED = "net.nullsum.audinaut.EVENT_META_CHANGED"; - public static final String EVENT_PLAYSTATE_CHANGED = "net.nullsum.audinaut.EVENT_PLAYSTATE_CHANGED"; - - public static final String AVRCP_PLAYSTATE_CHANGED = "com.android.music.playstatechanged"; - public static final String AVRCP_METADATA_CHANGED = "com.android.music.metachanged"; - private static OnAudioFocusChangeListener focusListener; private static boolean pauseFocus = false; private static boolean lowerFocus = false; - - // Used by hexEncode() - private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - private static Toast toast; - // private static Map> tokens = new HashMap<>(); - private static SparseArray> tokens = new SparseArray<>(); private static Random random; private Util() { @@ -170,7 +144,8 @@ public final class Util { // Don't allow the SERVER_INSTANCE to ever be 0 return prefs.getBoolean(Constants.PREFERENCES_KEY_OFFLINE, false) ? 0 : Math.max(1, prefs.getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1)); } - public static int getMostRecentActiveServer(Context context) { + + private static int getMostRecentActiveServer(Context context) { SharedPreferences prefs = getPreferences(context); return Math.max(1, prefs.getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1)); } @@ -213,7 +188,7 @@ public final class Util { editor.apply(); if (instance == activeInstance) { - if(instance != 1) { + if (instance != 1) { Util.setActiveServer(context, 1); } else { Util.setOffline(context, true); @@ -228,6 +203,7 @@ public final class Util { int instance = prefs.getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1); return prefs.getString(Constants.PREFERENCES_KEY_SERVER_NAME + instance, null); } + public static String getServerName(Context context, int instance) { SharedPreferences prefs = getPreferences(context); return prefs.getString(Constants.PREFERENCES_KEY_SERVER_NAME + instance, null); @@ -244,25 +220,16 @@ public final class Util { public static String getSelectedMusicFolderId(Context context) { return getSelectedMusicFolderId(context, getActiveServer(context)); } + public static String getSelectedMusicFolderId(Context context, int instance) { SharedPreferences prefs = getPreferences(context); return prefs.getString(Constants.PREFERENCES_KEY_MUSIC_FOLDER_ID + instance, null); } - public static boolean getAlbumListsPerFolder(Context context) { - return getAlbumListsPerFolder(context, getActiveServer(context)); - } public static boolean getAlbumListsPerFolder(Context context, int instance) { SharedPreferences prefs = getPreferences(context); return prefs.getBoolean(Constants.PREFERENCES_KEY_ALBUMS_PER_FOLDER + instance, false); } - public static void setAlbumListsPerFolder(Context context, boolean perFolder) { - int instance = getActiveServer(context); - SharedPreferences prefs = getPreferences(context); - SharedPreferences.Editor editor = prefs.edit(); - editor.putBoolean(Constants.PREFERENCES_KEY_ALBUMS_PER_FOLDER + instance, perFolder); - editor.apply(); - } public static boolean getDisplayTrack(Context context) { SharedPreferences prefs = getPreferences(context); @@ -299,41 +266,39 @@ public final class Util { int cacheSize = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_CACHE_SIZE, "-1")); return cacheSize == -1 ? Integer.MAX_VALUE : cacheSize; } + public static boolean isBatchMode(Context context) { return Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_BATCH_MODE, false); } + public static void setBatchMode(Context context, boolean batchMode) { Util.getPreferences(context).edit().putBoolean(Constants.PREFERENCES_KEY_BATCH_MODE, batchMode).apply(); } - public static String getRestUrl(Context context, String method) { - return getRestUrl(context, method, true); + public static String getRestUrl(Context context) { + return getRestUrl(context, null, true); } + public static String getRestUrl(Context context, String method, boolean allowAltAddress) { SharedPreferences prefs = getPreferences(context); int instance = prefs.getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1); return getRestUrl(context, method, prefs, instance, allowAltAddress); } - public static String getRestUrl(Context context, String method, int instance) { - return getRestUrl(context, method, instance, true); - } + public static String getRestUrl(Context context, String method, int instance, boolean allowAltAddress) { SharedPreferences prefs = getPreferences(context); return getRestUrl(context, method, prefs, instance, allowAltAddress); } - public static String getRestUrl(Context context, String method, SharedPreferences prefs, int instance) { - return getRestUrl(context, method, prefs, instance, true); - } - public static String getRestUrl(Context context, String method, SharedPreferences prefs, int instance, boolean allowAltAddress) { + private static String getRestUrl(Context context, String method, SharedPreferences prefs, int instance, boolean allowAltAddress) { String serverUrl = prefs.getString(Constants.PREFERENCES_KEY_SERVER_URL + instance, null); HttpUrl.Builder builder; builder = HttpUrl.parse(serverUrl).newBuilder(); - if(allowAltAddress && Util.isWifiConnected(context)) { + if (allowAltAddress && Util.isWifiConnected(context)) { String SSID = prefs.getString(Constants.PREFERENCES_KEY_SERVER_LOCAL_NETWORK_SSID + instance, ""); - if(!SSID.isEmpty()) { + if (!SSID.isEmpty()) { String currentSSID = Util.getSSID(context); String[] ssidParts = SSID.split(","); @@ -355,7 +320,7 @@ public final class Util { int hash = (username + password).hashCode(); Pair values = tokens.get(hash); - if(values == null) { + if (values == null) { String salt = new BigInteger(130, getRandom()).toString(32); String token = md5Hex(password + salt); values = new Pair<>(salt, token); @@ -374,6 +339,7 @@ public final class Util { public static int getRestUrlHash(Context context) { return getRestUrlHash(context, Util.getMostRecentActiveServer(context)); } + public static int getRestUrlHash(Context context, int instance) { StringBuilder builder = new StringBuilder(); @@ -384,90 +350,39 @@ public final class Util { return builder.toString().hashCode(); } - public static String getBlockTokenUsePref(Context context, int instance) { + private static String getBlockTokenUsePref(Context context, int instance) { return Constants.CACHE_BLOCK_TOKEN_USE + Util.getRestUrl(context, null, instance, false); } - public static boolean getBlockTokenUse(Context context, int instance) { - return getPreferences(context).getBoolean(getBlockTokenUsePref(context, instance), false); - } - public static void setBlockTokenUse(Context context, int instance, boolean block) { + + public static void setBlockTokenUse(Context context, int instance) { SharedPreferences.Editor editor = getPreferences(context).edit(); - editor.putBoolean(getBlockTokenUsePref(context, instance), block); + editor.putBoolean(getBlockTokenUsePref(context, instance), true); editor.apply(); } - public static boolean isTagBrowsing(Context context) { - return isTagBrowsing(context, Util.getActiveServer(context)); - } - public static boolean isTagBrowsing(Context context, int instance) { - return true; - } - - public static String getParentFromEntry(Context context, MusicDirectory.Entry entry) { - if(Util.isTagBrowsing(context)) { - if(!entry.isDirectory()) { - return entry.getAlbumId(); - } else if(entry.isAlbum()) { - return entry.getArtistId(); - } else { - return null; - } - } else { - return entry.getParent(); - } - } - - public static String openToTab(Context context) { - return "Library"; - } - public static SharedPreferences getPreferences(Context context) { return context.getSharedPreferences(Constants.PREFERENCES_FILE_NAME, 0); } - public static SharedPreferences getOfflineSync(Context context) { - return context.getSharedPreferences(Constants.OFFLINE_SYNC_NAME, 0); - } - - public static String getSyncDefault(Context context) { - SharedPreferences prefs = Util.getOfflineSync(context); - return prefs.getString(Constants.OFFLINE_SYNC_DEFAULT, null); - } - public static void setSyncDefault(Context context, String defaultValue) { - SharedPreferences.Editor editor = Util.getOfflineSync(context).edit(); - editor.putString(Constants.OFFLINE_SYNC_DEFAULT, defaultValue); - editor.apply(); - } public static String getCacheName(Context context, String name, String id) { - return getCacheName(context, getActiveServer(context), name, id); - } - public static String getCacheName(Context context, int instance, String name, String id) { - String s = getRestUrl(context, null, instance, false) + id; - return name + "-" + s.hashCode() + ".ser"; - } - public static String getCacheName(Context context, String name) { - return getCacheName(context, getActiveServer(context), name); - } - public static String getCacheName(Context context, int instance, String name) { - String s = getRestUrl(context, null, instance, false); + String s = getRestUrl(context, null, getActiveServer(context), false) + id; return name + "-" + s.hashCode() + ".ser"; } - public static int offlineStarsCount(Context context) { - SharedPreferences offline = getOfflineSync(context); - return offline.getInt(Constants.OFFLINE_STAR_COUNT, 0); + public static String getCacheName(Context context) { + return getCacheName(context, "entryLookup", ""); } - public static String parseOfflineIDSearch(Context context, String id, String cacheLocation) { + public static String parseOfflineIDSearch(String id, String cacheLocation) { // Try to get this info based off of tags first String name = parseOfflineIDSearch(id); - if(name != null) { + if (name != null) { return name; } // Otherwise go nuts trying to parse from file structure name = id.replace(cacheLocation, ""); - if(name.startsWith("/")) { + if (name.startsWith("/")) { name = name.substring(1); } name = name.replace(".complete", "").replace(".partial", ""); @@ -476,12 +391,12 @@ public final class Util { String[] details = name.split("/"); String title = details[details.length - 1]; - if(index == -1) { - if(details.length > 1) { + if (index == -1) { + if (details.length > 1) { String artist = "artist:\"" + details[details.length - 2] + "\""; String simpleArtist = "artist:\"" + title + "\""; title = "album:\"" + title + "\""; - if(details[details.length - 1].equals(details[details.length - 2])) { + if (details[details.length - 1].equals(details[details.length - 2])) { name = title; } else { name = "(" + artist + " AND " + title + ")" + " OR " + simpleArtist; @@ -491,7 +406,7 @@ public final class Util { } } else { String artist; - if(details.length > 2) { + if (details.length > 2) { artist = "artist:\"" + details[details.length - 3] + "\""; } else { artist = "(artist:\"" + details[0] + "\" OR album:\"" + details[0] + "\")"; @@ -503,24 +418,22 @@ public final class Util { return name; } - public static String parseOfflineIDSearch(String id) { + private static String parseOfflineIDSearch(String id) { MusicDirectory.Entry entry = new MusicDirectory.Entry(); File file = new File(id); - if(file.exists()) { + if (file.exists()) { entry.loadMetadata(file); - if(entry.getArtist() != null) { + if (entry.getArtist() != null) { String title = file.getName(); title = title.replace(".complete", "").replace(".partial", ""); int index = title.lastIndexOf("."); title = index == -1 ? title : title.substring(0, index); title = title.substring(title.indexOf('-') + 1); - String query = "artist:\"" + entry.getArtist() + "\"" + - " AND title:\"" + title + "\""; - - return query; + return "artist:\"" + entry.getArtist() + "\"" + + " AND title:\"" + title + "\""; } else { return null; } @@ -533,11 +446,12 @@ public final class Util { SharedPreferences prefs = getPreferences(context); return prefs.getBoolean(Constants.PREFERENCES_KEY_FIRST_LEVEL_ARTIST + getActiveServer(context), true); } + public static void toggleFirstLevelArtist(Context context) { SharedPreferences prefs = Util.getPreferences(context); SharedPreferences.Editor editor = prefs.edit(); - if(prefs.getBoolean(Constants.PREFERENCES_KEY_FIRST_LEVEL_ARTIST + getActiveServer(context), true)) { + if (prefs.getBoolean(Constants.PREFERENCES_KEY_FIRST_LEVEL_ARTIST + getActiveServer(context), true)) { editor.putBoolean(Constants.PREFERENCES_KEY_FIRST_LEVEL_ARTIST + getActiveServer(context), false); } else { editor.putBoolean(Constants.PREFERENCES_KEY_FIRST_LEVEL_ARTIST + getActiveServer(context), true); @@ -572,7 +486,7 @@ public final class Util { return output.toByteArray(); } - public static long copy(InputStream input, OutputStream output) + private static void copy(InputStream input, OutputStream output) throws IOException { byte[] buffer = new byte[1024 * 4]; long count = 0; @@ -581,11 +495,10 @@ public final class Util { output.write(buffer, 0, n); count += n; } - return count; } - public static void renameFile(File from, File to) throws IOException { - if(!from.renameTo(to)) { + public static void renameFile(File from, File to) { + if (!from.renameTo(to)) { Log.i(TAG, "Failed to rename " + from + " to " + to); } } @@ -634,26 +547,22 @@ public final class Util { toast.show(); } - public static void confirmDialog(Context context, int action, int subject, DialogInterface.OnClickListener onClick) { - Util.confirmDialog(context, context.getResources().getString(action).toLowerCase(), context.getResources().getString(subject), onClick, null); - } - public static void confirmDialog(Context context, int action, int subject, DialogInterface.OnClickListener onClick, DialogInterface.OnClickListener onCancel) { - Util.confirmDialog(context, context.getResources().getString(action).toLowerCase(), context.getResources().getString(subject), onClick, onCancel); + public static void confirmDialog(Context context, DialogInterface.OnClickListener onClick) { + Util.confirmDialog(context, context.getResources().getString(R.string.common_delete).toLowerCase(), context.getResources().getString(R.string.common_confirm_message_cache), onClick); } + public static void confirmDialog(Context context, int action, String subject, DialogInterface.OnClickListener onClick) { - Util.confirmDialog(context, context.getResources().getString(action).toLowerCase(), subject, onClick, null); + Util.confirmDialog(context, context.getResources().getString(action).toLowerCase(), subject, onClick); } - public static void confirmDialog(Context context, int action, String subject, DialogInterface.OnClickListener onClick, DialogInterface.OnClickListener onCancel) { - Util.confirmDialog(context, context.getResources().getString(action).toLowerCase(), subject, onClick, onCancel); - } - public static void confirmDialog(Context context, String action, String subject, DialogInterface.OnClickListener onClick, DialogInterface.OnClickListener onCancel) { + + private static void confirmDialog(Context context, String action, String subject, DialogInterface.OnClickListener onClick) { new AlertDialog.Builder(context) - .setIcon(android.R.drawable.ic_dialog_alert) - .setTitle(R.string.common_confirm) - .setMessage(context.getResources().getString(R.string.common_confirm_message, action, subject)) - .setPositiveButton(R.string.common_ok, onClick) - .setNegativeButton(R.string.common_cancel, onCancel) - .show(); + .setIcon(android.R.drawable.ic_dialog_alert) + .setTitle(R.string.common_confirm) + .setMessage(context.getResources().getString(R.string.common_confirm_message, action, subject)) + .setPositiveButton(R.string.common_ok, onClick) + .setNegativeButton(R.string.common_cancel, null) + .show(); } /** @@ -674,20 +583,17 @@ public final class Util { // More than 1 GB? if (byteCount >= 1024 * 1024 * 1024) { - NumberFormat gigaByteFormat = GIGA_BYTE_FORMAT; - return gigaByteFormat.format((double) byteCount / (1024 * 1024 * 1024)); + return GIGA_BYTE_FORMAT.format((double) byteCount / (1024 * 1024 * 1024)); } // More than 1 MB? if (byteCount >= 1024 * 1024) { - NumberFormat megaByteFormat = MEGA_BYTE_FORMAT; - return megaByteFormat.format((double) byteCount / (1024 * 1024)); + return MEGA_BYTE_FORMAT.format((double) byteCount / (1024 * 1024)); } // More than 1 KB? if (byteCount >= 1024) { - NumberFormat kiloByteFormat = KILO_BYTE_FORMAT; - return kiloByteFormat.format((double) byteCount / 1024); + return KILO_BYTE_FORMAT.format((double) byteCount / 1024); } return byteCount + " B"; @@ -753,9 +659,9 @@ public final class Util { int secs = seconds % 60; StringBuilder builder = new StringBuilder(7); - if(hours > 0) { + if (hours > 0) { builder.append(hours).append(":"); - if(minutes < 10) { + if (minutes < 10) { builder.append("0"); } } @@ -772,13 +678,7 @@ public final class Util { } public static boolean equals(Object object1, Object object2) { - if (object1 == object2) { - return true; - } - if (object1 == null || object2 == null) { - return false; - } - return object1.equals(object2); + return object1 == object2 || !(object1 == null || object2 == null) && object1.equals(object2); } @@ -790,7 +690,7 @@ public final class Util { * @param data Bytes to convert to hexadecimal characters. * @return A string containing hexadecimal characters. */ - public static String hexEncode(byte[] data) { + private static String hexEncode(byte[] data) { int length = data.length; char[] out = new char[length << 1]; // two characters form the hex value. @@ -820,10 +720,6 @@ public final class Util { } } - public static boolean isNullOrWhiteSpace(String string) { - return string == null || "".equals(string) || "".equals(string.trim()); - } - public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; @@ -865,7 +761,7 @@ public final class Util { throw new IllegalArgumentException("Strings must not be null"); } - if(t.toString().toLowerCase().indexOf(s.toString().toLowerCase()) != -1) { + if (t.toString().toLowerCase().contains(s.toString().toLowerCase())) { return 1; } @@ -919,12 +815,13 @@ public final class Util { public static boolean isNetworkConnected(Context context) { return isNetworkConnected(context, false); } - public static boolean isNetworkConnected(Context context, boolean streaming) { + + private static boolean isNetworkConnected(Context context, boolean streaming) { ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = manager.getActiveNetworkInfo(); boolean connected = networkInfo != null && networkInfo.isConnected(); - if(streaming) { + if (streaming) { boolean wifiConnected = connected && networkInfo.getType() == ConnectivityManager.TYPE_WIFI; boolean wifiRequired = isWifiRequiredForDownload(context); @@ -933,12 +830,14 @@ public final class Util { return connected; } } - public static boolean isWifiConnected(Context context) { + + private static boolean isWifiConnected(Context context) { ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = manager.getActiveNetworkInfo(); boolean connected = networkInfo != null && networkInfo.isConnected(); return connected && (networkInfo.getType() == ConnectivityManager.TYPE_WIFI); } + public static String getSSID(Context context) { if (isWifiConnected(context)) { WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); @@ -957,113 +856,74 @@ public final class Util { public static boolean isAllowedToDownload(Context context) { return isNetworkConnected(context, true) && !isOffline(context); } + public static boolean isWifiRequiredForDownload(Context context) { SharedPreferences prefs = getPreferences(context); return prefs.getBoolean(Constants.PREFERENCES_KEY_WIFI_REQUIRED_FOR_DOWNLOAD, false); } public static void info(Context context, int titleId, int messageId) { - info(context, titleId, messageId, true); - } - public static void info(Context context, int titleId, String message) { - info(context, titleId, message, true); - } - public static void info(Context context, String title, String message) { - info(context, title, message, true); - } - public static void info(Context context, int titleId, int messageId, boolean linkify) { - showDialog(context, android.R.drawable.ic_dialog_info, titleId, messageId, linkify); - } - public static void info(Context context, int titleId, String message, boolean linkify) { - showDialog(context, android.R.drawable.ic_dialog_info, titleId, message, linkify); - } - public static void info(Context context, String title, String message, boolean linkify) { - showDialog(context, android.R.drawable.ic_dialog_info, title, message, linkify); + showDialog(context, titleId, messageId); } - public static void showDialog(Context context, int icon, int titleId, int messageId) { - showDialog(context, icon, titleId, messageId, true); + private static void showDialog(Context context, int titleId, int messageId) { + showDialog(context, context.getResources().getString(titleId), context.getResources().getString(messageId)); } - public static void showDialog(Context context, int icon, int titleId, String message) { - showDialog(context, icon, titleId, message, true); - } - public static void showDialog(Context context, int icon, String title, String message) { - showDialog(context, icon, title, message, true); - } - public static void showDialog(Context context, int icon, int titleId, int messageId, boolean linkify) { - showDialog(context, icon, context.getResources().getString(titleId), context.getResources().getString(messageId), linkify); - } - public static void showDialog(Context context, int icon, int titleId, String message, boolean linkify) { - showDialog(context, icon, context.getResources().getString(titleId), message, linkify); - } - public static void showDialog(Context context, int icon, String title, String message, boolean linkify) { + + private static void showDialog(Context context, String title, String message) { SpannableString ss = new SpannableString(message); - if(linkify) { - Linkify.addLinks(ss, Linkify.ALL); - } + Linkify.addLinks(ss, Linkify.ALL); AlertDialog dialog = new AlertDialog.Builder(context) - .setIcon(icon) - .setTitle(title) - .setMessage(ss) - .setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int i) { - dialog.dismiss(); - } - }) - .show(); + .setIcon(android.R.drawable.ic_dialog_info) + .setTitle(title) + .setMessage(ss) + .setPositiveButton(R.string.common_ok, (dialog1, i) -> dialog1.dismiss()) + .show(); - ((TextView)dialog.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance()); + ((TextView) dialog.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance()); } public static void showDetailsDialog(Context context, @StringRes int title, List headers, List details) { List headerStrings = new ArrayList<>(); - for(@StringRes Integer res: headers) { + for (@StringRes Integer res : headers) { headerStrings.add(context.getResources().getString(res)); } showDetailsDialog(context, context.getResources().getString(title), headerStrings, details); } - public static void showDetailsDialog(Context context, String title, List headers, final List details) { + + private static void showDetailsDialog(Context context, String title, List headers, final List details) { ListView listView = new ListView(context); - listView.setAdapter(new DetailsAdapter(context, R.layout.details_item, headers, details)); + listView.setAdapter(new DetailsAdapter(context, headers, details)); listView.setDivider(null); listView.setScrollbarFadingEnabled(false); // Let the user long-click on a row to copy its value to the clipboard final Context contextRef = context; - listView.setOnItemLongClickListener(new ListView.OnItemLongClickListener() { - @Override - public boolean onItemLongClick(AdapterView parent, View view, int pos, long id) { - TextView nameView = (TextView) view.findViewById(R.id.detail_name); - TextView detailsView = (TextView) view.findViewById(R.id.detail_value); - if(nameView == null || detailsView == null) { - return false; - } - - CharSequence name = nameView.getText(); - CharSequence value = detailsView.getText(); - - ClipboardManager clipboard = (ClipboardManager) contextRef.getSystemService(Context.CLIPBOARD_SERVICE); - ClipData clip = ClipData.newPlainText(name, value); - clipboard.setPrimaryClip(clip); - - toast(contextRef, "Copied " + name + " to clipboard"); - - return true; + listView.setOnItemLongClickListener((parent, view, pos, id) -> { + TextView nameView = view.findViewById(R.id.detail_name); + TextView detailsView = view.findViewById(R.id.detail_value); + if (nameView == null || detailsView == null) { + return false; } + + CharSequence name = nameView.getText(); + CharSequence value = detailsView.getText(); + + ClipboardManager clipboard = (ClipboardManager) contextRef.getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clip = ClipData.newPlainText(name, value); + clipboard.setPrimaryClip(clip); + + toast(contextRef, "Copied " + name + " to clipboard"); + + return true; }); new AlertDialog.Builder(context) // .setIcon(android.R.drawable.ic_dialog_info) .setTitle(title) .setView(listView) - .setPositiveButton(R.string.common_close, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int i) { - dialog.dismiss(); - } - }) + .setPositiveButton(R.string.common_close, (dialog, i) -> dialog.dismiss()) .show(); } @@ -1075,36 +935,12 @@ public final class Util { } } - public static void startActivityWithoutTransition(Activity currentActivity, Class newActivitiy) { - startActivityWithoutTransition(currentActivity, new Intent(currentActivity, newActivitiy)); - } - public static void startActivityWithoutTransition(Activity currentActivity, Intent intent) { currentActivity.startActivity(intent); - disablePendingTransition(currentActivity); - } - - public static void disablePendingTransition(Activity activity) { - - // Activity.overridePendingTransition() was introduced in Android 2.0. Use reflection to maintain - // compatibility with 1.5. - try { - Method method = Activity.class.getMethod("overridePendingTransition", int.class, int.class); - method.invoke(activity, 0, 0); - } catch (Throwable x) { - // Ignored - } } public static Drawable createDrawableFromBitmap(Context context, Bitmap bitmap) { - // BitmapDrawable(Resources, Bitmap) was introduced in Android 1.6. Use reflection to maintain - // compatibility with 1.5. - try { - Constructor constructor = BitmapDrawable.class.getConstructor(Resources.class, Bitmap.class); - return constructor.newInstance(context.getResources(), bitmap); - } catch (Throwable x) { - return new BitmapDrawable(bitmap); - } + return new BitmapDrawable(context.getResources(), bitmap); } public static void registerMediaButtonEventReceiver(Context context) { @@ -1114,31 +950,16 @@ public final class Util { boolean enabled = prefs.getBoolean(Constants.PREFERENCES_KEY_MEDIA_BUTTONS, true); if (enabled) { - - // AudioManager.registerMediaButtonEventReceiver() was introduced in Android 2.2. - // Use reflection to maintain compatibility with 1.5. - try { - AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - ComponentName componentName = new ComponentName(context.getPackageName(), MediaButtonIntentReceiver.class.getName()); - Method method = AudioManager.class.getMethod("registerMediaButtonEventReceiver", ComponentName.class); - method.invoke(audioManager, componentName); - } catch (Throwable x) { - // Ignored. - } + AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + ComponentName componentName = new ComponentName(context.getPackageName(), MediaButtonIntentReceiver.class.getName()); + audioManager.registerMediaButtonEventReceiver(componentName); } } public static void unregisterMediaButtonEventReceiver(Context context) { - // AudioManager.unregisterMediaButtonEventReceiver() was introduced in Android 2.2. - // Use reflection to maintain compatibility with 1.5. - try { - AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - ComponentName componentName = new ComponentName(context.getPackageName(), MediaButtonIntentReceiver.class.getName()); - Method method = AudioManager.class.getMethod("unregisterMediaButtonEventReceiver", ComponentName.class); - method.invoke(audioManager, componentName); - } catch (Throwable x) { - // Ignored. - } + AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + ComponentName componentName = new ComponentName(context.getPackageName(), MediaButtonIntentReceiver.class.getName()); + audioManager.unregisterMediaButtonEventReceiver(componentName); } public static void requestAudioFocus(final Context context) { @@ -1146,30 +967,30 @@ public final class Util { final AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); audioManager.requestAudioFocus(focusListener = new OnAudioFocusChangeListener() { public void onAudioFocusChange(int focusChange) { - DownloadService downloadService = (DownloadService)context; - if((focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK)) { - if(downloadService.getPlayerState() == PlayerState.STARTED) { + DownloadService downloadService = (DownloadService) context; + if ((focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK)) { + if (downloadService.getPlayerState() == PlayerState.STARTED) { Log.i(TAG, "Temporary loss of focus"); SharedPreferences prefs = getPreferences(context); int lossPref = Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_TEMP_LOSS, "1")); - if(lossPref == 2 || (lossPref == 1 && focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK)) { + if (lossPref == 2 || (lossPref == 1 && focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK)) { lowerFocus = true; downloadService.setVolume(0.1f); - } else if(lossPref == 0 || (lossPref == 1 && focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT)) { + } else if (lossPref == 0 || (lossPref == 1 && focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT)) { pauseFocus = true; downloadService.pause(true); } } } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { - if(pauseFocus) { + if (pauseFocus) { pauseFocus = false; downloadService.start(); } - if(lowerFocus) { + if (lowerFocus) { lowerFocus = false; downloadService.setVolume(1.0f); } - } else if(focusChange == AudioManager.AUDIOFOCUS_LOSS) { + } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { Log.i(TAG, "Permanently lost focus"); focusListener = null; downloadService.pause(); @@ -1180,14 +1001,6 @@ public final class Util { } } - public static void abandonAudioFocus(Context context) { - if(focusListener != null) { - final AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - audioManager.abandonAudioFocus(focusListener); - focusListener = null; - } - } - /** *

Broadcasts the given song info as the new song being played.

*/ @@ -1215,7 +1028,7 @@ public final class Util { context.sendBroadcast(intent); context.sendBroadcast(avrcpIntent); - } catch(Exception e) { + } catch (Exception e) { Log.e(TAG, "Failed to broadcastNewTrackInfo", e); } } @@ -1243,7 +1056,7 @@ public final class Util { break; case PREPARED: // Only send quick pause event for samsung devices, causes issues for others - if (Build.MANUFACTURER.toLowerCase().indexOf("samsung") != -1) { + if (Build.MANUFACTURER.toLowerCase().contains("samsung")) { avrcpIntent.putExtra("playing", false); } else { return; // Don't broadcast anything @@ -1262,14 +1075,14 @@ public final class Util { context.sendBroadcast(intent); } context.sendBroadcast(avrcpIntent); - } catch(Exception e) { + } catch (Exception e) { Log.e(TAG, "Failed to broadcastPlaybackStatusChange", e); } } private static void addTrackInfo(Context context, MusicDirectory.Entry song, Intent intent) { if (song != null) { - DownloadService downloadService = (DownloadService)context; + DownloadService downloadService = (DownloadService) context; File albumArtFile = FileUtil.getAlbumArtFile(context, song); intent.putExtra("track", song.getTitle()); @@ -1280,7 +1093,7 @@ public final class Util { intent.putExtra("duration", (long) downloadService.getPlayerDuration()); intent.putExtra("position", (long) downloadService.getPlayerPosition()); intent.putExtra("coverart", albumArtFile.getAbsolutePath()); - intent.putExtra("package","net.nullsum.audinaut"); + intent.putExtra("package", "net.nullsum.audinaut"); } else { intent.putExtra("track", ""); intent.putExtra("artist", ""); @@ -1290,7 +1103,7 @@ public final class Util { intent.putExtra("duration", (long) 0); intent.putExtra("position", (long) 0); intent.putExtra("coverart", ""); - intent.putExtra("package","net.nullsum.audinaut"); + intent.putExtra("package", "net.nullsum.audinaut"); } } @@ -1299,8 +1112,8 @@ public final class Util { return wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, tag); } - public static Random getRandom() { - if(random == null) { + private static Random getRandom() { + if (random == null) { random = new SecureRandom(); } diff --git a/app/src/main/java/net/nullsum/audinaut/util/tags/Bastp.java b/app/src/main/java/net/nullsum/audinaut/util/tags/Bastp.java index eb4adc3..b2f062a 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/tags/Bastp.java +++ b/app/src/main/java/net/nullsum/audinaut/util/tags/Bastp.java @@ -18,12 +18,12 @@ package net.nullsum.audinaut.util.tags; -import java.io.RandomAccessFile; import java.io.IOException; +import java.io.RandomAccessFile; import java.util.HashMap; -public class Bastp { +class Bastp { public Bastp() { } @@ -34,34 +34,30 @@ public class Bastp { RandomAccessFile ra = new RandomAccessFile(fname, "r"); tags = getTags(ra); ra.close(); - } - catch(Exception e) { + } catch (Exception e) { /* we dont' care much: SOMETHING went wrong. d'oh! */ } return tags; } - public HashMap getTags(RandomAccessFile s) { + private HashMap getTags(RandomAccessFile s) { HashMap tags = new HashMap(); byte[] file_ff = new byte[4]; try { s.read(file_ff); String magic = new String(file_ff); - if(magic.equals("fLaC")) { + if (magic.equals("fLaC")) { tags = (new FlacFile()).getTags(s); - } - else if(magic.equals("OggS")) { + } else if (magic.equals("OggS")) { tags = (new OggFile()).getTags(s); - } - else if(file_ff[0] == -1 && file_ff[1] == -5) { /* aka 0xfffb in real languages */ + } else if (file_ff[0] == -1 && file_ff[1] == -5) { /* aka 0xfffb in real languages */ tags = (new LameHeader()).getTags(s); - } - else if(magic.substring(0,3).equals("ID3")) { + } else if (magic.substring(0, 3).equals("ID3")) { tags = (new ID3v2File()).getTags(s); - if(tags.containsKey("_hdrlen")) { - Long hlen = Long.parseLong( tags.get("_hdrlen").toString(), 10 ); + if (tags.containsKey("_hdrlen")) { + Long hlen = Long.parseLong(tags.get("_hdrlen").toString(), 10); HashMap lameInfo = (new LameHeader()).parseLameHeader(s, hlen); /* add gain tags if not already present */ inheritTag("REPLAYGAIN_TRACK_GAIN", lameInfo, tags); @@ -69,14 +65,13 @@ public class Bastp { } } tags.put("_magic", magic); - } - catch (IOException e) { + } catch (IOException ignored) { } return tags; } private void inheritTag(String key, HashMap from, HashMap to) { - if(!to.containsKey(key) && from.containsKey(key)) { + if (!to.containsKey(key) && from.containsKey(key)) { to.put(key, from.get(key)); } } diff --git a/app/src/main/java/net/nullsum/audinaut/util/tags/BastpUtil.java b/app/src/main/java/net/nullsum/audinaut/util/tags/BastpUtil.java index 269f837..8ce28c3 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/tags/BastpUtil.java +++ b/app/src/main/java/net/nullsum/audinaut/util/tags/BastpUtil.java @@ -18,18 +18,20 @@ package net.nullsum.audinaut.util.tags; import android.support.v4.util.LruCache; + import java.util.HashMap; import java.util.Vector; public final class BastpUtil { - private static final RGLruCache rgCache = new RGLruCache(16); + private static final RGLruCache rgCache = new RGLruCache(); - /** Returns the ReplayGain values of 'path' as + /** + * Returns the ReplayGain values of 'path' as */ public static float[] getReplayGainValues(String path) { float[] cached = rgCache.get(path); - if(cached == null) { + if (cached == null) { cached = getReplayGainValuesFromFile(path); rgCache.put(path, cached); } @@ -37,35 +39,36 @@ public final class BastpUtil { } - - /** Parse given file and return track,album replay gain values + /** + * Parse given file and return track,album replay gain values */ private static float[] getReplayGainValuesFromFile(String path) { - String[] keys = { "REPLAYGAIN_TRACK_GAIN", "REPLAYGAIN_ALBUM_GAIN" }; - float[] adjust= { 0f , 0f }; - HashMap tags = (new Bastp()).getTags(path); + String[] keys = {"REPLAYGAIN_TRACK_GAIN", "REPLAYGAIN_ALBUM_GAIN"}; + float[] adjust = {0f, 0f}; + HashMap tags = (new Bastp()).getTags(path); - for (int i=0; i { - public RGLruCache(int size) { - super(size); + public RGLruCache() { + super(16); } } diff --git a/app/src/main/java/net/nullsum/audinaut/util/tags/Common.java b/app/src/main/java/net/nullsum/audinaut/util/tags/Common.java index fa67271..507144c 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/tags/Common.java +++ b/app/src/main/java/net/nullsum/audinaut/util/tags/Common.java @@ -23,51 +23,44 @@ import java.io.RandomAccessFile; import java.util.HashMap; import java.util.Vector; -public class Common { +class Common { private static final long MAX_PKT_SIZE = 524288; - public void xdie(String reason) throws IOException { + void xdie(String reason) throws IOException { throw new IOException(reason); } /* ** Returns a 32bit int from given byte offset in LE */ - public int b2le32(byte[] b, int off) { + private int b2le32(byte[] b, int off) { int r = 0; - for(int i=0; i<4; i++) { - r |= ( b2u(b[off+i]) << (8*i) ); + for (int i = 0; i < 4; i++) { + r |= (b2u(b[off + i]) << (8 * i)); } return r; } - public int b2be32(byte[] b, int off) { + int b2be32(byte[] b, int off) { return swap32(b2le32(b, off)); } - public int swap32(int i) { - return((i&0xff)<<24)+((i&0xff00)<<8)+((i&0xff0000)>>8)+((i>>24)&0xff); + private int swap32(int i) { + return ((i & 0xff) << 24) + ((i & 0xff00) << 8) + ((i & 0xff0000) >> 8) + ((i >> 24) & 0xff); } /* ** convert 'byte' value into unsigned int */ - public int b2u(byte x) { + int b2u(byte x) { return (x & 0xFF); } - /* - ** Printout debug message to STDOUT - */ - public void debug(String s) { - System.out.println("DBUG "+s); - } - - public HashMap parse_vorbis_comment(RandomAccessFile s, long offset, long payload_len) throws IOException { + HashMap parse_vorbis_comment(RandomAccessFile s, long offset, long payload_len) throws IOException { HashMap tags = new HashMap(); - int comments = 0; // number of found comments - int xoff = 0; // offset within 'scratch' - int can_read = (int)(payload_len > MAX_PKT_SIZE ? MAX_PKT_SIZE : payload_len); + int comments; // number of found comments + int xoff = 0; // offset within 'scratch' + int can_read = (int) (payload_len > MAX_PKT_SIZE ? MAX_PKT_SIZE : payload_len); byte[] scratch = new byte[can_read]; // seek to given position and slurp in the payload @@ -75,33 +68,32 @@ public class Common { s.read(scratch); // skip vendor string in format: [LEN][VENDOR_STRING] - xoff += 4 + b2le32(scratch, xoff); // 4 = LEN = 32bit int + xoff += 4 + b2le32(scratch, xoff); // 4 = LEN = 32bit int comments = b2le32(scratch, xoff); - xoff += 4; + xoff += 4; // debug("comments count = "+comments); - for(int i=0; i scratch.length) + if (xoff > scratch.length) xdie("string out of bounds"); - String tag_raw = new String(scratch, xoff-clen, clen); - String[] tag_vec = tag_raw.split("=",2); - String tag_key = tag_vec[0].toUpperCase(); + String tag_raw = new String(scratch, xoff - clen, clen); + String[] tag_vec = tag_raw.split("=", 2); + String tag_key = tag_vec[0].toUpperCase(); addTagEntry(tags, tag_key, tag_vec[1]); } return tags; } - public void addTagEntry(HashMap tags, String key, String value) { - if(tags.containsKey(key)) { - ((Vector)tags.get(key)).add(value); // just add to existing vector - } - else { + void addTagEntry(HashMap tags, String key, String value) { + if (tags.containsKey(key)) { + ((Vector) tags.get(key)).add(value); // just add to existing vector + } else { Vector vx = new Vector(); vx.add(value); tags.put(key, vx); diff --git a/app/src/main/java/net/nullsum/audinaut/util/tags/FlacFile.java b/app/src/main/java/net/nullsum/audinaut/util/tags/FlacFile.java index 5793694..39605c4 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/tags/FlacFile.java +++ b/app/src/main/java/net/nullsum/audinaut/util/tags/FlacFile.java @@ -20,30 +20,29 @@ package net.nullsum.audinaut.util.tags; import java.io.IOException; import java.io.RandomAccessFile; import java.util.HashMap; -import java.util.Enumeration; -public class FlacFile extends Common { +class FlacFile extends Common { private static final int FLAC_TYPE_COMMENT = 4; // ID of 'VorbisComment's public FlacFile() { } public HashMap getTags(RandomAccessFile s) throws IOException { - int xoff = 4; // skip file magic + int xoff = 4; // skip file magic int retry = 64; int r[]; HashMap tags = new HashMap(); - for(; retry > 0; retry--) { + for (; retry > 0; retry--) { r = parse_metadata_block(s, xoff); - if(r[2] == FLAC_TYPE_COMMENT) { - tags = parse_vorbis_comment(s, xoff+r[0], r[1]); + if (r[2] == FLAC_TYPE_COMMENT) { + tags = parse_vorbis_comment(s, xoff + r[0], r[1]); break; } - if(r[3] != 0) + if (r[3] != 0) break; // eof reached // else: calculate next offset @@ -56,20 +55,20 @@ public class FlacFile extends Common { ** [header_size, payload_size, type, stop_after] */ private int[] parse_metadata_block(RandomAccessFile s, long offset) throws IOException { - int[] result = new int[4]; + int[] result = new int[4]; byte[] mb_head = new byte[4]; - int stop_after = 0; - int block_type = 0; - int block_size = 0; + int stop_after; + int block_type; + int block_size; s.seek(offset); - if( s.read(mb_head) != 4 ) + if (s.read(mb_head) != 4) xdie("failed to read metadata block header"); - block_size = b2be32(mb_head,0); // read whole header as 32 big endian + block_size = b2be32(mb_head, 0); // read whole header as 32 big endian block_type = (block_size >> 24) & 127; // BIT 1-7 are the type - stop_after = (((block_size >> 24) & 128) > 0 ? 1 : 0 ); // BIT 0 indicates the last-block flag + stop_after = (((block_size >> 24) & 128) > 0 ? 1 : 0); // BIT 0 indicates the last-block flag block_size = (block_size & 0x00FFFFFF); // byte 1-7 are the size // debug("size="+block_size+", type="+block_type+", is_last="+stop_after); diff --git a/app/src/main/java/net/nullsum/audinaut/util/tags/ID3v2File.java b/app/src/main/java/net/nullsum/audinaut/util/tags/ID3v2File.java index f643e39..bfbc20b 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/tags/ID3v2File.java +++ b/app/src/main/java/net/nullsum/audinaut/util/tags/ID3v2File.java @@ -24,17 +24,13 @@ import java.util.HashMap; import java.util.Locale; -public class ID3v2File extends Common { - private static int ID3_ENC_LATIN = 0x00; - private static int ID3_ENC_UTF16LE = 0x01; - private static int ID3_ENC_UTF16BE = 0x02; - private static int ID3_ENC_UTF8 = 0x03; +class ID3v2File extends Common { public ID3v2File() { } public HashMap getTags(RandomAccessFile s) throws IOException { - HashMap tags = new HashMap(); + HashMap tags; final int v2hdr_len = 10; byte[] v2hdr = new byte[v2hdr_len]; @@ -43,12 +39,11 @@ public class ID3v2File extends Common { s.seek(0); s.read(v2hdr); - int id3v = ((b2be32(v2hdr,0))) & 0xFF; // swapped ID3\04 -> ver. ist the first byte - int v3len = ((b2be32(v2hdr,6))); // total size EXCLUDING the this 10 byte header - v3len = ((v3len & 0x7f000000) >> 3) | // for some funky reason, this is encoded as 7*4 bits - ((v3len & 0x007f0000) >> 2) | - ((v3len & 0x00007f00) >> 1) | - ((v3len & 0x0000007f) >> 0) ; + int v3len = ((b2be32(v2hdr, 6))); // total size EXCLUDING the this 10 byte header + v3len = ((v3len & 0x7f000000) >> 3) | // for some funky reason, this is encoded as 7*4 bits + ((v3len & 0x007f0000) >> 2) | + ((v3len & 0x00007f00) >> 1) | + ((v3len & 0x0000007f)); // debug(">> tag version ID3v2."+id3v); // debug(">> LEN= "+v3len+" // "+v3len); @@ -56,34 +51,34 @@ public class ID3v2File extends Common { // we should already be at the first frame // so we can start the parsing right now tags = parse_v3_frames(s, v3len); - tags.put("_hdrlen", v3len+v2hdr_len); + tags.put("_hdrlen", v3len + v2hdr_len); return tags; } /* Parses all ID3v2 frames at the current position up until payload_len ** bytes were read */ - public HashMap parse_v3_frames(RandomAccessFile s, long payload_len) throws IOException { + private HashMap parse_v3_frames(RandomAccessFile s, long payload_len) throws IOException { HashMap tags = new HashMap(); - byte[] frame = new byte[10]; // a frame header is always 10 bytes - long bread = 0; // total amount of read bytes + byte[] frame = new byte[10]; // a frame header is always 10 bytes + long bread = 0; // total amount of read bytes - while(bread < payload_len) { + while (bread < payload_len) { bread += s.read(frame); String framename = new String(frame, 0, 4); int slen = b2be32(frame, 4); /* Abort on silly sizes */ - if(slen < 1 || slen > 524288) + if (slen < 1 || slen > 524288) break; byte[] xpl = new byte[slen]; bread += s.read(xpl); - if(framename.substring(0,1).equals("T")) { + if (framename.substring(0, 1).equals("T")) { String[] nmzInfo = normalizeTaginfo(framename, xpl); - for(int i = 0; i < nmzInfo.length; i += 2) { + for (int i = 0; i < nmzInfo.length; i += 2) { String oggKey = nmzInfo[i]; String decPld = nmzInfo[i + 1]; @@ -92,46 +87,41 @@ public class ID3v2File extends Common { } } } - else if(framename.equals("RVA2")) { - // - } - } return tags; } /* Converts ID3v2 sillyframes to OggNames */ private String[] normalizeTaginfo(String k, byte[] v) { - String[] rv = new String[] {"",""}; + String[] rv = new String[]{"", ""}; HashMap lu = new HashMap(); lu.put("TIT2", "TITLE"); lu.put("TALB", "ALBUM"); lu.put("TPE1", "ARTIST"); - if(lu.containsKey(k)) { + if (lu.containsKey(k)) { /* A normal, known key: translate into Ogg-Frame name */ - rv[0] = (String)lu.get(k); + rv[0] = (String) lu.get(k); rv[1] = getDecodedString(v); - } - else if(k.equals("TXXX")) { + } else if (k.equals("TXXX")) { /* A freestyle field, ieks! */ String txData[] = getDecodedString(v).split(Character.toString('\0'), 2); /* Check if we got replaygain info in key\0value style */ - if(txData.length == 2) { - if(txData[0].matches("^(?i)REPLAYGAIN_(ALBUM|TRACK)_GAIN$")) { + if (txData.length == 2) { + if (txData[0].matches("^(?i)REPLAYGAIN_(ALBUM|TRACK)_GAIN$")) { rv[0] = txData[0].toUpperCase(); /* some tagwriters use lowercase for this */ rv[1] = txData[1]; } else { // Check for replaygain tags just thrown randomly in field - int nextStartIndex = 1; + int nextStartIndex; int startName = txData[1].toLowerCase(Locale.US).indexOf("replaygain_"); - ArrayList parts = new ArrayList(); - while(startName != -1) { + ArrayList parts = new ArrayList<>(); + while (startName != -1) { int endName = txData[1].indexOf((char) 0, startName); - if(endName != -1) { + if (endName != -1) { parts.add(txData[1].substring(startName, endName).toUpperCase()); int endValue = txData[1].indexOf((char) 0, endName + 1); - if(endValue != -1) { + if (endValue != -1) { parts.add(txData[1].substring(endName + 1, endValue)); nextStartIndex = endValue + 1; } else { @@ -144,7 +134,7 @@ public class ID3v2File extends Common { startName = txData[1].toLowerCase(Locale.US).indexOf("replaygain_", nextStartIndex); } - if(parts.size() > 0) { + if (parts.size() > 0) { rv = new String[parts.size()]; rv = parts.toArray(rv); } @@ -158,22 +148,24 @@ public class ID3v2File extends Common { /* Converts a raw byte-stream text into a java String */ private String getDecodedString(byte[] raw) { int encid = raw[0] & 0xFF; - int len = raw.length; - String v = ""; + int len = raw.length; + String v = ""; try { - if(encid == ID3_ENC_LATIN) { - v = new String(raw, 1, len-1, "ISO-8859-1"); + int ID3_ENC_LATIN = 0x00; + int ID3_ENC_UTF8 = 0x03; + int ID3_ENC_UTF16BE = 0x02; + int ID3_ENC_UTF16LE = 0x01; + if (encid == ID3_ENC_LATIN) { + v = new String(raw, 1, len - 1, "ISO-8859-1"); + } else if (encid == ID3_ENC_UTF8) { + v = new String(raw, 1, len - 1, "UTF-8"); + } else if (encid == ID3_ENC_UTF16LE) { + v = new String(raw, 3, len - 3, "UTF-16LE"); + } else if (encid == ID3_ENC_UTF16BE) { + v = new String(raw, 3, len - 3, "UTF-16BE"); } - else if (encid == ID3_ENC_UTF8) { - v = new String(raw, 1, len-1, "UTF-8"); - } - else if (encid == ID3_ENC_UTF16LE) { - v = new String(raw, 3, len-3, "UTF-16LE"); - } - else if (encid == ID3_ENC_UTF16BE) { - v = new String(raw, 3, len-3, "UTF-16BE"); - } - } catch(Exception e) {} + } catch (Exception ignored) { + } return v; } diff --git a/app/src/main/java/net/nullsum/audinaut/util/tags/LameHeader.java b/app/src/main/java/net/nullsum/audinaut/util/tags/LameHeader.java index d23f892..fed0fd3 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/tags/LameHeader.java +++ b/app/src/main/java/net/nullsum/audinaut/util/tags/LameHeader.java @@ -20,10 +20,9 @@ package net.nullsum.audinaut.util.tags; import java.io.IOException; import java.io.RandomAccessFile; import java.util.HashMap; -import java.util.Enumeration; -public class LameHeader extends Common { +class LameHeader extends Common { public LameHeader() { } @@ -41,25 +40,25 @@ public class LameHeader extends Common { String lameMark = new String(chunk, 0, chunk.length, "ISO-8859-1"); - if(lameMark.equals("Info") || lameMark.equals("Xing")) { - s.seek(offset+0xAB); + if (lameMark.equals("Info") || lameMark.equals("Xing")) { + s.seek(offset + 0xAB); s.read(chunk); int raw = b2be32(chunk, 0); int gtrk_raw = raw >> 16; /* first 16 bits are the raw track gain value */ int galb_raw = raw & 0xFFFF; /* the rest is for the album gain value */ - float gtrk_val = (float)(gtrk_raw & 0x01FF)/10; - float galb_val = (float)(galb_raw & 0x01FF)/10; + float gtrk_val = (float) (gtrk_raw & 0x01FF) / 10; + float galb_val = (float) (galb_raw & 0x01FF) / 10; - gtrk_val = ((gtrk_raw&0x0200)!=0 ? -1*gtrk_val : gtrk_val); - galb_val = ((galb_raw&0x0200)!=0 ? -1*galb_val : galb_val); + gtrk_val = ((gtrk_raw & 0x0200) != 0 ? -1 * gtrk_val : gtrk_val); + galb_val = ((galb_raw & 0x0200) != 0 ? -1 * galb_val : galb_val); - if( (gtrk_raw&0xE000) == 0x2000 ) { - addTagEntry(tags, "REPLAYGAIN_TRACK_GAIN", gtrk_val+" dB"); + if ((gtrk_raw & 0xE000) == 0x2000) { + addTagEntry(tags, "REPLAYGAIN_TRACK_GAIN", gtrk_val + " dB"); } - if( (gtrk_raw&0xE000) == 0x4000 ) { - addTagEntry(tags, "REPLAYGAIN_ALBUM_GAIN", galb_val+" dB"); + if ((gtrk_raw & 0xE000) == 0x4000) { + addTagEntry(tags, "REPLAYGAIN_ALBUM_GAIN", galb_val + " dB"); } } diff --git a/app/src/main/java/net/nullsum/audinaut/util/tags/OggFile.java b/app/src/main/java/net/nullsum/audinaut/util/tags/OggFile.java index 847c1b2..4e93044 100644 --- a/app/src/main/java/net/nullsum/audinaut/util/tags/OggFile.java +++ b/app/src/main/java/net/nullsum/audinaut/util/tags/OggFile.java @@ -23,9 +23,9 @@ import java.io.RandomAccessFile; import java.util.HashMap; -public class OggFile extends Common { +class OggFile extends Common { - private static final int OGG_PAGE_SIZE = 27; // Static size of an OGG Page + private static final int OGG_PAGE_SIZE = 27; // Static size of an OGG Page private static final int OGG_TYPE_COMMENT = 3; // ID of 'VorbisComment's public OggFile() { @@ -33,13 +33,13 @@ public class OggFile extends Common { public HashMap getTags(RandomAccessFile s) throws IOException { long offset = 0; - int retry = 64; + int retry = 64; HashMap tags = new HashMap(); - for( ; retry > 0 ; retry-- ) { + for (; retry > 0; retry--) { long res[] = parse_ogg_page(s, offset); - if(res[2] == OGG_TYPE_COMMENT) { - tags = parse_ogg_vorbis_comment(s, offset+res[0], res[1]); + if (res[2] == OGG_TYPE_COMMENT) { + tags = parse_ogg_vorbis_comment(s, offset + res[0], res[1]); break; } offset += res[0] + res[1]; @@ -52,29 +52,29 @@ public class OggFile extends Common { ** [header_size, payload_size, type] */ private long[] parse_ogg_page(RandomAccessFile s, long offset) throws IOException { - long[] result = new long[3]; // [header_size, payload_size] + long[] result = new long[3]; // [header_size, payload_size] byte[] p_header = new byte[OGG_PAGE_SIZE]; // buffer for the page header byte[] scratch; - int bread = 0; // number of bytes read - int psize = 0; // payload-size - int nsegs = 0; // Number of segments + int bread; // number of bytes read + int psize = 0; // payload-size + int nsegs; // Number of segments s.seek(offset); bread = s.read(p_header); - if(bread != OGG_PAGE_SIZE) + if (bread != OGG_PAGE_SIZE) xdie("Unable to read() OGG_PAGE_HEADER"); - if((new String(p_header, 0, 5)).equals("OggS\0") != true) + if (!(new String(p_header, 0, 5)).equals("OggS\0")) xdie("Invalid magic - not an ogg file?"); nsegs = b2u(p_header[26]); // debug("> file seg: "+nsegs); - if(nsegs > 0) { - scratch = new byte[nsegs]; - bread = s.read(scratch); - if(bread != nsegs) + if (nsegs > 0) { + scratch = new byte[nsegs]; + bread = s.read(scratch); + if (bread != nsegs) xdie("Failed to read segtable"); - for(int i=0; i pre-read */ - if(psize >= 1 && s.read(p_header, 0, 1) == 1) { + if (psize >= 1 && s.read(p_header, 0, 1) == 1) { result[2] = b2u(p_header[0]); } @@ -97,18 +97,18 @@ public class OggFile extends Common { ** parset with the correct offset (+7) */ private HashMap parse_ogg_vorbis_comment(RandomAccessFile s, long offset, long pl_len) throws IOException { final int pfx_len = 7; - byte[] pfx = new byte[pfx_len]; + byte[] pfx = new byte[pfx_len]; - if(pl_len < pfx_len) + if (pl_len < pfx_len) xdie("ogg vorbis comment field is too short!"); s.seek(offset); s.read(pfx); - if( (new String(pfx, 0, pfx_len)).equals("\3vorbis") == false ) + if (!(new String(pfx, 0, pfx_len)).equals("\3vorbis")) xdie("Damaged packet found!"); - return parse_vorbis_comment(s, offset+pfx_len, pl_len-pfx_len); + return parse_vorbis_comment(s, offset + pfx_len, pl_len - pfx_len); } -}; +} diff --git a/app/src/main/java/net/nullsum/audinaut/view/AlbumView.java b/app/src/main/java/net/nullsum/audinaut/view/AlbumView.java index faca80d..d6ec271 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/AlbumView.java +++ b/app/src/main/java/net/nullsum/audinaut/view/AlbumView.java @@ -21,10 +21,8 @@ package net.nullsum.audinaut.view; import android.content.Context; import android.view.LayoutInflater; -import android.view.View; -import android.widget.ImageButton; -import android.widget.ImageView; import android.widget.TextView; + import net.nullsum.audinaut.R; import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.util.FileUtil; @@ -34,28 +32,27 @@ import net.nullsum.audinaut.util.Util; import java.io.File; public class AlbumView extends UpdateView2 { - private static final String TAG = AlbumView.class.getSimpleName(); + private final TextView titleView; + private final TextView artistView; private File file; - private TextView titleView; - private TextView artistView; private boolean showArtist = true; private String coverArtId; public AlbumView(Context context, boolean cell) { - super(context); + super(context, true); - if(cell) { + if (cell) { LayoutInflater.from(context).inflate(R.layout.album_cell_item, this, true); } else { LayoutInflater.from(context).inflate(R.layout.album_list_item, this, true); } coverArtView = findViewById(R.id.album_coverart); - titleView = (TextView) findViewById(R.id.album_title); - artistView = (TextView) findViewById(R.id.album_artist); + titleView = findViewById(R.id.album_title); + artistView = findViewById(R.id.album_artist); - moreButton = (ImageView) findViewById(R.id.item_more); + moreButton = findViewById(R.id.item_more); checkable = true; } @@ -67,7 +64,7 @@ public class AlbumView extends UpdateView2 { protected void setObjectImpl(MusicDirectory.Entry album, ImageLoader imageLoader) { titleView.setText(album.getAlbumDisplay()); String artist = ""; - if(showArtist) { + if (showArtist) { artist = album.getArtist(); if (artist == null) { artist = ""; @@ -75,7 +72,7 @@ public class AlbumView extends UpdateView2 { if (album.getYear() != null) { artist += " - " + album.getYear(); } - } else if(album.getYear() != null) { + } else if (album.getYear() != null) { artist += album.getYear(); } artistView.setText(album.getArtist() == null ? "" : artist); @@ -83,14 +80,14 @@ public class AlbumView extends UpdateView2 { file = null; } - public void onUpdateImageView() { + void onUpdateImageView() { imageTask = item2.loadImage(coverArtView, item, false, true); coverArtId = item.getCoverArt(); } @Override protected void updateBackground() { - if(file == null) { + if (file == null) { file = FileUtil.getAlbumDirectory(context, item); } @@ -101,7 +98,7 @@ public class AlbumView extends UpdateView2 { public void update() { super.update(); - if(!Util.equals(item.getCoverArt(), coverArtId)) { + if (!Util.equals(item.getCoverArt(), coverArtId)) { onUpdateImageView(); } } diff --git a/app/src/main/java/net/nullsum/audinaut/view/ArtistEntryView.java b/app/src/main/java/net/nullsum/audinaut/view/ArtistEntryView.java index 41c4605..8e60a64 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/ArtistEntryView.java +++ b/app/src/main/java/net/nullsum/audinaut/view/ArtistEntryView.java @@ -21,36 +21,31 @@ package net.nullsum.audinaut.view; import android.content.Context; import android.view.LayoutInflater; import android.view.View; -import android.widget.ImageButton; -import android.widget.ImageView; import android.widget.TextView; + import net.nullsum.audinaut.R; import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.util.FileUtil; import java.io.File; + /** * Used to display albums in a {@code ListView}. * * @author Sindre Mehus */ public class ArtistEntryView extends UpdateView { - private static final String TAG = ArtistEntryView.class.getSimpleName(); + private final TextView titleView; private File file; - private TextView titleView; public ArtistEntryView(Context context) { - super(context); + super(context, true); LayoutInflater.from(context).inflate(R.layout.basic_list_item, this, true); - titleView = (TextView) findViewById(R.id.item_name); - moreButton = (ImageView) findViewById(R.id.item_more); - moreButton.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - v.showContextMenu(); - } - }); + titleView = findViewById(R.id.item_name); + moreButton = findViewById(R.id.item_more); + moreButton.setOnClickListener(View::showContextMenu); } protected void setObjectImpl(MusicDirectory.Entry artist) { diff --git a/app/src/main/java/net/nullsum/audinaut/view/ArtistView.java b/app/src/main/java/net/nullsum/audinaut/view/ArtistView.java index 9cd2851..578e845 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/ArtistView.java +++ b/app/src/main/java/net/nullsum/audinaut/view/ArtistView.java @@ -21,9 +21,8 @@ package net.nullsum.audinaut.view; import android.content.Context; import android.view.LayoutInflater; import android.view.View; -import android.widget.ImageButton; -import android.widget.ImageView; import android.widget.TextView; + import net.nullsum.audinaut.R; import net.nullsum.audinaut.domain.Artist; import net.nullsum.audinaut.util.FileUtil; @@ -36,22 +35,17 @@ import java.io.File; * @author Sindre Mehus */ public class ArtistView extends UpdateView { - private static final String TAG = ArtistView.class.getSimpleName(); + private final TextView titleView; private File file; - private TextView titleView; public ArtistView(Context context) { - super(context); + super(context, true); LayoutInflater.from(context).inflate(R.layout.basic_list_item, this, true); - titleView = (TextView) findViewById(R.id.item_name); - moreButton = (ImageView) findViewById(R.id.item_more); - moreButton.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - v.showContextMenu(); - } - }); + titleView = findViewById(R.id.item_name); + moreButton = findViewById(R.id.item_more); + moreButton.setOnClickListener(View::showContextMenu); } protected void setObjectImpl(Artist artist) { diff --git a/app/src/main/java/net/nullsum/audinaut/view/AutoRepeatButton.java b/app/src/main/java/net/nullsum/audinaut/view/AutoRepeatButton.java index 0ce4113..52c55ad 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/AutoRepeatButton.java +++ b/app/src/main/java/net/nullsum/audinaut/view/AutoRepeatButton.java @@ -4,7 +4,6 @@ import android.content.Context; import android.support.v7.widget.AppCompatImageButton; import android.util.AttributeSet; import android.view.MotionEvent; -import android.view.View; public class AutoRepeatButton extends AppCompatImageButton { @@ -13,13 +12,13 @@ public class AutoRepeatButton extends AppCompatImageButton { private boolean doClick = true; private Runnable repeatEvent = null; - private Runnable repeatClickWhileButtonHeldRunnable = new Runnable() { + private final Runnable repeatClickWhileButtonHeldRunnable = new Runnable() { @Override public void run() { doClick = false; //Perform the present repetition of the click action provided by the user // in setOnClickListener(). - if(repeatEvent != null) + if (repeatEvent != null) repeatEvent.run(); //Schedule the next repetitions of the click action, using a faster repeat @@ -28,52 +27,11 @@ public class AutoRepeatButton extends AppCompatImageButton { } }; - private void commonConstructorCode() { - this.setOnTouchListener(new OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - int action = event.getAction(); - if(action == MotionEvent.ACTION_DOWN) - { - doClick = true; - //Just to be sure that we removed all callbacks, - // which should have occurred in the ACTION_UP - removeCallbacks(repeatClickWhileButtonHeldRunnable); - - //Schedule the start of repetitions after a one half second delay. - postDelayed(repeatClickWhileButtonHeldRunnable, initialRepeatDelay); - - setPressed(true); - } - else if(action == MotionEvent.ACTION_UP) { - //Cancel any repetition in progress. - removeCallbacks(repeatClickWhileButtonHeldRunnable); - - if(doClick || repeatEvent == null) { - performClick(); - } - - setPressed(false); - } - - //Returning true here prevents performClick() from getting called - // in the usual manner, which would be redundant, given that we are - // already calling it above. - return true; - } - }); - } - - public void setOnRepeatListener(Runnable runnable) { - repeatEvent = runnable; - } - public AutoRepeatButton(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); commonConstructorCode(); } - public AutoRepeatButton(Context context, AttributeSet attrs) { super(context, attrs); commonConstructorCode(); @@ -83,4 +41,39 @@ public class AutoRepeatButton extends AppCompatImageButton { super(context); commonConstructorCode(); } + + private void commonConstructorCode() { + this.setOnTouchListener((v, event) -> { + int action = event.getAction(); + if (action == MotionEvent.ACTION_DOWN) { + doClick = true; + //Just to be sure that we removed all callbacks, + // which should have occurred in the ACTION_UP + removeCallbacks(repeatClickWhileButtonHeldRunnable); + + //Schedule the start of repetitions after a one half second delay. + postDelayed(repeatClickWhileButtonHeldRunnable, initialRepeatDelay); + + setPressed(true); + } else if (action == MotionEvent.ACTION_UP) { + //Cancel any repetition in progress. + removeCallbacks(repeatClickWhileButtonHeldRunnable); + + if (doClick || repeatEvent == null) { + performClick(); + } + + setPressed(false); + } + + //Returning true here prevents performClick() from getting called + // in the usual manner, which would be redundant, given that we are + // already calling it above. + return true; + }); + } + + public void setOnRepeatListener(Runnable runnable) { + repeatEvent = runnable; + } } diff --git a/app/src/main/java/net/nullsum/audinaut/view/BasicHeaderView.java b/app/src/main/java/net/nullsum/audinaut/view/BasicHeaderView.java index 0454b5e..9bbb610 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/BasicHeaderView.java +++ b/app/src/main/java/net/nullsum/audinaut/view/BasicHeaderView.java @@ -22,16 +22,17 @@ import android.widget.TextView; import net.nullsum.audinaut.R; public class BasicHeaderView extends UpdateView { - TextView nameView; + private final TextView nameView; public BasicHeaderView(Context context) { this(context, R.layout.basic_header); } + public BasicHeaderView(Context context, int layout) { super(context, false); LayoutInflater.from(context).inflate(layout, this, true); - nameView = (TextView) findViewById(R.id.item_name); + nameView = findViewById(R.id.item_name); } protected void setObjectImpl(String string) { diff --git a/app/src/main/java/net/nullsum/audinaut/view/BasicListView.java b/app/src/main/java/net/nullsum/audinaut/view/BasicListView.java index c908c1a..feb84df 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/BasicListView.java +++ b/app/src/main/java/net/nullsum/audinaut/view/BasicListView.java @@ -18,21 +18,19 @@ package net.nullsum.audinaut.view; import android.content.Context; import android.view.LayoutInflater; import android.view.View; -import android.widget.ImageButton; -import android.widget.ImageView; import android.widget.TextView; import net.nullsum.audinaut.R; public class BasicListView extends UpdateView { - private TextView titleView; + private final TextView titleView; public BasicListView(Context context) { super(context, false); LayoutInflater.from(context).inflate(R.layout.basic_list_item, this, true); - titleView = (TextView) findViewById(R.id.item_name); - moreButton = (ImageView) findViewById(R.id.item_more); + titleView = findViewById(R.id.item_name); + moreButton = findViewById(R.id.item_more); moreButton.setVisibility(View.GONE); } diff --git a/app/src/main/java/net/nullsum/audinaut/view/CacheLocationPreference.java b/app/src/main/java/net/nullsum/audinaut/view/CacheLocationPreference.java index d511655..3da78ca 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/CacheLocationPreference.java +++ b/app/src/main/java/net/nullsum/audinaut/view/CacheLocationPreference.java @@ -17,7 +17,6 @@ package net.nullsum.audinaut.view; import android.content.Context; import android.os.Build; import android.os.Environment; -import android.preference.DialogPreference; import android.preference.EditTextPreference; import android.support.v4.content.ContextCompat; import android.util.AttributeSet; @@ -28,25 +27,25 @@ import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; -import android.widget.TextView; + +import net.nullsum.audinaut.R; import java.io.File; -import net.nullsum.audinaut.R; -import net.nullsum.audinaut.util.FileUtil; - public class CacheLocationPreference extends EditTextPreference { private static final String TAG = CacheLocationPreference.class.getSimpleName(); - private Context context; + private final Context context; public CacheLocationPreference(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.context = context; } + public CacheLocationPreference(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; } + public CacheLocationPreference(Context context) { super(context); this.context = context; @@ -58,15 +57,15 @@ public class CacheLocationPreference extends EditTextPreference { view.setLayoutParams(new ViewGroup.LayoutParams(android.view.ViewGroup.LayoutParams.WRAP_CONTENT, android.view.ViewGroup.LayoutParams.WRAP_CONTENT)); - final EditText editText = (EditText) view.findViewById(android.R.id.edit); + final EditText editText = view.findViewById(android.R.id.edit); ViewGroup vg = (ViewGroup) editText.getParent(); LinearLayout cacheButtonsWrapper = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.cache_location_buttons, vg, true); - Button internalLocation = (Button) cacheButtonsWrapper.findViewById(R.id.location_internal); - Button externalLocation = (Button) cacheButtonsWrapper.findViewById(R.id.location_external); + Button internalLocation = cacheButtonsWrapper.findViewById(R.id.location_internal); + Button externalLocation = cacheButtonsWrapper.findViewById(R.id.location_external); File[] dirs; - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { dirs = context.getExternalMediaDirs(); } else { dirs = ContextCompat.getExternalFilesDirs(context, null); @@ -74,19 +73,19 @@ public class CacheLocationPreference extends EditTextPreference { // Past 5.0 we can query directly for SD Card File internalDir = null, externalDir = null; - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - for(int i = 0; i < dirs.length; i++) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + for (File dir : dirs) { try { - if (dirs[i] != null) { - if(Environment.isExternalStorageRemovable(dirs[i])) { - if(externalDir != null) { - externalDir = dirs[i]; + if (dir != null) { + if (Environment.isExternalStorageRemovable(dir)) { + if (externalDir != null) { + externalDir = dir; } } else { - internalDir = dirs[i]; + internalDir = dir; } - if(internalDir != null && externalDir != null) { + if (internalDir != null && externalDir != null) { break; } } @@ -97,7 +96,7 @@ public class CacheLocationPreference extends EditTextPreference { } // Before 5.0, we have to guess. Most of the time the SD card is last - if(externalDir == null) { + if (externalDir == null) { for (int i = dirs.length - 1; i >= 0; i--) { if (dirs[i] != null) { externalDir = dirs[i]; @@ -105,10 +104,10 @@ public class CacheLocationPreference extends EditTextPreference { } } } - if(internalDir == null) { - for (int i = 0; i < dirs.length; i++) { - if (dirs[i] != null) { - internalDir = dirs[i]; + if (internalDir == null) { + for (File dir : dirs) { + if (dir != null) { + internalDir = dir; break; } } @@ -116,25 +115,19 @@ public class CacheLocationPreference extends EditTextPreference { final File finalInternalDir = new File(internalDir, "music"); final File finalExternalDir = new File(externalDir, "music"); - if(finalInternalDir != null && (finalInternalDir.exists() || finalInternalDir.mkdirs())) { - internalLocation.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - String path = finalInternalDir.getPath(); - editText.setText(path); - } + if (finalInternalDir != null && (finalInternalDir.exists() || finalInternalDir.mkdirs())) { + internalLocation.setOnClickListener(v -> { + String path = finalInternalDir.getPath(); + editText.setText(path); }); } else { internalLocation.setEnabled(false); } - if(finalExternalDir != null && !finalInternalDir.equals(finalExternalDir) && (finalExternalDir.exists() || finalExternalDir.mkdirs())) { - externalLocation.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - String path = finalExternalDir.getPath(); - editText.setText(path); - } + if (finalExternalDir != null && !finalInternalDir.equals(finalExternalDir) && (finalExternalDir.exists() || finalExternalDir.mkdirs())) { + externalLocation.setOnClickListener(v -> { + String path = finalExternalDir.getPath(); + editText.setText(path); }); } else { externalLocation.setEnabled(false); diff --git a/app/src/main/java/net/nullsum/audinaut/view/CardView.java b/app/src/main/java/net/nullsum/audinaut/view/CardView.java index 4f69c2f..4bb6d2a 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/CardView.java +++ b/app/src/main/java/net/nullsum/audinaut/view/CardView.java @@ -7,13 +7,12 @@ import android.graphics.RectF; import android.os.Build; import android.util.AttributeSet; import android.util.Log; -import android.view.View; import android.widget.FrameLayout; import net.nullsum.audinaut.R; import net.nullsum.audinaut.util.DrawableTint; -public class CardView extends FrameLayout{ +public class CardView extends FrameLayout { private static final String TAG = CardView.class.getSimpleName(); public CardView(Context context) { @@ -31,7 +30,7 @@ public class CardView extends FrameLayout{ init(context); } - public CardView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + private CardView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(context); } @@ -43,7 +42,7 @@ public class CardView extends FrameLayout{ float roundedDp = getResources().getDimension(R.dimen.Card_Radius); clipPath.addRoundRect(new RectF(canvas.getClipBounds()), roundedDp, roundedDp, Path.Direction.CW); canvas.clipPath(clipPath); - } catch(Exception e) { + } catch (Exception e) { Log.e(TAG, "Failed to clip path on canvas", e); } super.onDraw(canvas); @@ -52,7 +51,7 @@ public class CardView extends FrameLayout{ private void init(Context context) { setClipChildren(true); setBackgroundResource(DrawableTint.getDrawableRes(context, R.attr.cardBackgroundDrawable)); - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { setElevation(getResources().getInteger(R.integer.Card_Elevation)); } } diff --git a/app/src/main/java/net/nullsum/audinaut/view/ErrorDialog.java b/app/src/main/java/net/nullsum/audinaut/view/ErrorDialog.java index 4447f57..9c81077 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/ErrorDialog.java +++ b/app/src/main/java/net/nullsum/audinaut/view/ErrorDialog.java @@ -19,9 +19,8 @@ package net.nullsum.audinaut.view; import android.app.Activity; -import android.support.v7.app.AlertDialog; -import android.content.DialogInterface; import android.content.Intent; +import android.support.v7.app.AlertDialog; import net.nullsum.audinaut.R; import net.nullsum.audinaut.activity.SubsonicFragmentActivity; @@ -32,8 +31,8 @@ import net.nullsum.audinaut.util.Util; */ public class ErrorDialog { - public ErrorDialog(Activity activity, int messageId, boolean finishActivityOnCancel) { - this(activity, activity.getResources().getString(messageId), finishActivityOnCancel); + public ErrorDialog(Activity activity, int messageId) { + this(activity, activity.getResources().getString(messageId), false); } public ErrorDialog(final Activity activity, String message, final boolean finishActivityOnClose) { @@ -43,26 +42,20 @@ public class ErrorDialog { builder.setTitle(R.string.error_label); builder.setMessage(message); builder.setCancelable(true); - builder.setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialogInterface) { - if (finishActivityOnClose) { - restart(activity); - } + builder.setOnCancelListener(dialogInterface -> { + if (finishActivityOnClose) { + restart(activity); } }); - builder.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - if (finishActivityOnClose) { - restart(activity); - } + builder.setPositiveButton(R.string.common_ok, (dialogInterface, i) -> { + if (finishActivityOnClose) { + restart(activity); } }); try { builder.create().show(); - } catch(Exception e) { + } catch (Exception e) { // Don't care, just means no activity to attach to } } diff --git a/app/src/main/java/net/nullsum/audinaut/view/FadeOutAnimation.java b/app/src/main/java/net/nullsum/audinaut/view/FadeOutAnimation.java index 4bdc1df..cbf2edf 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/FadeOutAnimation.java +++ b/app/src/main/java/net/nullsum/audinaut/view/FadeOutAnimation.java @@ -32,6 +32,24 @@ public class FadeOutAnimation extends AlphaAnimation { private boolean cancelled; + private FadeOutAnimation(final View view, long durationMillis) { + super(1.0F, 0.0F); + setDuration(durationMillis); + setAnimationListener(new AnimationListener() { + public void onAnimationStart(Animation animation) { + } + + public void onAnimationRepeat(Animation animation) { + } + + public void onAnimationEnd(Animation animation) { + if (!cancelled) { + view.setVisibility(View.INVISIBLE); + } + } + }); + } + /** * Creates and starts the fade out animation. * @@ -53,24 +71,6 @@ public class FadeOutAnimation extends AlphaAnimation { } } - FadeOutAnimation(final View view, long durationMillis) { - super(1.0F, 0.0F); - setDuration(durationMillis); - setAnimationListener(new AnimationListener() { - public void onAnimationStart(Animation animation) { - } - - public void onAnimationRepeat(Animation animation) { - } - - public void onAnimationEnd(Animation animation) { - if (!cancelled) { - view.setVisibility(View.INVISIBLE); - } - } - }); - } - private void cancelFadeOut() { cancelled = true; } diff --git a/app/src/main/java/net/nullsum/audinaut/view/FastScroller.java b/app/src/main/java/net/nullsum/audinaut/view/FastScroller.java index 9cf9b2d..ef31a21 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/FastScroller.java +++ b/app/src/main/java/net/nullsum/audinaut/view/FastScroller.java @@ -17,11 +17,9 @@ package net.nullsum.audinaut.view; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; import android.support.annotation.NonNull; -import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.AdapterDataObserver; @@ -41,12 +39,10 @@ import static android.support.v7.widget.RecyclerView.OnScrollListener; public class FastScroller extends LinearLayout { private static final String TAG = FastScroller.class.getSimpleName(); private static final int BUBBLE_ANIMATION_DURATION = 100; - private static final int TRACK_SNAP_RANGE = 5; - + private final ScrollListener scrollListener = new ScrollListener(); private TextView bubble; private View handle; private RecyclerView recyclerView; - private final ScrollListener scrollListener = new ScrollListener(); private int height; private int visibleRange = -1; private RecyclerView.Adapter adapter; @@ -56,8 +52,8 @@ public class FastScroller extends LinearLayout { private ObjectAnimator currentAnimator = null; - public FastScroller(final Context context,final AttributeSet attrs,final int defStyleAttr) { - super(context,attrs,defStyleAttr); + public FastScroller(final Context context, final AttributeSet attrs, final int defStyleAttr) { + super(context, attrs, defStyleAttr); initialise(context); } @@ -66,7 +62,7 @@ public class FastScroller extends LinearLayout { initialise(context); } - public FastScroller(final Context context,final AttributeSet attrs) { + public FastScroller(final Context context, final AttributeSet attrs) { super(context, attrs); initialise(context); } @@ -75,16 +71,16 @@ public class FastScroller extends LinearLayout { setOrientation(HORIZONTAL); setClipChildren(false); LayoutInflater inflater = LayoutInflater.from(context); - inflater.inflate(R.layout.fast_scroller,this,true); - bubble = (TextView)findViewById(R.id.fastscroller_bubble); + inflater.inflate(R.layout.fast_scroller, this, true); + bubble = findViewById(R.id.fastscroller_bubble); handle = findViewById(R.id.fastscroller_handle); bubble.setVisibility(INVISIBLE); setVisibility(GONE); } @Override - protected void onSizeChanged(int w,int h,int oldw,int oldh) { - super.onSizeChanged(w,h,oldw,oldh); + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); height = h; visibleRange = -1; } @@ -92,20 +88,19 @@ public class FastScroller extends LinearLayout { @Override public boolean onTouchEvent(@NonNull MotionEvent event) { final int action = event.getAction(); - switch(action) - { + switch (action) { case MotionEvent.ACTION_DOWN: - if(event.getX() < (handle.getX() - 30)) { + if (event.getX() < (handle.getX() - 30)) { return false; } - if(currentAnimator != null) + if (currentAnimator != null) currentAnimator.cancel(); - if(bubble.getVisibility() == INVISIBLE) { - if(visibleBubble) { + if (bubble.getVisibility() == INVISIBLE) { + if (visibleBubble) { showBubble(); } - } else if(!visibleBubble) { + } else if (!visibleBubble) { hideBubble(); } handle.setSelected(true); @@ -127,27 +122,21 @@ public class FastScroller extends LinearLayout { registerAdapter(); visibleRange = -1; } - public void detachRecyclerView() { - recyclerView.removeOnScrollListener(scrollListener); - recyclerView.setVerticalScrollBarEnabled(true); - unregisterAdapter(); - recyclerView = null; - setVisibility(View.GONE); - } + public boolean isAttached() { return recyclerView != null; } private void setRecyclerViewPosition(float y) { - if(recyclerView != null) { - if(recyclerView.getChildCount() == 0) { + if (recyclerView != null) { + if (recyclerView.getChildCount() == 0) { return; } int itemCount = recyclerView.getAdapter().getItemCount(); - float proportion = getValueInRange(0, 1f, y / (float) height); + float proportion = getValueInRange(1f, y / (float) height); - float targetPosFloat = getValueInRange(0, itemCount - 1, proportion * (float)itemCount); + float targetPosFloat = getValueInRange(itemCount - 1, proportion * (float) itemCount); int targetPos = (int) targetPosFloat; // Immediately make sure that the target is visible @@ -157,14 +146,14 @@ public class FastScroller extends LinearLayout { // Calculate how far through this position we are int columns = Math.round(recyclerView.getWidth() / firstVisibleView.getWidth()); - int firstVisiblePosition = recyclerView.getChildPosition(firstVisibleView); + int firstVisiblePosition = recyclerView.getChildAdapterPosition(firstVisibleView); int remainder = (targetPos - firstVisiblePosition) % columns; float offsetPercentage = (targetPosFloat - targetPos + remainder) / columns; - if(offsetPercentage < 0) { + if (offsetPercentage < 0) { offsetPercentage = 1 + offsetPercentage; } int firstVisibleHeight = firstVisibleView.getHeight(); - if(columns > 1) { + if (columns > 1) { firstVisibleHeight += (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, GridSpacingDecoration.SPACING, firstVisibleView.getResources().getDisplayMetrics()); } int offset = (int) (offsetPercentage * firstVisibleHeight); @@ -175,11 +164,11 @@ public class FastScroller extends LinearLayout { try { String bubbleText = null; RecyclerView.Adapter adapter = recyclerView.getAdapter(); - if(adapter instanceof BubbleTextGetter) { + if (adapter instanceof BubbleTextGetter) { bubbleText = ((BubbleTextGetter) adapter).getTextToShowInBubble(targetPos); } - if(bubbleText == null) { + if (bubbleText == null) { visibleBubble = false; bubble.setVisibility(View.INVISIBLE); } else { @@ -187,37 +176,37 @@ public class FastScroller extends LinearLayout { bubble.setVisibility(View.VISIBLE); visibleBubble = true; } - } catch(Exception e) { + } catch (Exception e) { Log.e(TAG, "Error getting text for bubble", e); } } } - private float getValueInRange(float min, float max, float value) { - float minimum = Math.max(min, value); - return Math.min(minimum,max); + private float getValueInRange(float max, float value) { + float minimum = Math.max((float) 0, value); + return Math.min(minimum, max); } private void setBubbleAndHandlePosition(float y) { int bubbleHeight = bubble.getHeight(); int handleHeight = handle.getHeight(); - handle.setY(getValueInRange(0,height-handleHeight,(int)(y-handleHeight/2))); - bubble.setY(getValueInRange(0, height - bubbleHeight - handleHeight / 2, (int) (y - bubbleHeight))); + handle.setY(getValueInRange(height - handleHeight, (int) (y - handleHeight / 2))); + bubble.setY(getValueInRange(height - bubbleHeight - handleHeight / 2, (int) (y - bubbleHeight))); } private void showBubble() { bubble.setVisibility(VISIBLE); - if(currentAnimator != null) + if (currentAnimator != null) currentAnimator.cancel(); - currentAnimator = ObjectAnimator.ofFloat(bubble,"alpha",0f,1f).setDuration(BUBBLE_ANIMATION_DURATION); + currentAnimator = ObjectAnimator.ofFloat(bubble, "alpha", 0f, 1f).setDuration(BUBBLE_ANIMATION_DURATION); currentAnimator.start(); } private void hideBubble() { - if(currentAnimator != null) + if (currentAnimator != null) currentAnimator.cancel(); - currentAnimator = ObjectAnimator.ofFloat(bubble,"alpha",1f,0f).setDuration(BUBBLE_ANIMATION_DURATION); - currentAnimator.addListener(new AnimatorListenerAdapter(){ + currentAnimator = ObjectAnimator.ofFloat(bubble, "alpha", 1f, 0f).setDuration(BUBBLE_ANIMATION_DURATION); + currentAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); @@ -237,11 +226,11 @@ public class FastScroller extends LinearLayout { private void registerAdapter() { RecyclerView.Adapter newAdapter = recyclerView.getAdapter(); - if(newAdapter != adapter) { + if (newAdapter != adapter) { unregisterAdapter(); } - if(newAdapter != null) { + if (newAdapter != null) { adapterObserver = new AdapterDataObserver() { @Override public void onChanged() { @@ -272,36 +261,30 @@ public class FastScroller extends LinearLayout { adapter = newAdapter; } } + private void unregisterAdapter() { - if(adapter != null) { + if (adapter != null) { adapter.unregisterAdapterDataObserver(adapterObserver); adapter = null; adapterObserver = null; } } - private class ScrollListener extends OnScrollListener { - @Override - public void onScrolled(RecyclerView rv,int dx,int dy) { - onUpdateScroll(dx, dy); - } - } - private void onUpdateScroll(int dx, int dy) { - if(recyclerView.getWidth() == 0) { + if (recyclerView.getWidth() == 0) { return; } registerAdapter(); View firstVisibleView = recyclerView.getChildAt(0); - if(firstVisibleView == null) { + if (firstVisibleView == null) { return; } - int firstVisiblePosition = recyclerView.getChildPosition(firstVisibleView); + int firstVisiblePosition = recyclerView.getChildAdapterPosition(firstVisibleView); int itemCount = recyclerView.getAdapter().getItemCount(); int columns = Math.round(recyclerView.getWidth() / firstVisibleView.getWidth()); - if(visibleRange == -1) { + if (visibleRange == -1) { visibleRange = recyclerView.getChildCount(); } @@ -316,13 +299,13 @@ public class FastScroller extends LinearLayout { float proportion = position / itemCount; setBubbleAndHandlePosition(height * proportion); - if((visibleRange * 2) < itemCount) { + if ((visibleRange * 2) < itemCount) { if (!hasScrolled && (dx > 0 || dy > 0)) { setVisibility(View.VISIBLE); hasScrolled = true; recyclerView.setVerticalScrollBarEnabled(false); } - } else if(hasScrolled) { + } else if (hasScrolled) { setVisibility(View.GONE); hasScrolled = false; recyclerView.setVerticalScrollBarEnabled(true); @@ -332,4 +315,11 @@ public class FastScroller extends LinearLayout { public interface BubbleTextGetter { String getTextToShowInBubble(int position); } + + private class ScrollListener extends OnScrollListener { + @Override + public void onScrolled(RecyclerView rv, int dx, int dy) { + onUpdateScroll(dx, dy); + } + } } diff --git a/app/src/main/java/net/nullsum/audinaut/view/GenreView.java b/app/src/main/java/net/nullsum/audinaut/view/GenreView.java index bd28fe3..428cf7a 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/GenreView.java +++ b/app/src/main/java/net/nullsum/audinaut/view/GenreView.java @@ -22,29 +22,29 @@ import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; + import net.nullsum.audinaut.R; import net.nullsum.audinaut.domain.Genre; public class GenreView extends UpdateView { - private static final String TAG = GenreView.class.getSimpleName(); - private TextView titleView; - private TextView songsView; - private TextView albumsView; + private final TextView titleView; + private final TextView songsView; + private final TextView albumsView; public GenreView(Context context) { super(context, false); LayoutInflater.from(context).inflate(R.layout.genre_list_item, this, true); - titleView = (TextView) findViewById(R.id.genre_name); - songsView = (TextView) findViewById(R.id.genre_songs); - albumsView = (TextView) findViewById(R.id.genre_albums); + titleView = findViewById(R.id.genre_name); + songsView = findViewById(R.id.genre_songs); + albumsView = findViewById(R.id.genre_albums); } public void setObjectImpl(Genre genre) { titleView.setText(genre.getName()); - if(genre.getAlbumCount() != 0) { + if (genre.getAlbumCount() != 0) { songsView.setVisibility(View.VISIBLE); albumsView.setVisibility(View.VISIBLE); songsView.setText(context.getResources().getString(R.string.select_genre_songs, genre.getSongCount())); diff --git a/app/src/main/java/net/nullsum/audinaut/view/GridSpacingDecoration.java b/app/src/main/java/net/nullsum/audinaut/view/GridSpacingDecoration.java index 078ce8a..6f37184 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/GridSpacingDecoration.java +++ b/app/src/main/java/net/nullsum/audinaut/view/GridSpacingDecoration.java @@ -18,17 +18,13 @@ package net.nullsum.audinaut.view; import android.graphics.Rect; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; -import android.util.Log; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.LinearLayout; -import static android.widget.LinearLayout.*; - public class GridSpacingDecoration extends RecyclerView.ItemDecoration { - private static final String TAG = GridSpacingDecoration.class.getSimpleName(); public static final int SPACING = 10; @Override @@ -39,20 +35,20 @@ public class GridSpacingDecoration extends RecyclerView.ItemDecoration { int halfSpacing = spacing / 2; int childCount = parent.getChildCount(); - int childIndex = parent.getChildPosition(view); + int childIndex = parent.getChildAdapterPosition(view); // Not an actual child (ie: during delete event) - if(childIndex == -1) { + if (childIndex == -1) { return; } - int spanCount = getTotalSpan(view, parent); + int spanCount = getTotalSpan(parent); int spanIndex = childIndex % spanCount; // If we can, use the SpanSizeLookup since headers screw up the index calculation RecyclerView.LayoutManager layoutManager = parent.getLayoutManager(); - if(layoutManager instanceof GridLayoutManager) { + if (layoutManager instanceof GridLayoutManager) { GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager; GridLayoutManager.SpanSizeLookup spanSizeLookup = gridLayoutManager.getSpanSizeLookup(); - if(spanSizeLookup != null) { + if (spanSizeLookup != null) { spanIndex = spanSizeLookup.getSpanIndex(childIndex, spanCount); } } @@ -62,7 +58,7 @@ public class GridSpacingDecoration extends RecyclerView.ItemDecoration { if (spanCount < 1 || spanSize > 1) return; int margins = 0; - if(view instanceof UpdateView) { + if (view instanceof UpdateView) { View firstChild = ((ViewGroup) view).getChildAt(0); ViewGroup.LayoutParams layoutParams = firstChild.getLayoutParams(); if (layoutParams instanceof LinearLayout.LayoutParams) { @@ -82,7 +78,7 @@ public class GridSpacingDecoration extends RecyclerView.ItemDecoration { outRect.top = spacing - doubleMargins; } - if (isLeftEdge(spanIndex, spanCount)) { + if (isLeftEdge(spanIndex)) { outRect.left = spacing - doubleMargins; } @@ -95,7 +91,7 @@ public class GridSpacingDecoration extends RecyclerView.ItemDecoration { } } - protected int getTotalSpan(View view, RecyclerView parent) { + private int getTotalSpan(RecyclerView parent) { RecyclerView.LayoutManager mgr = parent.getLayoutManager(); if (mgr instanceof GridLayoutManager) { return ((GridLayoutManager) mgr).getSpanCount(); @@ -103,11 +99,12 @@ public class GridSpacingDecoration extends RecyclerView.ItemDecoration { return -1; } - protected int getSpanSize(RecyclerView parent, int childIndex) { + + private int getSpanSize(RecyclerView parent, int childIndex) { RecyclerView.LayoutManager mgr = parent.getLayoutManager(); if (mgr instanceof GridLayoutManager) { GridLayoutManager.SpanSizeLookup lookup = ((GridLayoutManager) mgr).getSpanSizeLookup(); - if(lookup != null) { + if (lookup != null) { return lookup.getSpanSize(childIndex); } } @@ -115,19 +112,19 @@ public class GridSpacingDecoration extends RecyclerView.ItemDecoration { return 1; } - protected boolean isLeftEdge(int spanIndex, int spanCount) { + private boolean isLeftEdge(int spanIndex) { return spanIndex == 0; } - protected boolean isRightEdge(int spanIndex, int spanCount) { + private boolean isRightEdge(int spanIndex, int spanCount) { return spanIndex == spanCount - 1; } - protected boolean isTopEdge(int childIndex, int spanIndex, int spanCount) { + private boolean isTopEdge(int childIndex, int spanIndex, int spanCount) { return childIndex < spanCount && childIndex == spanIndex; } - protected boolean isBottomEdge(int childIndex, int childCount, int spanCount) { + private boolean isBottomEdge(int childIndex, int childCount, int spanCount) { return childIndex >= childCount - spanCount; } } diff --git a/app/src/main/java/net/nullsum/audinaut/view/MyLeadingMarginSpan2.java b/app/src/main/java/net/nullsum/audinaut/view/MyLeadingMarginSpan2.java deleted file mode 100644 index d40e30c..0000000 --- a/app/src/main/java/net/nullsum/audinaut/view/MyLeadingMarginSpan2.java +++ /dev/null @@ -1,34 +0,0 @@ -package net.nullsum.audinaut.view; - -import android.graphics.Canvas; -import android.graphics.Paint; -import android.text.Layout; -import android.text.style.LeadingMarginSpan; - -/** - * Created by Scott on 1/13/2015. - */ -public class MyLeadingMarginSpan2 implements LeadingMarginSpan.LeadingMarginSpan2 { - private int margin; - private int lines; - - public MyLeadingMarginSpan2(int lines, int margin) { - this.margin = margin; - this.lines = lines; - } - - @Override - public int getLeadingMargin(boolean first) { - return first ? margin : 0; - } - - @Override - public int getLeadingMarginLineCount() { - return lines; - } - - @Override - public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, - int top, int baseline, int bottom, CharSequence text, - int start, int end, boolean first, Layout layout) {} -} diff --git a/app/src/main/java/net/nullsum/audinaut/view/PlaylistSongView.java b/app/src/main/java/net/nullsum/audinaut/view/PlaylistSongView.java index 3cc6bb1..ed54e8d 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/PlaylistSongView.java +++ b/app/src/main/java/net/nullsum/audinaut/view/PlaylistSongView.java @@ -21,23 +21,20 @@ package net.nullsum.audinaut.view; import android.content.Context; import android.view.LayoutInflater; import android.view.View; -import android.widget.ImageButton; -import android.widget.ImageView; import android.widget.TextView; -import java.util.List; - import net.nullsum.audinaut.R; import net.nullsum.audinaut.domain.MusicDirectory; import net.nullsum.audinaut.domain.Playlist; import net.nullsum.audinaut.util.FileUtil; import net.nullsum.audinaut.util.Util; -public class PlaylistSongView extends UpdateView2> { - private static final String TAG = PlaylistSongView.class.getSimpleName(); +import java.util.List; - private TextView titleView; - private TextView countView; +public class PlaylistSongView extends UpdateView2> { + + private final TextView titleView; + private final TextView countView; private int count = 0; public PlaylistSongView(Context context) { @@ -45,8 +42,8 @@ public class PlaylistSongView extends UpdateView2 songs) { @@ -62,12 +59,12 @@ public class PlaylistSongView extends UpdateView2 { - private static final String TAG = PlaylistView.class.getSimpleName(); - private TextView titleView; - private ImageLoader imageLoader; + private final TextView titleView; + private final ImageLoader imageLoader; public PlaylistView(Context context, ImageLoader imageLoader, boolean largeCell) { - super(context); + super(context, true); LayoutInflater.from(context).inflate(largeCell ? R.layout.basic_cell_item : R.layout.basic_art_item, this, true); coverArtView = findViewById(R.id.item_art); - titleView = (TextView) findViewById(R.id.item_name); - moreButton = (ImageView) findViewById(R.id.item_more); + titleView = findViewById(R.id.item_name); + moreButton = findViewById(R.id.item_more); this.imageLoader = imageLoader; } protected void setObjectImpl(Playlist playlist) { titleView.setText(playlist.getName()); - imageTask = imageLoader.loadImage(coverArtView, playlist, false, true); + imageTask = imageLoader.loadImage(coverArtView, playlist); } public void onUpdateImageView() { - imageTask = imageLoader.loadImage(coverArtView, item, false, true); + imageTask = imageLoader.loadImage(coverArtView, item); } @Override diff --git a/app/src/main/java/net/nullsum/audinaut/view/RecyclingImageView.java b/app/src/main/java/net/nullsum/audinaut/view/RecyclingImageView.java index 5216c62..b6617f9 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/RecyclingImageView.java +++ b/app/src/main/java/net/nullsum/audinaut/view/RecyclingImageView.java @@ -16,18 +16,15 @@ package net.nullsum.audinaut.view; import android.content.Context; -import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.TransitionDrawable; -import android.os.Build; import android.support.v7.widget.AppCompatImageView; import android.util.AttributeSet; public class RecyclingImageView extends AppCompatImageView { private boolean invalidated = false; - private OnInvalidated onInvalidated; public RecyclingImageView(Context context) { super(context); @@ -44,18 +41,18 @@ public class RecyclingImageView extends AppCompatImageView { @Override public void onDraw(Canvas canvas) { Drawable drawable = this.getDrawable(); - if(drawable != null) { - if(drawable instanceof BitmapDrawable) { + if (drawable != null) { + if (drawable instanceof BitmapDrawable) { if (isBitmapRecycled(drawable)) { this.setImageDrawable(null); setInvalidated(true); } - } else if(drawable instanceof TransitionDrawable) { + } else if (drawable instanceof TransitionDrawable) { TransitionDrawable transitionDrawable = (TransitionDrawable) drawable; // If last bitmap in chain is recycled, just blank this out since it would be invalid anyways Drawable lastDrawable = transitionDrawable.getDrawable(transitionDrawable.getNumberOfLayers() - 1); - if(isBitmapRecycled(lastDrawable)) { + if (isBitmapRecycled(lastDrawable)) { this.setImageDrawable(null); setInvalidated(true); } else { @@ -82,34 +79,19 @@ public class RecyclingImageView extends AppCompatImageView { } private boolean isBitmapRecycled(Drawable drawable) { - if(!(drawable instanceof BitmapDrawable)) { + if (!(drawable instanceof BitmapDrawable)) { return false; } BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; - if (bitmapDrawable.getBitmap() != null && bitmapDrawable.getBitmap().isRecycled()) { - return true; - } else { - return false; - } + return bitmapDrawable.getBitmap() != null && bitmapDrawable.getBitmap().isRecycled(); } - public void setInvalidated(boolean invalidated) { - this.invalidated = invalidated; - - if(invalidated && onInvalidated != null) { - onInvalidated.onInvalidated(this); - } - } public boolean isInvalidated() { return invalidated; } - public void setOnInvalidated(OnInvalidated onInvalidated) { - this.onInvalidated = onInvalidated; - } - - public interface OnInvalidated { - void onInvalidated(RecyclingImageView imageView); + private void setInvalidated(boolean invalidated) { + this.invalidated = invalidated; } } diff --git a/app/src/main/java/net/nullsum/audinaut/view/SeekBarPreference.java b/app/src/main/java/net/nullsum/audinaut/view/SeekBarPreference.java index 89b0255..3a50dbd 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/SeekBarPreference.java +++ b/app/src/main/java/net/nullsum/audinaut/view/SeekBarPreference.java @@ -26,49 +26,38 @@ import android.content.Context; import android.content.res.TypedArray; import android.preference.DialogPreference; import android.util.AttributeSet; -import android.util.Log; import android.view.View; import android.widget.SeekBar; import android.widget.TextView; import net.nullsum.audinaut.R; -import net.nullsum.audinaut.util.Constants; /** * SeekBar preference to set the shake force threshold. */ public class SeekBarPreference extends DialogPreference implements SeekBar.OnSeekBarChangeListener { - private static final String TAG = SeekBarPreference.class.getSimpleName(); + private final int mMin; + private final int mMax; + private final float mStepSize; /** * The current value. */ private String mValue; - private int mMin; - private int mMax; - private float mStepSize; private String mDisplay; - /** - * Our context (needed for getResources()) - */ - private Context mContext; - /** * TextView to display current threshold. */ private TextView mValueText; - public SeekBarPreference(Context context, AttributeSet attrs) - { + public SeekBarPreference(Context context, AttributeSet attrs) { super(context, attrs); - mContext = context; - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SeekBarPreference); mMin = a.getInteger(R.styleable.SeekBarPreference_min, 0); mMax = a.getInteger(R.styleable.SeekBarPreference_max, 100); mStepSize = a.getFloat(R.styleable.SeekBarPreference_stepSize, 1f); mDisplay = a.getString(R.styleable.SeekBarPreference_display); - if(mDisplay == null) { + if (mDisplay == null) { mDisplay = "%.0f"; } @@ -76,21 +65,18 @@ public class SeekBarPreference extends DialogPreference implements SeekBar.OnSee } @Override - public CharSequence getSummary() - { + public CharSequence getSummary() { return getSummary(mValue); } @Override - protected Object onGetDefaultValue(TypedArray a, int index) - { + protected Object onGetDefaultValue(TypedArray a, int index) { return a.getString(index); } @Override - protected void onSetInitialValue(boolean restoreValue, Object defaultValue) - { - mValue = restoreValue ? getPersistedString((String) defaultValue) : (String)defaultValue; + protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { + mValue = restoreValue ? getPersistedString((String) defaultValue) : (String) defaultValue; } /** @@ -109,18 +95,17 @@ public class SeekBarPreference extends DialogPreference implements SeekBar.OnSee } @Override - protected View onCreateDialogView() - { + protected View onCreateDialogView() { View view = super.onCreateDialogView(); - mValueText = (TextView)view.findViewById(R.id.value); + mValueText = view.findViewById(R.id.value); mValueText.setText(getSummary(mValue)); - SeekBar seekBar = (SeekBar)view.findViewById(R.id.seek_bar); + SeekBar seekBar = view.findViewById(R.id.seek_bar); seekBar.setMax(mMax - mMin); try { seekBar.setProgress(Integer.parseInt(mValue)); - } catch(Exception e) { + } catch (Exception e) { seekBar.setProgress(0); } seekBar.setOnSeekBarChangeListener(this); @@ -129,17 +114,15 @@ public class SeekBarPreference extends DialogPreference implements SeekBar.OnSee } @Override - protected void onDialogClosed(boolean positiveResult) - { - if(positiveResult) { + protected void onDialogClosed(boolean positiveResult) { + if (positiveResult) { persistString(mValue); notifyChanged(); } } @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) - { + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (fromUser) { mValue = String.valueOf(progress); mValueText.setText(getSummary(mValue)); @@ -147,12 +130,10 @@ public class SeekBarPreference extends DialogPreference implements SeekBar.OnSee } @Override - public void onStartTrackingTouch(SeekBar seekBar) - { + public void onStartTrackingTouch(SeekBar seekBar) { } @Override - public void onStopTrackingTouch(SeekBar seekBar) - { + public void onStopTrackingTouch(SeekBar seekBar) { } } diff --git a/app/src/main/java/net/nullsum/audinaut/view/SettingView.java b/app/src/main/java/net/nullsum/audinaut/view/SettingView.java index 5645345..17c092c 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/SettingView.java +++ b/app/src/main/java/net/nullsum/audinaut/view/SettingView.java @@ -18,11 +18,9 @@ package net.nullsum.audinaut.view; import android.content.Context; import android.view.LayoutInflater; import android.widget.CheckBox; -import android.widget.CompoundButton; import android.widget.TextView; import net.nullsum.audinaut.R; -import net.nullsum.audinaut.domain.User; import net.nullsum.audinaut.domain.User.MusicFolderSetting; import static net.nullsum.audinaut.domain.User.Setting; @@ -36,14 +34,11 @@ public class SettingView extends UpdateView2 { this.context = context; LayoutInflater.from(context).inflate(R.layout.basic_choice_item, this, true); - titleView = (TextView) findViewById(R.id.item_name); - checkBox = (CheckBox) findViewById(R.id.item_checkbox); - checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - if(item != null) { - item.setValue(isChecked); - } + titleView = findViewById(R.id.item_name); + checkBox = findViewById(R.id.item_checkbox); + checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> { + if (item != null) { + item.setValue(isChecked); } }); checkBox.setClickable(false); @@ -52,23 +47,23 @@ public class SettingView extends UpdateView2 { protected void setObjectImpl(Setting setting, Boolean isEditable) { // Can't edit non-role parts String name = setting.getName(); - if(name.indexOf("Role") == -1 && !(setting instanceof MusicFolderSetting)) { + if (!name.contains("Role") && !(setting instanceof MusicFolderSetting)) { item2 = false; } int res = -1; - if(setting instanceof MusicFolderSetting) { + if (setting instanceof MusicFolderSetting) { titleView.setText(((MusicFolderSetting) setting).getLabel()); } else { // Last resort to display the raw value titleView.setText(name); } - if(res != -1) { + if (res != -1) { titleView.setText(res); } - if(setting.getValue()) { + if (setting.getValue()) { checkBox.setChecked(setting.getValue()); } else { checkBox.setChecked(false); diff --git a/app/src/main/java/net/nullsum/audinaut/view/SongView.java b/app/src/main/java/net/nullsum/audinaut/view/SongView.java index 3af6e2c..70b69ce 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/SongView.java +++ b/app/src/main/java/net/nullsum/audinaut/view/SongView.java @@ -19,17 +19,17 @@ package net.nullsum.audinaut.view; import android.content.Context; -import android.graphics.Color; import android.view.LayoutInflater; import android.view.View; -import android.widget.*; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.TextView; + import net.nullsum.audinaut.R; import net.nullsum.audinaut.domain.MusicDirectory; -import net.nullsum.audinaut.service.DownloadService; import net.nullsum.audinaut.service.DownloadFile; +import net.nullsum.audinaut.service.DownloadService; import net.nullsum.audinaut.util.DrawableTint; -import net.nullsum.audinaut.util.SongDBHandler; -import net.nullsum.audinaut.util.ThemeUtil; import net.nullsum.audinaut.util.Util; import java.io.File; @@ -40,18 +40,16 @@ import java.io.File; * @author Sindre Mehus */ public class SongView extends UpdateView2 { - private static final String TAG = SongView.class.getSimpleName(); - private TextView trackTextView; - private TextView titleTextView; + private final TextView trackTextView; + private final TextView titleTextView; + private final TextView artistTextView; + private final TextView durationTextView; + private final TextView statusTextView; + private final ImageView statusImageView; + private final ImageView playedButton; + private final View bottomRowView; private TextView playingTextView; - private TextView artistTextView; - private TextView durationTextView; - private TextView statusTextView; - private ImageView statusImageView; - private ImageView playedButton; - private View bottomRowView; - private DownloadService downloadService; private long revision = -1; private DownloadFile downloadFile; @@ -65,31 +63,30 @@ public class SongView extends UpdateView2 { private File partialFile; private boolean partialFileExists = false; private boolean loaded = false; - private boolean isPlayed = false; private boolean isPlayedShown = false; private boolean showAlbum = false; public SongView(Context context) { - super(context); + super(context, true); LayoutInflater.from(context).inflate(R.layout.song_list_item, this, true); - trackTextView = (TextView) findViewById(R.id.song_track); - titleTextView = (TextView) findViewById(R.id.song_title); - artistTextView = (TextView) findViewById(R.id.song_artist); - durationTextView = (TextView) findViewById(R.id.song_duration); - statusTextView = (TextView) findViewById(R.id.song_status); - statusImageView = (ImageView) findViewById(R.id.song_status_icon); + trackTextView = findViewById(R.id.song_track); + titleTextView = findViewById(R.id.song_title); + artistTextView = findViewById(R.id.song_artist); + durationTextView = findViewById(R.id.song_duration); + statusTextView = findViewById(R.id.song_status); + statusImageView = findViewById(R.id.song_status_icon); playedButton = (ImageButton) findViewById(R.id.song_played); - moreButton = (ImageView) findViewById(R.id.item_more); + moreButton = findViewById(R.id.item_more); bottomRowView = findViewById(R.id.song_bottom); } - public void setObjectImpl(MusicDirectory.Entry song, Boolean checkable) { + protected void setObjectImpl(MusicDirectory.Entry song, Boolean checkable) { this.checkable = checkable; StringBuilder artist = new StringBuilder(40); - if(showAlbum) { + if (showAlbum) { artist.append(song.getAlbum()); } else { artist.append(song.getArtist()); @@ -101,7 +98,7 @@ public class SongView extends UpdateView2 { String title = song.getTitle(); Integer track = song.getTrack(); TextView newPlayingTextView; - if(track != null && Util.getDisplayTrack(context)) { + if (track != null && Util.getDisplayTrack(context)) { trackTextView.setText(String.format("%02d", track)); trackTextView.setVisibility(View.VISIBLE); newPlayingTextView = trackTextView; @@ -110,8 +107,8 @@ public class SongView extends UpdateView2 { newPlayingTextView = titleTextView; } - if(newPlayingTextView != playingTextView || playingTextView == null) { - if(playing) { + if (newPlayingTextView != playingTextView || playingTextView == null) { + if (playing) { playingTextView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); playing = false; } @@ -129,26 +126,26 @@ public class SongView extends UpdateView2 { dontChangeDownloadFile = false; } + public DownloadFile getDownloadFile() { + return downloadFile; + } + public void setDownloadFile(DownloadFile downloadFile) { this.downloadFile = downloadFile; dontChangeDownloadFile = true; } - public DownloadFile getDownloadFile() { - return downloadFile; - } - @Override protected void updateBackground() { if (downloadService == null) { downloadService = DownloadService.getInstance(); - if(downloadService == null) { + if (downloadService == null) { return; } } long newRevision = downloadService.getDownloadListUpdateRevision(); - if((revision != newRevision && dontChangeDownloadFile == false) || downloadFile == null) { + if ((revision != newRevision && !dontChangeDownloadFile) || downloadFile == null) { downloadFile = downloadService.forSong(item); revision = newRevision; } @@ -159,7 +156,7 @@ public class SongView extends UpdateView2 { partialFileExists = partialFile.exists(); // Check if needs to load metadata: check against all fields that we know are null in offline mode - if(item.getBitRate() == null && item.getDuration() == null && item.getDiscNumber() == null && isWorkDone) { + if (item.getBitRate() == null && item.getDuration() == null && item.getDiscNumber() == null && isWorkDone) { item.loadMetadata(downloadFile.getCompleteFile()); loaded = true; } @@ -167,7 +164,7 @@ public class SongView extends UpdateView2 { @Override protected void update() { - if(loaded) { + if (loaded) { setObjectImpl(item, item2); } if (downloadService == null || downloadFile == null) { @@ -176,11 +173,11 @@ public class SongView extends UpdateView2 { if (isWorkDone) { int moreImage = isSaved ? R.drawable.download_pinned : R.drawable.download_cached; - if(moreImage != this.moreImage) { + if (moreImage != this.moreImage) { moreButton.setImageResource(moreImage); this.moreImage = moreImage; } - } else if(this.moreImage != R.drawable.download_none_light) { + } else if (this.moreImage != R.drawable.download_none_light) { moreButton.setImageResource(DrawableTint.getDrawableRes(context, R.attr.download_none)); this.moreImage = R.drawable.download_none_light; } @@ -188,12 +185,12 @@ public class SongView extends UpdateView2 { if (downloadFile.isDownloading() && !downloadFile.isDownloadCancelled() && partialFileExists) { double percentage = (partialFile.length() * 100.0) / downloadFile.getEstimatedSize(); percentage = Math.min(percentage, 100); - statusTextView.setText((int)percentage + " %"); - if(!rightImage) { + statusTextView.setText((int) percentage + " %"); + if (!rightImage) { statusImageView.setVisibility(View.VISIBLE); rightImage = true; } - } else if(rightImage) { + } else if (rightImage) { statusTextView.setText(null); statusImageView.setVisibility(View.GONE); rightImage = false; @@ -201,28 +198,29 @@ public class SongView extends UpdateView2 { boolean playing = Util.equals(downloadService.getCurrentPlaying(), downloadFile); if (playing) { - if(!this.playing) { + if (!this.playing) { this.playing = playing; playingTextView.setCompoundDrawablesWithIntrinsicBounds(DrawableTint.getDrawableRes(context, R.attr.playing), 0, 0, 0); } } else { - if(this.playing) { + if (this.playing) { this.playing = playing; playingTextView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0); } } - if(isPlayed) { - if(!isPlayedShown) { - if(playedButton.getDrawable() == null) { - playedButton.setImageDrawable(DrawableTint.getTintedDrawable(context, R.drawable.ic_toggle_played)); + boolean isPlayed = false; + if (isPlayed) { + if (!isPlayedShown) { + if (playedButton.getDrawable() == null) { + playedButton.setImageDrawable(DrawableTint.getTintedDrawable(context)); } playedButton.setVisibility(View.VISIBLE); isPlayedShown = true; } } else { - if(isPlayedShown) { + if (isPlayedShown) { playedButton.setVisibility(View.GONE); isPlayedShown = false; } diff --git a/app/src/main/java/net/nullsum/audinaut/view/SquareImageView.java b/app/src/main/java/net/nullsum/audinaut/view/SquareImageView.java index d7b7224..de80697 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/SquareImageView.java +++ b/app/src/main/java/net/nullsum/audinaut/view/SquareImageView.java @@ -17,7 +17,6 @@ package net.nullsum.audinaut.view; import android.content.Context; import android.util.AttributeSet; -import android.widget.ImageView; public class SquareImageView extends RecyclingImageView { public SquareImageView(final Context context, final AttributeSet attrs) { diff --git a/app/src/main/java/net/nullsum/audinaut/view/UpdateView.java b/app/src/main/java/net/nullsum/audinaut/view/UpdateView.java index dcd627a..65e401f 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/UpdateView.java +++ b/app/src/main/java/net/nullsum/audinaut/view/UpdateView.java @@ -27,114 +27,71 @@ import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; -import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; +import net.nullsum.audinaut.R; +import net.nullsum.audinaut.domain.MusicDirectory; +import net.nullsum.audinaut.util.DrawableTint; +import net.nullsum.audinaut.util.SilentBackgroundTask; + import java.util.ArrayList; import java.util.List; import java.util.WeakHashMap; -import net.nullsum.audinaut.domain.MusicDirectory; -import net.nullsum.audinaut.R; -import net.nullsum.audinaut.util.DrawableTint; -import net.nullsum.audinaut.util.SilentBackgroundTask; - public abstract class UpdateView extends LinearLayout { private static final String TAG = UpdateView.class.getSimpleName(); - private static final WeakHashMap INSTANCES = new WeakHashMap(); + private static final WeakHashMap INSTANCES = new WeakHashMap<>(); - protected static Handler backgroundHandler; - protected static Handler uiHandler; + static Handler backgroundHandler; + static Handler uiHandler; private static Runnable updateRunnable; private static int activeActivities = 0; + Context context; + T item; + ImageView moreButton; + View coverArtView; + boolean exists = false; + boolean pinned = false; + SilentBackgroundTask imageTask = null; + boolean checkable; + private boolean shaded = false; + private Drawable startBackgroundDrawable; - protected Context context; - protected T item; - protected ImageView moreButton; - protected View coverArtView; - - protected boolean exists = false; - protected boolean pinned = false; - protected boolean shaded = false; - protected SilentBackgroundTask imageTask = null; - protected Drawable startBackgroundDrawable; - - protected final boolean autoUpdate; - protected boolean checkable; - - public UpdateView(Context context) { - this(context, true); - } - public UpdateView(Context context, boolean autoUpdate) { + UpdateView(Context context, boolean autoUpdate) { super(context); this.context = context; - this.autoUpdate = autoUpdate; setLayoutParams(new AbsListView.LayoutParams( - ViewGroup.LayoutParams.FILL_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); - if(autoUpdate) { + if (autoUpdate) { INSTANCES.put(this, null); } startUpdater(); } - @Override - public void setPressed(boolean pressed) { - - } - - public void setObject(T obj) { - if(item == obj) { - return; - } - - item = obj; - if(imageTask != null) { - imageTask.cancel(); - imageTask = null; - } - if(coverArtView != null && coverArtView instanceof ImageView) { - ((ImageView) coverArtView).setImageDrawable(null); - } - setObjectImpl(obj); - updateBackground(); - update(); - } - public void setObject(T obj1, Object obj2) { - setObject(obj1, null); - } - protected abstract void setObjectImpl(T obj); - private static synchronized void startUpdater() { - if(uiHandler != null) { + if (uiHandler != null) { return; } uiHandler = new Handler(); // Needed so handler is never null until thread creates it backgroundHandler = uiHandler; - updateRunnable = new Runnable() { - @Override - public void run() { - updateAll(); - } - }; + updateRunnable = UpdateView::updateAll; - new Thread(new Runnable() { - public void run() { - Looper.prepare(); - backgroundHandler = new Handler(Looper.myLooper()); - uiHandler.post(updateRunnable); - Looper.loop(); - } + new Thread(() -> { + Looper.prepare(); + backgroundHandler = new Handler(Looper.myLooper()); + uiHandler.post(updateRunnable); + Looper.loop(); }, "UpdateView").start(); } public static synchronized void triggerUpdate() { - if(backgroundHandler != null) { + if (backgroundHandler != null) { uiHandler.removeCallbacksAndMessages(null); backgroundHandler.removeCallbacksAndMessages(null); uiHandler.post(updateRunnable); @@ -144,18 +101,18 @@ public abstract class UpdateView extends LinearLayout { private static void updateAll() { try { // If nothing can see this, stop updating - if(activeActivities == 0) { + if (activeActivities == 0) { activeActivities--; return; } - List views = new ArrayList(); + List views = new ArrayList<>(); for (UpdateView view : INSTANCES.keySet()) { if (view.isShown()) { views.add(view); } } - if(views.size() > 0) { + if (views.size() > 0) { updateAllLive(views); } else { uiHandler.postDelayed(updateRunnable, 2000L); @@ -164,62 +121,54 @@ public abstract class UpdateView extends LinearLayout { Log.w(TAG, "Error when updating song views.", x); } } + private static void updateAllLive(final List views) { - final Runnable runnable = new Runnable() { - @Override - public void run() { - try { - for(UpdateView view: views) { - view.update(); - } - } catch (Throwable x) { - Log.w(TAG, "Error when updating song views.", x); + final Runnable runnable = () -> { + try { + for (UpdateView view : views) { + view.update(); } - uiHandler.postDelayed(updateRunnable, 1000L); + } catch (Throwable x) { + Log.w(TAG, "Error when updating song views.", x); } + uiHandler.postDelayed(updateRunnable, 1000L); }; - backgroundHandler.post(new Runnable() { - @Override - public void run() { - try { - for(UpdateView view: views) { - view.updateBackground(); - } - uiHandler.post(runnable); - } catch (Throwable x) { - Log.w(TAG, "Error when updating song views.", x); + backgroundHandler.post(() -> { + try { + for (UpdateView view : views) { + view.updateBackground(); } + uiHandler.post(runnable); + } catch (Throwable x) { + Log.w(TAG, "Error when updating song views.", x); } }); } - public static boolean hasActiveActivity() { - return activeActivities > 0; - } - public static void addActiveActivity() { activeActivities++; - if(activeActivities == 0 && uiHandler != null && updateRunnable != null) { + if (activeActivities == 0 && uiHandler != null && updateRunnable != null) { activeActivities++; uiHandler.post(updateRunnable); } } + public static void removeActiveActivity() { activeActivities--; } public static MusicDirectory.Entry findEntry(MusicDirectory.Entry entry) { - for(UpdateView view: INSTANCES.keySet()) { + for (UpdateView view : INSTANCES.keySet()) { MusicDirectory.Entry check = null; - if(view instanceof SongView) { + if (view instanceof SongView) { check = ((SongView) view).getEntry(); - } else if(view instanceof AlbumView) { + } else if (view instanceof AlbumView) { check = ((AlbumView) view).getEntry(); } - if(check != null && entry != check && check.getId().equals(entry.getId())) { + if (check != null && entry != check && check.getId().equals(entry.getId())) { return check; } } @@ -227,27 +176,53 @@ public abstract class UpdateView extends LinearLayout { return null; } - protected void updateBackground() { + @Override + public void setPressed(boolean pressed) { } - protected void update() { - if(moreButton != null) { - if(exists || pinned) { - if(!shaded) { + + public void setObject(T obj) { + if (item == obj) { + return; + } + + item = obj; + if (imageTask != null) { + imageTask.cancel(); + imageTask = null; + } + if (coverArtView != null && coverArtView instanceof ImageView) { + ((ImageView) coverArtView).setImageDrawable(null); + } + setObjectImpl(obj); + updateBackground(); + update(); + } + + protected abstract void setObjectImpl(T obj); + + void updateBackground() { + + } + + void update() { + if (moreButton != null) { + if (exists || pinned) { + if (!shaded) { moreButton.setImageResource(exists ? R.drawable.download_cached : R.drawable.download_pinned); shaded = true; } } else { - if(shaded) { + if (shaded) { moreButton.setImageResource(DrawableTint.getDrawableRes(context, R.attr.download_none)); shaded = false; } } } - if(coverArtView != null && coverArtView instanceof RecyclingImageView) { + if (coverArtView != null && coverArtView instanceof RecyclingImageView) { RecyclingImageView recyclingImageView = (RecyclingImageView) coverArtView; - if(recyclingImageView.isInvalidated()) { + if (recyclingImageView.isInvalidated()) { onUpdateImageView(); } } @@ -256,28 +231,25 @@ public abstract class UpdateView extends LinearLayout { public boolean isCheckable() { return checkable; } + public void setChecked(boolean checked) { View child = getChildAt(0); if (checked && startBackgroundDrawable == null) { startBackgroundDrawable = child.getBackground(); child.setBackgroundColor(DrawableTint.getColorRes(context, R.attr.colorPrimary)); } else if (!checked && startBackgroundDrawable != null) { - child.setBackgroundDrawable(startBackgroundDrawable); + child.setBackground(startBackgroundDrawable); startBackgroundDrawable = null; } } - public void onClick() { - - } - - public void onUpdateImageView() { + void onUpdateImageView() { } public static class UpdateViewHolder extends RecyclerView.ViewHolder { + private final View view; private UpdateView updateView; - private View view; private T item; public UpdateViewHolder(UpdateView itemView) { @@ -288,7 +260,7 @@ public abstract class UpdateView extends LinearLayout { } // Different is so that call is not ambiguous - public UpdateViewHolder(View view, boolean different) { + public UpdateViewHolder(View view) { super(view); this.view = view; } @@ -296,15 +268,18 @@ public abstract class UpdateView extends LinearLayout { public UpdateView getUpdateView() { return updateView; } + public View getView() { return view; } - public void setItem(T item) { - this.item = item; - } + public T getItem() { return item; } + + public void setItem(T item) { + this.item = item; + } } } diff --git a/app/src/main/java/net/nullsum/audinaut/view/UpdateView2.java b/app/src/main/java/net/nullsum/audinaut/view/UpdateView2.java index 5069657..cf4d6b2 100644 --- a/app/src/main/java/net/nullsum/audinaut/view/UpdateView2.java +++ b/app/src/main/java/net/nullsum/audinaut/view/UpdateView2.java @@ -4,52 +4,45 @@ import android.content.Context; import android.widget.ImageView; public abstract class UpdateView2 extends UpdateView { - protected T2 item2; + T2 item2; public UpdateView2(Context context) { - super(context); + super(context, true); } - public UpdateView2(Context context, boolean autoUpdate) { + UpdateView2(Context context, boolean autoUpdate) { super(context, autoUpdate); } public final void setObject(T1 obj1) { setObject(obj1, null); } - @Override + public void setObject(T1 obj1, Object obj2) { - if(item == obj1 && item2 == obj2) { + if (item == obj1 && item2 == obj2) { return; } item = obj1; item2 = (T2) obj2; - if(imageTask != null) { + if (imageTask != null) { imageTask.cancel(); imageTask = null; } - if(coverArtView != null && coverArtView instanceof ImageView) { + if (coverArtView != null && coverArtView instanceof ImageView) { ((ImageView) coverArtView).setImageDrawable(null); } setObjectImpl(item, item2); - backgroundHandler.post(new Runnable() { - @Override - public void run() { - updateBackground(); - uiHandler.post(new Runnable() { - @Override - public void run() { - update(); - } - }); - } + backgroundHandler.post(() -> { + updateBackground(); + uiHandler.post(this::update); }); } protected final void setObjectImpl(T1 obj1) { setObjectImpl(obj1, null); } + protected abstract void setObjectImpl(T1 obj1, T2 obj2); } diff --git a/app/src/main/kotlin/net/nullsum/audinuat/domain/Artist.kt b/app/src/main/kotlin/net/nullsum/audinuat/domain/Artist.kt index a358bc7..a20fdba 100644 --- a/app/src/main/kotlin/net/nullsum/audinuat/domain/Artist.kt +++ b/app/src/main/kotlin/net/nullsum/audinuat/domain/Artist.kt @@ -1,17 +1,9 @@ package net.nullsum.audinaut.domain -import android.util.Log - import java.io.Serializable -import java.text.Collator -import java.util.Collections -import java.util.Comparator -import java.util.Locale class Artist constructor(var id: String = "", var name: String = "") : Serializable { val TAG: String = "Artist" - val ROOT_ID: String = "-1" - val MISSING_ID: String = "-2" var index: String = "" var closeness: Int = 0 diff --git a/app/src/main/kotlin/net/nullsum/audinuat/domain/Indexes.kt b/app/src/main/kotlin/net/nullsum/audinuat/domain/Indexes.kt index 4091c1f..0e797f6 100644 --- a/app/src/main/kotlin/net/nullsum/audinuat/domain/Indexes.kt +++ b/app/src/main/kotlin/net/nullsum/audinuat/domain/Indexes.kt @@ -1,18 +1,11 @@ package net.nullsum.audinaut.domain import android.content.Context -import android.content.SharedPreferences - -import kotlin.collections.MutableList import java.io.Serializable -import net.nullsum.audinaut.util.Constants -import net.nullsum.audinaut.util.Util - -class Indexes constructor(var lastModified: Long = 0, - var shortcuts: MutableList = mutableListOf(), - var artists: MutableList = mutableListOf(), - var entries: MutableList = mutableListOf()) : Serializable { +class Indexes(var shortcuts: MutableList = mutableListOf(), + var artists: MutableList = mutableListOf(), + var entries: MutableList = mutableListOf()) : Serializable { fun sortChildren(context: Context) { } } diff --git a/app/src/main/kotlin/net/nullsum/audinuat/domain/PlayerState.kt b/app/src/main/kotlin/net/nullsum/audinuat/domain/PlayerState.kt index 5af80a8..3a88422 100644 --- a/app/src/main/kotlin/net/nullsum/audinuat/domain/PlayerState.kt +++ b/app/src/main/kotlin/net/nullsum/audinuat/domain/PlayerState.kt @@ -1,19 +1,14 @@ package net.nullsum.audinaut.domain -import android.media.RemoteControlClient +enum class PlayerState { + IDLE, + DOWNLOADING, + PREPARING, + PREPARED, + STARTED, + STOPPED, + PAUSED, + PAUSED_TEMP, + COMPLETED; -enum class PlayerState constructor(val mRemoteControlClientPlayState: Int) { - IDLE(RemoteControlClient.PLAYSTATE_STOPPED), - DOWNLOADING(RemoteControlClient.PLAYSTATE_BUFFERING), - PREPARING(RemoteControlClient.PLAYSTATE_BUFFERING), - PREPARED(RemoteControlClient.PLAYSTATE_STOPPED), - STARTED(RemoteControlClient.PLAYSTATE_PLAYING), - STOPPED(RemoteControlClient.PLAYSTATE_STOPPED), - PAUSED(RemoteControlClient.PLAYSTATE_PAUSED), - PAUSED_TEMP(RemoteControlClient.PLAYSTATE_PAUSED), - COMPLETED(RemoteControlClient.PLAYSTATE_STOPPED); - - fun getRemoteControlClientPlayState(): Int { - return mRemoteControlClientPlayState - } } diff --git a/app/src/main/kotlin/net/nullsum/audinuat/service/MusicServiceFactory.kt b/app/src/main/kotlin/net/nullsum/audinuat/service/MusicServiceFactory.kt index 974052d..ca23db0 100644 --- a/app/src/main/kotlin/net/nullsum/audinuat/service/MusicServiceFactory.kt +++ b/app/src/main/kotlin/net/nullsum/audinuat/service/MusicServiceFactory.kt @@ -1,8 +1,7 @@ package net.nullsum.audinaut.service -import net.nullsum.audinaut.util.Util - import android.content.Context +import net.nullsum.audinaut.util.Util object MusicServiceFactory { @@ -10,10 +9,10 @@ object MusicServiceFactory { val onlineService: MusicService = CachedMusicService(RESTMusicService()) @JvmStatic - val offlineService: MusicService = OfflineMusicService() + private val offlineService: MusicService = OfflineMusicService() @JvmStatic - fun getMusicService(context: Context) : MusicService { + fun getMusicService(context: Context): MusicService { return if (Util.isOffline(context)) offlineService else onlineService } } diff --git a/app/src/main/res/anim/enter_from_left.xml b/app/src/main/res/anim/enter_from_left.xml index b5de863..9e81c14 100644 --- a/app/src/main/res/anim/enter_from_left.xml +++ b/app/src/main/res/anim/enter_from_left.xml @@ -3,10 +3,13 @@ android:shareInterpolator="false"> + android:fromXDelta="-100%" + android:interpolator="@android:anim/accelerate_interpolator" + android:toXDelta="0%" /> - + diff --git a/app/src/main/res/anim/enter_from_right.xml b/app/src/main/res/anim/enter_from_right.xml index e6d03d2..8b07116 100644 --- a/app/src/main/res/anim/enter_from_right.xml +++ b/app/src/main/res/anim/enter_from_right.xml @@ -3,10 +3,13 @@ android:shareInterpolator="false"> + android:fromXDelta="100%" + android:interpolator="@android:anim/accelerate_interpolator" + android:toXDelta="0%" /> - + diff --git a/app/src/main/res/anim/exit_to_left.xml b/app/src/main/res/anim/exit_to_left.xml index a2314cf..7e636a6 100644 --- a/app/src/main/res/anim/exit_to_left.xml +++ b/app/src/main/res/anim/exit_to_left.xml @@ -3,10 +3,13 @@ android:shareInterpolator="false"> + android:fromXDelta="0%" + android:interpolator="@android:anim/accelerate_interpolator" + android:toXDelta="-100%" /> - + diff --git a/app/src/main/res/anim/exit_to_right.xml b/app/src/main/res/anim/exit_to_right.xml index 0d501cc..6c23f6e 100644 --- a/app/src/main/res/anim/exit_to_right.xml +++ b/app/src/main/res/anim/exit_to_right.xml @@ -3,10 +3,13 @@ android:shareInterpolator="false"> + android:fromXDelta="0%" + android:interpolator="@android:anim/accelerate_interpolator" + android:toXDelta="100%" /> - + diff --git a/app/src/main/res/anim/fade_in.xml b/app/src/main/res/anim/fade_in.xml index b6a2997..912f34f 100644 --- a/app/src/main/res/anim/fade_in.xml +++ b/app/src/main/res/anim/fade_in.xml @@ -1,5 +1,5 @@ + android:duration="500" + android:fromAlpha="0.0" + android:toAlpha="1.0" /> diff --git a/app/src/main/res/anim/fade_out.xml b/app/src/main/res/anim/fade_out.xml index 14a58c1..2bf4782 100644 --- a/app/src/main/res/anim/fade_out.xml +++ b/app/src/main/res/anim/fade_out.xml @@ -1,5 +1,5 @@ + android:duration="500" + android:fromAlpha="1.0" + android:toAlpha="0.0" /> diff --git a/app/src/main/res/anim/push_down_in.xml b/app/src/main/res/anim/push_down_in.xml index 6cfbd1b..3630d43 100644 --- a/app/src/main/res/anim/push_down_in.xml +++ b/app/src/main/res/anim/push_down_in.xml @@ -1,5 +1,4 @@ - - - - + + diff --git a/app/src/main/res/anim/push_down_out.xml b/app/src/main/res/anim/push_down_out.xml index 3d0b8af..36f3876 100644 --- a/app/src/main/res/anim/push_down_out.xml +++ b/app/src/main/res/anim/push_down_out.xml @@ -1,5 +1,4 @@ - - - - + + diff --git a/app/src/main/res/anim/push_up_in.xml b/app/src/main/res/anim/push_up_in.xml index 6a0ba14..ab4d93e 100644 --- a/app/src/main/res/anim/push_up_in.xml +++ b/app/src/main/res/anim/push_up_in.xml @@ -1,5 +1,4 @@ - - - - + + diff --git a/app/src/main/res/anim/push_up_out.xml b/app/src/main/res/anim/push_up_out.xml index c0a1e87..c9dbe1e 100644 --- a/app/src/main/res/anim/push_up_out.xml +++ b/app/src/main/res/anim/push_up_out.xml @@ -1,5 +1,4 @@ - - - - + + diff --git a/app/src/main/res/drawable-v21/notification_backward.xml b/app/src/main/res/drawable-v21/notification_backward.xml index 2130e0e..7b00628 100644 --- a/app/src/main/res/drawable-v21/notification_backward.xml +++ b/app/src/main/res/drawable-v21/notification_backward.xml @@ -1,4 +1,3 @@ - + diff --git a/app/src/main/res/drawable-v21/notification_close.xml b/app/src/main/res/drawable-v21/notification_close.xml index 2b010b3..6f643f5 100644 --- a/app/src/main/res/drawable-v21/notification_close.xml +++ b/app/src/main/res/drawable-v21/notification_close.xml @@ -1,4 +1,3 @@ - + diff --git a/app/src/main/res/drawable-v21/notification_forward.xml b/app/src/main/res/drawable-v21/notification_forward.xml index 972cb2b..45cd535 100644 --- a/app/src/main/res/drawable-v21/notification_forward.xml +++ b/app/src/main/res/drawable-v21/notification_forward.xml @@ -1,4 +1,3 @@ - + diff --git a/app/src/main/res/drawable-v21/notification_pause.xml b/app/src/main/res/drawable-v21/notification_pause.xml index dad7c7e..7ff55b2 100644 --- a/app/src/main/res/drawable-v21/notification_pause.xml +++ b/app/src/main/res/drawable-v21/notification_pause.xml @@ -1,4 +1,3 @@ - + diff --git a/app/src/main/res/drawable-v21/notification_start.xml b/app/src/main/res/drawable-v21/notification_start.xml index f410eed..fdcbb67 100644 --- a/app/src/main/res/drawable-v21/notification_start.xml +++ b/app/src/main/res/drawable-v21/notification_start.xml @@ -1,4 +1,3 @@ - + diff --git a/app/src/main/res/drawable/card_rounded_corners_black.xml b/app/src/main/res/drawable/card_rounded_corners_black.xml index 8d977a6..f6df0f8 100644 --- a/app/src/main/res/drawable/card_rounded_corners_black.xml +++ b/app/src/main/res/drawable/card_rounded_corners_black.xml @@ -1,6 +1,10 @@ - - - + + + diff --git a/app/src/main/res/drawable/card_rounded_corners_dark.xml b/app/src/main/res/drawable/card_rounded_corners_dark.xml index 2be3de9..0c3172b 100644 --- a/app/src/main/res/drawable/card_rounded_corners_dark.xml +++ b/app/src/main/res/drawable/card_rounded_corners_dark.xml @@ -1,6 +1,10 @@ - - - + + + diff --git a/app/src/main/res/drawable/card_rounded_corners_light.xml b/app/src/main/res/drawable/card_rounded_corners_light.xml index 9b63f8e..e82d4bd 100644 --- a/app/src/main/res/drawable/card_rounded_corners_light.xml +++ b/app/src/main/res/drawable/card_rounded_corners_light.xml @@ -1,6 +1,10 @@ - - - + + + diff --git a/app/src/main/res/drawable/fast_scroller_bubble.xml b/app/src/main/res/drawable/fast_scroller_bubble.xml index 4f60829..fdd722c 100644 --- a/app/src/main/res/drawable/fast_scroller_bubble.xml +++ b/app/src/main/res/drawable/fast_scroller_bubble.xml @@ -3,14 +3,14 @@ android:shape="rectangle"> + android:bottomRightRadius="0px" + android:topLeftRadius="44dp" + android:topRightRadius="44dp" /> - + + android:width="88dp" + android:height="88dp" /> diff --git a/app/src/main/res/drawable/fast_scroller_handle.xml b/app/src/main/res/drawable/fast_scroller_handle.xml index 550590d..8170d9f 100644 --- a/app/src/main/res/drawable/fast_scroller_handle.xml +++ b/app/src/main/res/drawable/fast_scroller_handle.xml @@ -2,25 +2,21 @@ - + - + - + - + - + - + diff --git a/app/src/main/res/drawable/notification_backward.xml b/app/src/main/res/drawable/notification_backward.xml index bc4db5f..8374c8a 100644 --- a/app/src/main/res/drawable/notification_backward.xml +++ b/app/src/main/res/drawable/notification_backward.xml @@ -1,4 +1,3 @@ - + diff --git a/app/src/main/res/drawable/notification_close.xml b/app/src/main/res/drawable/notification_close.xml index 9d356f5..b4c5f4c 100644 --- a/app/src/main/res/drawable/notification_close.xml +++ b/app/src/main/res/drawable/notification_close.xml @@ -1,4 +1,3 @@ - + diff --git a/app/src/main/res/drawable/notification_forward.xml b/app/src/main/res/drawable/notification_forward.xml index 8095c4f..9d11adb 100644 --- a/app/src/main/res/drawable/notification_forward.xml +++ b/app/src/main/res/drawable/notification_forward.xml @@ -1,4 +1,3 @@ - + diff --git a/app/src/main/res/drawable/notification_pause.xml b/app/src/main/res/drawable/notification_pause.xml index 8c74aa6..482685a 100644 --- a/app/src/main/res/drawable/notification_pause.xml +++ b/app/src/main/res/drawable/notification_pause.xml @@ -1,4 +1,3 @@ - + diff --git a/app/src/main/res/drawable/notification_start.xml b/app/src/main/res/drawable/notification_start.xml index d945bb9..854f7ee 100644 --- a/app/src/main/res/drawable/notification_start.xml +++ b/app/src/main/res/drawable/notification_start.xml @@ -1,4 +1,3 @@ - + diff --git a/app/src/main/res/layout-land/download.xml b/app/src/main/res/layout-land/download.xml index f53cc49..f5afeaf 100644 --- a/app/src/main/res/layout-land/download.xml +++ b/app/src/main/res/layout-land/download.xml @@ -1,9 +1,9 @@ + android:layout_height="match_parent" + android:baselineAligned="false" + android:orientation="horizontal"> + android:scaleType="fitCenter" + android:src="@drawable/unknown_album_large" /> - + - - - - - + android:layout_marginLeft="12dip" + android:layout_marginRight="12dip" + android:ellipsize="end" + android:gravity="center_horizontal" + android:maxLines="1" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="?android:textColorPrimary" /> - - + android:id="@+id/download_status" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_above="@+id/download_media_buttons_wrapper" + android:layout_marginBottom="8dip" + android:layout_marginLeft="12dip" + android:layout_marginRight="12dip" + android:ellipsize="end" + android:gravity="center_horizontal" + android:maxLines="1" + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="?android:textColorSecondary" /> - + - + diff --git a/app/src/main/res/layout-large-land/abstract_fragment_container.xml b/app/src/main/res/layout-large-land/abstract_fragment_container.xml index 6a7aaba..a0e06ba 100644 --- a/app/src/main/res/layout-large-land/abstract_fragment_container.xml +++ b/app/src/main/res/layout-large-land/abstract_fragment_container.xml @@ -1,21 +1,22 @@ + android:layout_marginTop="?attr/actionBarSize" + android:baselineAligned="false" + android:orientation="horizontal"> + android:layout_weight="4" /> + android:visibility="gone" /> diff --git a/app/src/main/res/layout-large-land/download.xml b/app/src/main/res/layout-large-land/download.xml index 6b781b6..f6653da 100644 --- a/app/src/main/res/layout-large-land/download.xml +++ b/app/src/main/res/layout-large-land/download.xml @@ -1,20 +1,18 @@ + android:layout_height="match_parent" + android:orientation="horizontal"> + android:scaleType="fitCenter" + android:src="@drawable/unknown_album_large" /> - - - - - - - + @@ -51,29 +32,29 @@ android:id="@+id/download_song_title" android:layout_width="fill_parent" android:layout_height="wrap_content" + android:layout_above="@+id/download_status" android:layout_centerHorizontal="true" android:layout_marginLeft="12dip" android:layout_marginRight="12dip" - android:maxLines="1" android:ellipsize="end" android:gravity="center_horizontal" + android:maxLines="1" android:textAppearance="?android:attr/textAppearanceMedium" - android:textColor="?android:textColorPrimary" - android:layout_above="@+id/download_status"/> + android:textColor="?android:textColorPrimary" /> + android:textColor="?android:textColorSecondary" /> - + - + diff --git a/app/src/main/res/layout-port/download.xml b/app/src/main/res/layout-port/download.xml index 632ed80..2746e3e 100644 --- a/app/src/main/res/layout-port/download.xml +++ b/app/src/main/res/layout-port/download.xml @@ -1,14 +1,12 @@ + android:layout_height="fill_parent" + android:orientation="vertical"> + android:background="@android:color/transparent" + android:orientation="vertical"> - + android:layout_height="wrap_content" + android:orientation="vertical"> + android:layout_gravity="center_horizontal|top" + android:scaleType="fitCenter" /> - + android:orientation="horizontal" + android:visibility="invisible" /> + android:maxLines="1" + android:textColor="?android:textColorSecondary" /> + android:textColor="?android:textColorPrimary" + android:textStyle="bold" /> - + - + - + diff --git a/app/src/main/res/layout/abstract_activity.xml b/app/src/main/res/layout/abstract_activity.xml index dc5ba64..73ee4d2 100644 --- a/app/src/main/res/layout/abstract_activity.xml +++ b/app/src/main/res/layout/abstract_activity.xml @@ -1,7 +1,5 @@ - + android:layout_height="match_parent" /> + android:layout_gravity="start" /> diff --git a/app/src/main/res/layout/abstract_fragment_activity.xml b/app/src/main/res/layout/abstract_fragment_activity.xml index 13cd632..29bd882 100644 --- a/app/src/main/res/layout/abstract_fragment_activity.xml +++ b/app/src/main/res/layout/abstract_fragment_activity.xml @@ -1,14 +1,13 @@ - + sothree:umanoShadowHeight="4dp"> + app:popupTheme="?attr/actionbarPopupStyle" /> - + @@ -40,27 +38,27 @@ + android:visibility="gone" + app:popupTheme="?attr/actionbarPopupStyle" /> + android:elevation="4dp" + android:orientation="horizontal"> + android:scaleType="fitCenter" /> + android:marqueeRepeatLimit="marquee_forever" + android:scrollHorizontally="true" + android:singleLine="true" + android:text="@string/main.title"> - + + android:text="@string/main.artist" /> + android:visibility="gone" /> - - - - - - + android:src="?attr/actionbar_backward" /> + + + + + + + android:id="@+id/now_playing_fragment_container" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:clickable="true" /> diff --git a/app/src/main/res/layout/abstract_fragment_container.xml b/app/src/main/res/layout/abstract_fragment_container.xml index 6d19b2b..7d3e7e5 100644 --- a/app/src/main/res/layout/abstract_fragment_container.xml +++ b/app/src/main/res/layout/abstract_fragment_container.xml @@ -3,4 +3,4 @@ android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_marginTop="?attr/actionBarSize"/> + android:layout_marginTop="?attr/actionBarSize" /> diff --git a/app/src/main/res/layout/abstract_recycler_fragment.xml b/app/src/main/res/layout/abstract_recycler_fragment.xml index 609e093..df466c5 100644 --- a/app/src/main/res/layout/abstract_recycler_fragment.xml +++ b/app/src/main/res/layout/abstract_recycler_fragment.xml @@ -5,10 +5,9 @@ android:layout_height="fill_parent"> + android:orientation="vertical"> + android:paddingRight="@dimen/FastScroller.LeftAlignedMargin" + android:scrollbarStyle="outsideOverlay" + android:scrollbars="vertical" /> + android:layout_alignParentRight="true" /> diff --git a/app/src/main/res/layout/actionbar_spinner.xml b/app/src/main/res/layout/actionbar_spinner.xml index 19c5ead..97f5201 100644 --- a/app/src/main/res/layout/actionbar_spinner.xml +++ b/app/src/main/res/layout/actionbar_spinner.xml @@ -1,8 +1,7 @@ + android:overlapAnchor="false" + android:prompt="@string/common.appname" /> diff --git a/app/src/main/res/layout/album_cell_item.xml b/app/src/main/res/layout/album_cell_item.xml index b2f341f..f2492c5 100644 --- a/app/src/main/res/layout/album_cell_item.xml +++ b/app/src/main/res/layout/album_cell_item.xml @@ -5,10 +5,10 @@ android:layout_margin="2dp"> + android:background="?attr/selectableItemBackground" + android:orientation="vertical"> + android:layout_height="match_parent" /> + android:paddingLeft="2dp" + android:paddingTop="4dp"> + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="?android:textColorPrimary" /> + android:textColor="?android:textColorSecondary" + android:textSize="12sp" /> + android:src="?attr/download_none" /> diff --git a/app/src/main/res/layout/album_list_header.xml b/app/src/main/res/layout/album_list_header.xml index 7d8c873..d200a05 100644 --- a/app/src/main/res/layout/album_list_header.xml +++ b/app/src/main/res/layout/album_list_header.xml @@ -7,23 +7,23 @@ + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="?attr/colorAccent" + android:textStyle="bold" /> + android:layout_marginRight="6dp" + android:text="@string/main.albums_per_folder" + android:textColor="?android:textColorPrimary" /> diff --git a/app/src/main/res/layout/album_list_item.xml b/app/src/main/res/layout/album_list_item.xml index dada80b..121b08c 100644 --- a/app/src/main/res/layout/album_list_item.xml +++ b/app/src/main/res/layout/album_list_item.xml @@ -1,10 +1,10 @@ + android:id="@id/drag_handle" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:background="?attr/selectableItemBackground" + android:orientation="horizontal"> + android:layout_gravity="left|center_vertical" /> @@ -30,27 +30,27 @@ android:id="@+id/album_title" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceMedium" - android:maxLines="1" android:ellipsize="marquee" android:paddingBottom="6dip" - android:textColor="?android:textColorPrimary"/> + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="?android:textColorPrimary" /> + android:textAppearance="?android:attr/textAppearanceSmall" + android:textColor="?android:textColorSecondary" /> + android:src="?attr/download_none" /> diff --git a/app/src/main/res/layout/appwidget4x1.xml b/app/src/main/res/layout/appwidget4x1.xml index 34afe62..ee4dae2 100644 --- a/app/src/main/res/layout/appwidget4x1.xml +++ b/app/src/main/res/layout/appwidget4x1.xml @@ -1,12 +1,12 @@ + android:minHeight="40dp" + android:minWidth="250dp" + android:orientation="horizontal"> + android:orientation="vertical"> + android:textStyle="bold"> - + @@ -83,27 +83,27 @@ + android:src="@drawable/media_start_dark" /> + android:src="@drawable/media_forward_dark" /> diff --git a/app/src/main/res/layout/appwidget4x2.xml b/app/src/main/res/layout/appwidget4x2.xml index c6788e0..75a6f8a 100644 --- a/app/src/main/res/layout/appwidget4x2.xml +++ b/app/src/main/res/layout/appwidget4x2.xml @@ -1,12 +1,12 @@ + android:minHeight="110dp" + android:minWidth="250dp" + android:orientation="horizontal"> + android:paddingTop="4dip"> + android:textStyle="bold"> - + - @@ -101,35 +101,35 @@ + android:paddingTop="4dip"> + android:src="@drawable/media_start_dark" /> + android:src="@drawable/media_forward_dark" /> diff --git a/app/src/main/res/layout/appwidget4x3.xml b/app/src/main/res/layout/appwidget4x3.xml index 4762d75..ecab87f 100644 --- a/app/src/main/res/layout/appwidget4x3.xml +++ b/app/src/main/res/layout/appwidget4x3.xml @@ -1,82 +1,82 @@ + android:orientation="vertical"> + android:paddingTop="4dip"> + android:textStyle="bold"> - + @@ -91,27 +91,27 @@ + android:src="@drawable/media_start_dark" /> + android:src="@drawable/media_forward_dark" /> diff --git a/app/src/main/res/layout/appwidget4x4.xml b/app/src/main/res/layout/appwidget4x4.xml index e6d4db0..386ff11 100644 --- a/app/src/main/res/layout/appwidget4x4.xml +++ b/app/src/main/res/layout/appwidget4x4.xml @@ -1,83 +1,83 @@ + android:orientation="vertical"> - + android:paddingTop="4dip"> + android:textStyle="bold"> - + @@ -89,31 +89,31 @@ android:gravity="bottom" android:orientation="horizontal" android:paddingBottom="4dip" - android:paddingTop="4dip" > + android:paddingTop="4dip"> + android:src="@drawable/media_start_dark" /> + android:src="@drawable/media_forward_dark" /> diff --git a/app/src/main/res/layout/basic_art_item.xml b/app/src/main/res/layout/basic_art_item.xml index 354b975..0215423 100644 --- a/app/src/main/res/layout/basic_art_item.xml +++ b/app/src/main/res/layout/basic_art_item.xml @@ -1,34 +1,34 @@ + android:background="?attr/selectableItemBackground" + android:orientation="horizontal"> + android:layout_gravity="left|center_vertical" /> + android:textColor="?android:textColorPrimary" /> + android:src="?attr/download_none" /> diff --git a/app/src/main/res/layout/basic_cell_item.xml b/app/src/main/res/layout/basic_cell_item.xml index 49b951a..b0b8fa9 100644 --- a/app/src/main/res/layout/basic_cell_item.xml +++ b/app/src/main/res/layout/basic_cell_item.xml @@ -5,41 +5,41 @@ android:layout_margin="2dp"> + android:background="?attr/selectableItemBackground" + android:orientation="vertical"> + android:layout_height="match_parent" /> + android:paddingLeft="2dp" + android:paddingTop="4dp"> + android:paddingLeft="@dimen/Card.TextLeftPadding" + android:singleLine="true" + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="?android:textColorPrimary" /> + android:src="?attr/download_none" /> diff --git a/app/src/main/res/layout/basic_choice_item.xml b/app/src/main/res/layout/basic_choice_item.xml index 3c0e766..8995c49 100644 --- a/app/src/main/res/layout/basic_choice_item.xml +++ b/app/src/main/res/layout/basic_choice_item.xml @@ -1,27 +1,27 @@ + android:background="?attr/selectableItemBackground" + android:orientation="horizontal"> + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="?android:textColorPrimary" /> + android:checkMark="?android:attr/listChoiceIndicatorMultiple" /> diff --git a/app/src/main/res/layout/basic_count_item.xml b/app/src/main/res/layout/basic_count_item.xml index 934cff8..39570e0 100644 --- a/app/src/main/res/layout/basic_count_item.xml +++ b/app/src/main/res/layout/basic_count_item.xml @@ -9,29 +9,29 @@ android:id="@+id/basic_count_name" android:layout_width="wrap_content" android:layout_height="fill_parent" - android:textAppearance="?android:attr/textAppearanceMedium" + android:background="@android:color/transparent" android:gravity="left|center_vertical" android:paddingLeft="6dip" android:paddingRight="6dip" - android:background="@android:color/transparent" android:text="Text" - android:textColor="?android:textColorPrimary"/> + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="?android:textColorPrimary" /> + android:textSize="11sp" + android:visibility="gone" /> diff --git a/app/src/main/res/layout/basic_header.xml b/app/src/main/res/layout/basic_header.xml index 8ee53df..69e6a31 100644 --- a/app/src/main/res/layout/basic_header.xml +++ b/app/src/main/res/layout/basic_header.xml @@ -3,11 +3,11 @@ android:id="@+id/item_name" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:textAppearance="?android:attr/textAppearanceMedium" android:background="@android:color/transparent" - android:textColor="?attr/colorAccent" - android:textStyle="bold" + android:paddingBottom="8dp" android:paddingLeft="6dp" android:paddingRight="6dp" android:paddingTop="8dp" - android:paddingBottom="8dp"/> + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="?attr/colorAccent" + android:textStyle="bold" /> diff --git a/app/src/main/res/layout/basic_list_item.xml b/app/src/main/res/layout/basic_list_item.xml index 98e123b..cfe22d5 100644 --- a/app/src/main/res/layout/basic_list_item.xml +++ b/app/src/main/res/layout/basic_list_item.xml @@ -1,28 +1,28 @@ + android:background="?attr/selectableItemBackground" + android:orientation="horizontal"> + android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="?android:textColorPrimary" /> + android:src="?attr/download_none" /> diff --git a/app/src/main/res/layout/cache_location_buttons.xml b/app/src/main/res/layout/cache_location_buttons.xml index b77108e..156d980 100644 --- a/app/src/main/res/layout/cache_location_buttons.xml +++ b/app/src/main/res/layout/cache_location_buttons.xml @@ -1,19 +1,19 @@ + android:layout_gravity="center" + android:orientation="horizontal">