From ab624be93da0ea1c90db5789b6129d2ee0a21c55 Mon Sep 17 00:00:00 2001 From: Nite Date: Mon, 13 Jan 2020 21:20:52 +0100 Subject: [PATCH 1/2] Implemented five star rating --- .../moire/ultrasonic/domain/MusicDirectory.kt | 4 +- .../api/subsonic/SubsonicApiSetRatingTest.kt | 55 ++++++++ .../api/subsonic/SubsonicAPIDefinition.kt | 6 + .../ultrasonic/activity/DownloadActivity.java | 124 ++++++++++++++++-- .../ultrasonic/fragment/SettingsFragment.java | 18 ++- .../service/CachedMusicService.java | 7 +- .../ultrasonic/service/DownloadService.java | 2 + .../service/DownloadServiceImpl.java | 43 +++++- .../DownloadServiceLifecycleSupport.java | 15 +++ .../ultrasonic/service/MusicService.java | 2 + .../ultrasonic/service/RESTMusicService.java | 11 ++ .../org/moire/ultrasonic/util/Constants.java | 1 + .../java/org/moire/ultrasonic/util/Util.java | 30 +++++ .../moire/ultrasonic/view/EntryAdapter.java | 7 + .../org/moire/ultrasonic/view/SongView.java | 107 +++++++++------ .../domain/APIMusicDirectoryConverter.kt | 2 + .../moire/ultrasonic/featureflags/Feature.kt | 6 +- .../src/main/res/layout-land/download.xml | 92 ++++++++++++- .../src/main/res/layout-port/download.xml | 96 ++++++++++++-- .../main/res/layout/notification_large.xml | 74 ++++++++++- .../src/main/res/layout/now_playing.xml | 89 +++++++------ .../src/main/res/layout/song_list_item.xml | 60 +++++++++ ultrasonic/src/main/res/values-es/strings.xml | 4 + ultrasonic/src/main/res/values-fr/strings.xml | 4 + ultrasonic/src/main/res/values-hu/strings.xml | 4 + ultrasonic/src/main/res/values-nl/strings.xml | 4 + ultrasonic/src/main/res/values-pl/strings.xml | 4 + .../src/main/res/values-pt-rBR/strings.xml | 4 + ultrasonic/src/main/res/values-pt/strings.xml | 4 + ultrasonic/src/main/res/values/strings.xml | 4 + ultrasonic/src/main/res/xml/settings.xml | 6 + .../domain/APIMusicDirectoryConverterTest.kt | 4 +- 32 files changed, 765 insertions(+), 128 deletions(-) create mode 100644 core/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicApiSetRatingTest.kt diff --git a/core/domain/src/main/kotlin/org/moire/ultrasonic/domain/MusicDirectory.kt b/core/domain/src/main/kotlin/org/moire/ultrasonic/domain/MusicDirectory.kt index 7475c701..530bb49b 100644 --- a/core/domain/src/main/kotlin/org/moire/ultrasonic/domain/MusicDirectory.kt +++ b/core/domain/src/main/kotlin/org/moire/ultrasonic/domain/MusicDirectory.kt @@ -63,7 +63,9 @@ class MusicDirectory { var type: String? = null, var created: Date? = null, var closeness: Int = 0, - var bookmarkPosition: Int = 0 + var bookmarkPosition: Int = 0, + var userRating: Int? = null, + var averageRating: Float? = null ) : Serializable { fun setDuration(duration: Long) { this.duration = duration.toInt() diff --git a/core/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicApiSetRatingTest.kt b/core/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicApiSetRatingTest.kt new file mode 100644 index 00000000..234fd901 --- /dev/null +++ b/core/subsonic-api/src/integrationTest/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicApiSetRatingTest.kt @@ -0,0 +1,55 @@ +package org.moire.ultrasonic.api.subsonic + +import org.amshove.kluent.`should be` +import org.junit.Test +import org.moire.ultrasonic.api.subsonic.response.SubsonicResponse + +/** + * Integration test for [SubsonicAPIClient] for setRating request. + */ +class SubsonicApiSetRatingTest : SubsonicAPIClientTest() { + @Test + fun `Should parse setRating ok response`() { + val id = "110" + val rating = 3 + + mockWebServerRule.enqueueResponse("ping_ok.json") + + val response = client.api.setRating(id, rating).execute() + + assertResponseSuccessful(response) + response.body()?.status `should be` SubsonicResponse.Status.OK + } + + @Test + fun `Should parse setRating error response`() { + val id = "110223" + val rating = 5 + + checkErrorCallParsed(mockWebServerRule) { + client.api.setRating(id, rating).execute() + } + } + + @Test + fun `Should pass id parameter`() { + val id = "110" + val rating = 5 + + mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", + expectedParam = "id=$id") { + client.api.setRating(id, rating).execute() + } + } + + @Test + fun `Should pass rating parameter`() { + val id = "110" + val rating = 5 + + mockWebServerRule.assertRequestParam(responseResourceName = "ping_ok.json", + expectedParam = "rating=$rating") { + client.api.setRating(id, rating).execute() + } + } +} diff --git a/core/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIDefinition.kt b/core/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIDefinition.kt index d867d452..bc74811d 100644 --- a/core/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIDefinition.kt +++ b/core/subsonic-api/src/main/kotlin/org/moire/ultrasonic/api/subsonic/SubsonicAPIDefinition.kt @@ -79,6 +79,12 @@ interface SubsonicAPIDefinition { @Query("artistId") artistId: String? = null ): Call + @GET("setRating.view") + fun setRating( + @Query("id") id: String, + @Query("rating") rating: Int + ): Call + @GET("getArtist.view") fun getArtist(@Query("id") id: String): Call diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/DownloadActivity.java b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/DownloadActivity.java index 6fd0f884..227170fc 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/DownloadActivity.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/DownloadActivity.java @@ -50,11 +50,15 @@ import android.widget.TextView; import android.widget.ViewFlipper; import com.mobeta.android.dslv.DragSortListView; + +import org.koin.java.standalone.KoinJavaComponent; import org.moire.ultrasonic.R; import org.moire.ultrasonic.domain.MusicDirectory; import org.moire.ultrasonic.domain.MusicDirectory.Entry; import org.moire.ultrasonic.domain.PlayerState; import org.moire.ultrasonic.domain.RepeatMode; +import org.moire.ultrasonic.featureflags.Feature; +import org.moire.ultrasonic.featureflags.FeatureStorage; import org.moire.ultrasonic.service.DownloadFile; import org.moire.ultrasonic.service.DownloadService; import org.moire.ultrasonic.service.MusicService; @@ -119,6 +123,15 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi private SilentBackgroundTask onProgressChangedTask; LinearLayout visualizerViewLayout; private MenuItem starMenuItem; + private LinearLayout ratingLinearLayout; + private ImageView fiveStar1ImageView; + private ImageView fiveStar2ImageView; + private ImageView fiveStar3ImageView; + private ImageView fiveStar4ImageView; + private ImageView fiveStar5ImageView; + private boolean useFiveStarRating; + private Drawable hollowStar; + private Drawable fullStar; /** * Called when the activity is first created. @@ -136,6 +149,8 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi int width = size.x; int height = size.y; + useFiveStarRating = KoinJavaComponent.get(FeatureStorage.class).isFeatureEnabled(Feature.FIVE_STAR_RATING); + swipeDistance = (width + height) * PERCENTAGE_OF_SCREEN_FOR_SWIPE / 100; swipeVelocity = swipeDistance; gestureScanner = new GestureDetector(this, this); @@ -162,6 +177,54 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi visualizerViewLayout = (LinearLayout) findViewById(R.id.download_visualizer_view_layout); + ratingLinearLayout = findViewById(R.id.song_rating); + fiveStar1ImageView = findViewById(R.id.song_five_star_1); + fiveStar2ImageView = findViewById(R.id.song_five_star_2); + fiveStar3ImageView = findViewById(R.id.song_five_star_3); + fiveStar4ImageView = findViewById(R.id.song_five_star_4); + fiveStar5ImageView = findViewById(R.id.song_five_star_5); + + if (!useFiveStarRating) ratingLinearLayout.setVisibility(View.GONE); + + hollowStar = Util.getDrawableFromAttribute(SubsonicTabActivity.getInstance(), R.attr.star_hollow); + fullStar = Util.getDrawableFromAttribute(SubsonicTabActivity.getInstance(), R.attr.star_full); + + fiveStar1ImageView.setOnClickListener(new View.OnClickListener() + { + @Override + public void onClick(final View view) { + setSongRating(1); + } + }); + fiveStar2ImageView.setOnClickListener(new View.OnClickListener() + { + @Override + public void onClick(final View view) { + setSongRating(2); + } + }); + fiveStar3ImageView.setOnClickListener(new View.OnClickListener() + { + @Override + public void onClick(final View view) { + setSongRating(3); + } + }); + fiveStar4ImageView.setOnClickListener(new View.OnClickListener() + { + @Override + public void onClick(final View view) { + setSongRating(4); + } + }); + fiveStar5ImageView.setOnClickListener(new View.OnClickListener() + { + @Override + public void onClick(final View view) { + setSongRating(5); + } + }); + View.OnTouchListener touchListener = new View.OnTouchListener() { @Override @@ -726,22 +789,20 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi currentSong = downloadFile.getSong(); } + if (useFiveStarRating) starMenuItem.setVisible(false); + if (currentSong != null) { - final Drawable starDrawable = currentSong.getStarred() ? Util.getDrawableFromAttribute(SubsonicTabActivity.getInstance(), R.attr.star_full) : Util.getDrawableFromAttribute(SubsonicTabActivity.getInstance(), R.attr.star_hollow); - if (starMenuItem != null) { - starMenuItem.setIcon(starDrawable); + starMenuItem.setIcon(currentSong.getStarred() ? fullStar : hollowStar); } } else { - final Drawable starDrawable = Util.getDrawableFromAttribute(SubsonicTabActivity.getInstance(), R.attr.star_hollow); - if (starMenuItem != null) { - starMenuItem.setIcon(starDrawable); + starMenuItem.setIcon(hollowStar); } } @@ -974,12 +1035,12 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi if (isStarred) { - starMenuItem.setIcon(Util.getDrawableFromAttribute(SubsonicTabActivity.getInstance(), R.attr.star_hollow)); + starMenuItem.setIcon(hollowStar); currentSong.setStarred(false); } else { - starMenuItem.setIcon(Util.getDrawableFromAttribute(SubsonicTabActivity.getInstance(), R.attr.star_full)); + starMenuItem.setIcon(fullStar); currentSong.setStarred(true); } @@ -1320,6 +1381,8 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi downloadTrackTextView.setText(trackFormat); downloadTotalDurationTextView.setText(duration); getImageLoader().loadImage(albumArtImageView, currentSong, true, 0, false, true); + + displaySongRating(); } else { @@ -1440,6 +1503,9 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi break; } + // TODO: It would be a lot nicer if DownloadService would send an event when this is necessary instead of updating every time + displaySongRating(); + onProgressChangedTask = null; } }; @@ -1580,4 +1646,46 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi { return progressBar; } + + private void displaySongRating() + { + int rating = currentSong.getUserRating() == null ? 0 : currentSong.getUserRating(); + fiveStar1ImageView.setImageDrawable(rating > 0 ? fullStar : hollowStar); + fiveStar2ImageView.setImageDrawable(rating > 1 ? fullStar : hollowStar); + fiveStar3ImageView.setImageDrawable(rating > 2 ? fullStar : hollowStar); + fiveStar4ImageView.setImageDrawable(rating > 3 ? fullStar : hollowStar); + fiveStar5ImageView.setImageDrawable(rating > 4 ? fullStar : hollowStar); + } + + private void setSongRating(final int rating) + { + if (currentSong == null) + { + return; + } + + final String id = currentSong.getId(); + + currentSong.setUserRating(rating); + displaySongRating(); + getDownloadService().updateNotification(); + + new Thread(new Runnable() + { + @Override + public void run() + { + final MusicService musicService = MusicServiceFactory.getMusicService(DownloadActivity.this); + + try + { + musicService.setRating(id, rating, DownloadActivity.this, null); + } + catch (Exception e) + { + Log.e(TAG, e.getMessage(), e); + } + } + }).start(); + } } diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SettingsFragment.java b/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SettingsFragment.java index 4dc2fe6f..204cb880 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SettingsFragment.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/fragment/SettingsFragment.java @@ -172,10 +172,11 @@ public class SettingsFragment extends PreferenceFragment } private void setupFeatureFlagsPreferences() { + final FeatureStorage featureStorage = KoinJavaComponent.get(FeatureStorage.class); + CheckBoxPreference ffImageLoader = (CheckBoxPreference) findPreference( Constants.PREFERENCES_KEY_FF_IMAGE_LOADER); - final FeatureStorage featureStorage = KoinJavaComponent.get(FeatureStorage.class); if (ffImageLoader != null) { ffImageLoader.setChecked(featureStorage.isFeatureEnabled(Feature.NEW_IMAGE_DOWNLOADER)); ffImageLoader.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { @@ -187,6 +188,21 @@ public class SettingsFragment extends PreferenceFragment } }); } + + CheckBoxPreference useFiveStarRating = (CheckBoxPreference) findPreference( + Constants.PREFERENCES_KEY_USE_FIVE_STAR_RATING); + + if (useFiveStarRating != null) { + useFiveStarRating.setChecked(featureStorage.isFeatureEnabled(Feature.FIVE_STAR_RATING)); + useFiveStarRating.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object o) { + featureStorage.changeFeatureFlag(Feature.FIVE_STAR_RATING, (Boolean) o); + return true; + } + }); + } + } private void setupGaplessControlSettingsV14() { diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/CachedMusicService.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/CachedMusicService.java index 38c27e44..d3ed1276 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/CachedMusicService.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/CachedMusicService.java @@ -385,7 +385,6 @@ public class CachedMusicService implements MusicService public void star(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception { musicService.star(id, albumId, artistId, context, progressListener); - } @Override @@ -394,6 +393,12 @@ public class CachedMusicService implements MusicService musicService.unstar(id, albumId, artistId, context, progressListener); } + @Override + public void setRating(String id, int rating, Context context, ProgressListener progressListener) throws Exception + { + musicService.setRating(id, rating, context, progressListener); + } + @Override public List getGenres(Context context, ProgressListener progressListener) throws Exception { diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadService.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadService.java index 63e36a13..1d1c412d 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadService.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadService.java @@ -144,4 +144,6 @@ public interface DownloadService void stopJukeboxService(); void startJukeboxService(); + + void updateNotification(); } diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadServiceImpl.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadServiceImpl.java index bcb3023c..0b76ce67 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadServiceImpl.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadServiceImpl.java @@ -39,9 +39,11 @@ import android.os.PowerManager; import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationManagerCompat; import android.util.Log; +import android.view.View; import android.widget.RemoteViews; import android.widget.SeekBar; +import org.koin.java.standalone.KoinJavaComponent; import org.moire.ultrasonic.R; import org.moire.ultrasonic.activity.DownloadActivity; import org.moire.ultrasonic.activity.SubsonicTabActivity; @@ -52,6 +54,8 @@ import org.moire.ultrasonic.domain.MusicDirectory.Entry; import org.moire.ultrasonic.domain.PlayerState; import org.moire.ultrasonic.domain.RepeatMode; import org.moire.ultrasonic.domain.UserInfo; +import org.moire.ultrasonic.featureflags.Feature; +import org.moire.ultrasonic.featureflags.FeatureStorage; import org.moire.ultrasonic.provider.UltraSonicAppWidgetProvider4x1; import org.moire.ultrasonic.provider.UltraSonicAppWidgetProvider4x2; import org.moire.ultrasonic.provider.UltraSonicAppWidgetProvider4x3; @@ -1238,11 +1242,7 @@ public class DownloadServiceImpl extends Service implements DownloadService // Only update notification is player state is one that will change the icon if (this.playerState == PlayerState.STARTED || this.playerState == PlayerState.PAUSED) { - if (Util.isNotificationEnabled(this)) { - final NotificationManagerCompat notificationManager = - NotificationManagerCompat.from(this); - notificationManager.notify(NOTIFICATION_ID, buildForegroundNotification()); - } + updateNotification(); tabInstance.showNowPlaying(); } } @@ -2071,6 +2071,16 @@ public class DownloadServiceImpl extends Service implements DownloadService } } + @Override + public void updateNotification() + { + if (Util.isNotificationEnabled(this)) { + final NotificationManagerCompat notificationManager = + NotificationManagerCompat.from(this); + notificationManager.notify(NOTIFICATION_ID, buildForegroundNotification()); + } + } + @SuppressWarnings("IconColors") private Notification buildForegroundNotification() { NotificationCompat.Builder builder = new NotificationCompat.Builder(this); @@ -2103,6 +2113,7 @@ public class DownloadServiceImpl extends Service implements DownloadService final String title = song.getTitle(); final String text = song.getArtist(); final String album = song.getAlbum(); + final int rating = song.getUserRating() == null ? 0 : song.getUserRating(); final int imageSize = Util.getNotificationImageSize(this); try { @@ -2127,6 +2138,17 @@ public class DownloadServiceImpl extends Service implements DownloadService contentView.setTextViewText(R.id.album, album); bigView.setTextViewText(R.id.album, album); + boolean useFiveStarRating = KoinJavaComponent.get(FeatureStorage.class).isFeatureEnabled(Feature.FIVE_STAR_RATING); + if (!useFiveStarRating) bigView.setViewVisibility(R.id.notification_rating, View.INVISIBLE); + else + { + bigView.setImageViewResource(R.id.notification_five_star_1, rating > 0 ? R.drawable.ic_star_full_dark : R.drawable.ic_star_hollow_dark); + bigView.setImageViewResource(R.id.notification_five_star_2, rating > 1 ? R.drawable.ic_star_full_dark : R.drawable.ic_star_hollow_dark); + bigView.setImageViewResource(R.id.notification_five_star_3, rating > 2 ? R.drawable.ic_star_full_dark : R.drawable.ic_star_hollow_dark); + bigView.setImageViewResource(R.id.notification_five_star_4, rating > 3 ? R.drawable.ic_star_full_dark : R.drawable.ic_star_hollow_dark); + bigView.setImageViewResource(R.id.notification_five_star_5, rating > 4 ? R.drawable.ic_star_full_dark : R.drawable.ic_star_hollow_dark); + } + Notification notification = builder.build(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { notification.bigContentView = bigView; @@ -2135,6 +2157,17 @@ public class DownloadServiceImpl extends Service implements DownloadService return notification; } + public void setSongRating(final int rating) + { + if (!new FeatureStorage(this).isFeatureEnabled(Feature.FIVE_STAR_RATING)) + return; + + final Entry song = currentPlaying.getSong(); + song.setUserRating(rating); + + updateNotification(); + } + private class BufferTask extends CancellableTask { private final DownloadFile downloadFile; diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadServiceLifecycleSupport.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadServiceLifecycleSupport.java index d9af9881..1ae1eaeb 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadServiceLifecycleSupport.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadServiceLifecycleSupport.java @@ -329,6 +329,21 @@ public class DownloadServiceLifecycleSupport case KeyEvent.KEYCODE_MEDIA_PAUSE: downloadService.pause(); break; + case KeyEvent.KEYCODE_1: + downloadService.setSongRating(1); + break; + case KeyEvent.KEYCODE_2: + downloadService.setSongRating(2); + break; + case KeyEvent.KEYCODE_3: + downloadService.setSongRating(3); + break; + case KeyEvent.KEYCODE_4: + downloadService.setSongRating(4); + break; + case KeyEvent.KEYCODE_5: + downloadService.setSongRating(5); + break; default: break; } diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/MusicService.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/MusicService.java index 17d3b42d..df66ca78 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/MusicService.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/MusicService.java @@ -59,6 +59,8 @@ public interface MusicService void unstar(String id, String albumId, String artistId, Context context, ProgressListener progressListener) throws Exception; + void setRating(String id, int rating, Context context, ProgressListener progressListener) throws Exception; + List getMusicFolders(boolean refresh, Context context, ProgressListener progressListener) throws Exception; Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) throws Exception; diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/RESTMusicService.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/RESTMusicService.java index 74e146d7..cd45a62e 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/RESTMusicService.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/RESTMusicService.java @@ -238,6 +238,17 @@ public class RESTMusicService implements MusicService { checkResponseSuccessful(response); } + @Override + public void setRating(String id, + int rating, + Context context, + ProgressListener progressListener) throws Exception { + updateProgressListener(progressListener, R.string.parser_reading); + Response response = subsonicAPIClient.getApi() + .setRating(id, rating).execute(); + checkResponseSuccessful(response); + } + @Override public MusicDirectory getMusicDirectory(String id, String name, diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/util/Constants.java b/ultrasonic/src/main/java/org/moire/ultrasonic/util/Constants.java index 2fdb0c79..d0ca72b7 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/util/Constants.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/util/Constants.java @@ -131,6 +131,7 @@ public final class Constants public static final String PREFERENCES_KEY_SCAN_MEDIA = "scanMedia"; public static final String PREFERENCES_KEY_IMAGE_LOADER_CONCURRENCY = "imageLoaderConcurrency"; public static final String PREFERENCES_KEY_FF_IMAGE_LOADER = "ff_new_image_loader"; + public static final String PREFERENCES_KEY_USE_FIVE_STAR_RATING = "use_five_star_rating"; // Number of free trial days for non-licensed servers. public static final int FREE_TRIAL_DAYS = 30; diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/util/Util.java b/ultrasonic/src/main/java/org/moire/ultrasonic/util/Util.java index e9673e23..5259037d 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/util/Util.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/util/Util.java @@ -1306,6 +1306,36 @@ public class Util extends DownloadActivity intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_STOP)); pendingIntent = PendingIntent.getService(context, 0, intent, 0); views.setOnClickPendingIntent(R.id.control_stop, pendingIntent); + + intent = new Intent("RATE_1"); + intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); + intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_1)); + pendingIntent = PendingIntent.getService(context, 0, intent, 0); + views.setOnClickPendingIntent(R.id.notification_five_star_1, pendingIntent); + + intent = new Intent("RATE_2"); + intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); + intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_2)); + pendingIntent = PendingIntent.getService(context, 0, intent, 0); + views.setOnClickPendingIntent(R.id.notification_five_star_2, pendingIntent); + + intent = new Intent("RATE_3"); + intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); + intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_3)); + pendingIntent = PendingIntent.getService(context, 0, intent, 0); + views.setOnClickPendingIntent(R.id.notification_five_star_3, pendingIntent); + + intent = new Intent("RATE_4"); + intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); + intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_4)); + pendingIntent = PendingIntent.getService(context, 0, intent, 0); + views.setOnClickPendingIntent(R.id.notification_five_star_4, pendingIntent); + + intent = new Intent("RATE_5"); + intent.setComponent(new ComponentName(context, DownloadServiceImpl.class)); + intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_5)); + pendingIntent = PendingIntent.getService(context, 0, intent, 0); + views.setOnClickPendingIntent(R.id.notification_five_star_5, pendingIntent); } public static int getNetworkTimeout(Context context) diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/view/EntryAdapter.java b/ultrasonic/src/main/java/org/moire/ultrasonic/view/EntryAdapter.java index ce229d65..2edcbfe5 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/view/EntryAdapter.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/view/EntryAdapter.java @@ -23,6 +23,7 @@ import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.CheckedTextView; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import org.moire.ultrasonic.activity.SubsonicTabActivity; import org.moire.ultrasonic.domain.MusicDirectory.Entry; @@ -120,6 +121,12 @@ public class EntryAdapter extends ArrayAdapter TextView status; TextView artist; TextView duration; + LinearLayout rating; + ImageView fiveStar1; + ImageView fiveStar2; + ImageView fiveStar3; + ImageView fiveStar4; + ImageView fiveStar5; ImageView star; ImageView drag; } diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/view/SongView.java b/ultrasonic/src/main/java/org/moire/ultrasonic/view/SongView.java index 20567820..24460f67 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/view/SongView.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/view/SongView.java @@ -28,10 +28,14 @@ import android.view.View; import android.widget.Checkable; import android.widget.CheckedTextView; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; +import org.koin.java.standalone.KoinJavaComponent; import org.moire.ultrasonic.R; import org.moire.ultrasonic.domain.MusicDirectory.Entry; +import org.moire.ultrasonic.featureflags.Feature; +import org.moire.ultrasonic.featureflags.FeatureStorage; import org.moire.ultrasonic.service.DownloadFile; import org.moire.ultrasonic.service.DownloadService; import org.moire.ultrasonic.service.DownloadServiceImpl; @@ -73,12 +77,15 @@ public class SongView extends UpdateView implements Checkable private boolean playing; private EntryAdapter.SongViewHolder viewHolder; private boolean maximized = false; + private boolean useFiveStarRating; public SongView(Context context) { super(context); this.context = context; + useFiveStarRating = KoinJavaComponent.get(FeatureStorage.class).isFeatureEnabled(Feature.FIVE_STAR_RATING); + String theme = Util.getTheme(context); boolean themesMatch = theme.equals(SongView.theme); inflater = LayoutInflater.from(this.context); @@ -124,6 +131,12 @@ public class SongView extends UpdateView implements Checkable inflater.inflate(song.isVideo() ? R.layout.video_list_item : R.layout.song_list_item, this, true); viewHolder = new EntryAdapter.SongViewHolder(); viewHolder.check = (CheckedTextView) findViewById(R.id.song_check); + viewHolder.rating = (LinearLayout) findViewById(R.id.song_rating); + viewHolder.fiveStar1 = (ImageView) findViewById(R.id.song_five_star_1); + viewHolder.fiveStar2 = (ImageView) findViewById(R.id.song_five_star_2); + viewHolder.fiveStar3 = (ImageView) findViewById(R.id.song_five_star_3); + viewHolder.fiveStar4 = (ImageView) findViewById(R.id.song_five_star_4); + viewHolder.fiveStar5 = (ImageView) findViewById(R.id.song_five_star_5); viewHolder.star = (ImageView) findViewById(R.id.song_star); viewHolder.drag = (ImageView) findViewById(R.id.song_drag); viewHolder.track = (TextView) findViewById(R.id.song_track); @@ -237,56 +250,59 @@ public class SongView extends UpdateView implements Checkable if (Util.isOffline(this.context)) { viewHolder.star.setVisibility(View.GONE); + viewHolder.rating.setVisibility(View.GONE); } else { - viewHolder.star.setImageDrawable(song.getStarred() ? starDrawable : starHollowDrawable); - - viewHolder.star.setOnClickListener(new View.OnClickListener() + if (useFiveStarRating) { - @Override - public void onClick(View view) - { - final boolean isStarred = song.getStarred(); - final String id = song.getId(); + viewHolder.star.setVisibility(View.GONE); - if (!isStarred) - { - viewHolder.star.setImageDrawable(starDrawable); - song.setStarred(true); - } - else - { - viewHolder.star.setImageDrawable(starHollowDrawable); - song.setStarred(false); - } + int rating = song.getUserRating() == null ? 0 : song.getUserRating(); + viewHolder.fiveStar1.setImageDrawable(rating > 0 ? starDrawable : starHollowDrawable); + viewHolder.fiveStar2.setImageDrawable(rating > 1 ? starDrawable : starHollowDrawable); + viewHolder.fiveStar3.setImageDrawable(rating > 2 ? starDrawable : starHollowDrawable); + viewHolder.fiveStar4.setImageDrawable(rating > 3 ? starDrawable : starHollowDrawable); + viewHolder.fiveStar5.setImageDrawable(rating > 4 ? starDrawable : starHollowDrawable); - new Thread(new Runnable() - { - @Override - public void run() - { - MusicService musicService = MusicServiceFactory.getMusicService(SongView.this.context); + } + else { + viewHolder.rating.setVisibility(View.GONE); + viewHolder.star.setImageDrawable(song.getStarred() ? starDrawable : starHollowDrawable); - try - { - if (!isStarred) - { - musicService.star(id, null, null, SongView.this.context, null); - } - else - { - musicService.unstar(id, null, null, SongView.this.context, null); - } - } - catch (Exception e) - { - Log.e(TAG, e.getMessage(), e); - } + viewHolder.star.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + final boolean isStarred = song.getStarred(); + final String id = song.getId(); + + if (!isStarred) { + viewHolder.star.setImageDrawable(starDrawable); + song.setStarred(true); + } else { + viewHolder.star.setImageDrawable(starHollowDrawable); + song.setStarred(false); } - }).start(); - } - }); + + new Thread(new Runnable() { + @Override + public void run() { + MusicService musicService = MusicServiceFactory.getMusicService(SongView.this.context); + + try { + if (!isStarred) { + musicService.star(id, null, null, SongView.this.context, null); + } else { + musicService.unstar(id, null, null, SongView.this.context, null); + } + } catch (Exception e) { + Log.e(TAG, e.getMessage(), e); + } + } + }).start(); + } + }); + } } update(); @@ -394,6 +410,13 @@ public class SongView extends UpdateView implements Checkable } } + int rating = song.getUserRating() == null ? 0 : song.getUserRating(); + viewHolder.fiveStar1.setImageDrawable(rating > 0 ? starDrawable : starHollowDrawable); + viewHolder.fiveStar2.setImageDrawable(rating > 1 ? starDrawable : starHollowDrawable); + viewHolder.fiveStar3.setImageDrawable(rating > 2 ? starDrawable : starHollowDrawable); + viewHolder.fiveStar4.setImageDrawable(rating > 3 ? starDrawable : starHollowDrawable); + viewHolder.fiveStar5.setImageDrawable(rating > 4 ? starDrawable : starHollowDrawable); + boolean playing = downloadService.getCurrentPlaying() == downloadFile; if (playing) diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/domain/APIMusicDirectoryConverter.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/domain/APIMusicDirectoryConverter.kt index e1acb18c..d68f1889 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/domain/APIMusicDirectoryConverter.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/domain/APIMusicDirectoryConverter.kt @@ -45,6 +45,8 @@ fun MusicDirectoryChild.toDomainEntity(): MusicDirectory.Entry = MusicDirectory. if (this@toDomainEntity.publishDate != null) { artist = dateFormat.format(this@toDomainEntity.publishDate!!.time) } + userRating = this@toDomainEntity.userRating + averageRating = this@toDomainEntity.averageRating } fun List.toDomainEntityList() = this.map { it.toDomainEntity() } diff --git a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/featureflags/Feature.kt b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/featureflags/Feature.kt index 1f0757a3..a92edbc4 100644 --- a/ultrasonic/src/main/kotlin/org/moire/ultrasonic/featureflags/Feature.kt +++ b/ultrasonic/src/main/kotlin/org/moire/ultrasonic/featureflags/Feature.kt @@ -10,5 +10,9 @@ enum class Feature( /** * Enables new image downloader implementation. */ - NEW_IMAGE_DOWNLOADER(false) + NEW_IMAGE_DOWNLOADER(false), + /** + * Enables five star rating system. + */ + FIVE_STAR_RATING(false) } diff --git a/ultrasonic/src/main/res/layout-land/download.xml b/ultrasonic/src/main/res/layout-land/download.xml index df93d6dc..84053a6b 100644 --- a/ultrasonic/src/main/res/layout-land/download.xml +++ b/ultrasonic/src/main/res/layout-land/download.xml @@ -26,15 +26,93 @@ a:contentDescription="@string/albumArt"/> + a:layout_height="fill_parent" + a:gravity="bottom" + a:orientation="vertical" > + + + + + + + + + + + + + + + + + diff --git a/ultrasonic/src/main/res/layout-port/download.xml b/ultrasonic/src/main/res/layout-port/download.xml index ab4c8b9e..d2f8d73a 100644 --- a/ultrasonic/src/main/res/layout-port/download.xml +++ b/ultrasonic/src/main/res/layout-port/download.xml @@ -28,16 +28,94 @@ a:contentDescription="@string/albumArt"/> + a:layout_height="fill_parent" + a:gravity="bottom" + a:orientation="vertical" > + + + + + + + + + + + + + + + + + + diff --git a/ultrasonic/src/main/res/layout/notification_large.xml b/ultrasonic/src/main/res/layout/notification_large.xml index ee2b3012..e3a3809f 100644 --- a/ultrasonic/src/main/res/layout/notification_large.xml +++ b/ultrasonic/src/main/res/layout/notification_large.xml @@ -4,14 +4,14 @@ xmlns:tools="http://schemas.android.com/tools" android:id="@+id/statusbar" android:layout_width="match_parent" - android:layout_height="128dp" + android:layout_height="150dp" android:orientation="horizontal" android:background="@color/background_color_dark" > @@ -41,7 +41,7 @@ android:layout_weight="1" android:ellipsize="marquee" android:focusable="true" - android:maxLines="1" + android:singleLine="true" tools:text="Track name" /> @@ -80,15 +80,75 @@ android:maxLines="1" tools:text="Album" /> - + + + + + + + + + + + + + + + - + - + + android:layout_height="wrap_content"> - + - + - + + + + + + android:layout_gravity="center|right" + android:layout_marginTop="2dip" + android:layout_marginRight="5dip" + android:layout_weight="0.0" + android:focusable="false" + android:src="?attr/media_pause" /> - - - - - \ No newline at end of file diff --git a/ultrasonic/src/main/res/layout/song_list_item.xml b/ultrasonic/src/main/res/layout/song_list_item.xml index 0591cf9c..cec22dbb 100644 --- a/ultrasonic/src/main/res/layout/song_list_item.xml +++ b/ultrasonic/src/main/res/layout/song_list_item.xml @@ -15,6 +15,66 @@ + + + + + + + + + + + + + + Habilitar nuevo cargador de imágenes + Use cinco estrellas para las canciones. + Utilice el sistema de calificación de cinco estrellas para canciones + en lugar de simplemente destacar / desestimar elementos. + diff --git a/ultrasonic/src/main/res/values-fr/strings.xml b/ultrasonic/src/main/res/values-fr/strings.xml index 7bf589b4..19dcdc5b 100644 --- a/ultrasonic/src/main/res/values-fr/strings.xml +++ b/ultrasonic/src/main/res/values-fr/strings.xml @@ -442,6 +442,10 @@ Actuellement, il n\'enregistre pas l\'image dans le stockage de l\'appareil et n\'utilise que le cache en mémoire. + Utiliser une note de cinq étoiles pour les chansons + Utiliser un système de notation à cinq étoiles pour les chansons + au lieu de simplement mettre en vedette / désactiver les éléments. + Drapeaux des fonctionnalités diff --git a/ultrasonic/src/main/res/values-hu/strings.xml b/ultrasonic/src/main/res/values-hu/strings.xml index bca57a9c..cfd1ae60 100644 --- a/ultrasonic/src/main/res/values-hu/strings.xml +++ b/ultrasonic/src/main/res/values-hu/strings.xml @@ -441,5 +441,9 @@ Jellemzők Zászlók Engedélyezzen új képbetöltőt + Öt csillagos értékelés használata a dalokhoz + Öt csillag használata az értékeléshez az egyszerű + csillaggal jelölés helyett. + diff --git a/ultrasonic/src/main/res/values-nl/strings.xml b/ultrasonic/src/main/res/values-nl/strings.xml index 08c70dfb..0b416312 100644 --- a/ultrasonic/src/main/res/values-nl/strings.xml +++ b/ultrasonic/src/main/res/values-nl/strings.xml @@ -442,5 +442,9 @@ Momenteel slaat het geen afbeeldingen op op de apparaatopslag en wordt alleen geheugencache gebruikt. Experimentele functies + Gebruik vijf sterren voor nummers + Gebruik vijf sterren ratingsysteem voor liedjes + in plaats van items simpelweg in de hoofdrol te zetten / niet te verwijderen. + diff --git a/ultrasonic/src/main/res/values-pl/strings.xml b/ultrasonic/src/main/res/values-pl/strings.xml index 541c3593..9148a556 100644 --- a/ultrasonic/src/main/res/values-pl/strings.xml +++ b/ultrasonic/src/main/res/values-pl/strings.xml @@ -455,5 +455,9 @@ ponieważ api Subsonic nie wspiera nowego sposobu autoryzacji dla użytkowników Włącza implementację modułu ładującego nowe obrazy. Obecnie nie zapisuje obrazów w pamięci urządzenia, tylko wykorzystuje tylko pamięć podręczną. Flagi funkcji + Użyj pięciu gwiazdek dla utworów + W przypadku utworów użyj systemu pięciu gwiazdek + zamiast po prostu grać gwiazdkami / bez gwiazd. + diff --git a/ultrasonic/src/main/res/values-pt-rBR/strings.xml b/ultrasonic/src/main/res/values-pt-rBR/strings.xml index 4c0c6dfa..f210d9b1 100644 --- a/ultrasonic/src/main/res/values-pt-rBR/strings.xml +++ b/ultrasonic/src/main/res/values-pt-rBR/strings.xml @@ -441,5 +441,9 @@ Bandeiras de recursos Ativar novo carregador de imagens + Use classificação de cinco estrelas para músicas + Use o sistema de classificação de cinco estrelas para músicas + em vez de simplesmente estrelar / não estrelar itens. + diff --git a/ultrasonic/src/main/res/values-pt/strings.xml b/ultrasonic/src/main/res/values-pt/strings.xml index 784e116f..90082b7c 100644 --- a/ultrasonic/src/main/res/values-pt/strings.xml +++ b/ultrasonic/src/main/res/values-pt/strings.xml @@ -441,5 +441,9 @@ Bandeiras de recursos Ativar novo carregador de imagens + Use classificação de cinco estrelas para músicas + Use o sistema de classificação de cinco estrelas para músicas + em vez de simplesmente estrelar / não estrelar itens. + diff --git a/ultrasonic/src/main/res/values/strings.xml b/ultrasonic/src/main/res/values/strings.xml index fe80ab0c..e4d9e28c 100644 --- a/ultrasonic/src/main/res/values/strings.xml +++ b/ultrasonic/src/main/res/values/strings.xml @@ -445,6 +445,10 @@ Enables new image loader implementation. Currently it doesn\'t save image in device storage and uses only cache in memory. + Use five star rating for songs + Use five star rating system for songs + instead of simply starring/unstarring items. + Feature Flags diff --git a/ultrasonic/src/main/res/xml/settings.xml b/ultrasonic/src/main/res/xml/settings.xml index a4a52386..27fcff8a 100644 --- a/ultrasonic/src/main/res/xml/settings.xml +++ b/ultrasonic/src/main/res/xml/settings.xml @@ -291,6 +291,12 @@ a:title="@string/feature_flags_image_loader_title" a:summary="@string/feature_flags_image_loader_description" /> + diff --git a/ultrasonic/src/test/kotlin/org/moire/ultrasonic/domain/APIMusicDirectoryConverterTest.kt b/ultrasonic/src/test/kotlin/org/moire/ultrasonic/domain/APIMusicDirectoryConverterTest.kt index 3e4a0f1a..107cbaf5 100644 --- a/ultrasonic/src/test/kotlin/org/moire/ultrasonic/domain/APIMusicDirectoryConverterTest.kt +++ b/ultrasonic/src/test/kotlin/org/moire/ultrasonic/domain/APIMusicDirectoryConverterTest.kt @@ -39,7 +39,7 @@ class APIMusicDirectoryConverterTest { transcodedSuffix = "some-transcoded-suffix", duration = 11, bitRate = 256, path = "some-path", isDir = true, isVideo = true, playCount = 323, discNumber = 2, created = Calendar.getInstance(), type = "some-type", - starred = Calendar.getInstance()) + starred = Calendar.getInstance(), userRating = 3, averageRating = 2.99F) val convertedEntity = entity.toDomainEntity() @@ -69,6 +69,8 @@ class APIMusicDirectoryConverterTest { starred `should be equal to` (entity.starred != null) discNumber `should equal` entity.discNumber type `should equal` entity.type + userRating `should equal` entity.userRating + averageRating `should equal` entity.averageRating } } From 99dbf236c9a9e48a4997d1fbaf59f6a750bcdf2b Mon Sep 17 00:00:00 2001 From: Nite Date: Sun, 23 Feb 2020 12:57:15 +0100 Subject: [PATCH 2/2] Fixed rating from notification --- .../ultrasonic/activity/DownloadActivity.java | 25 +------------------ .../ultrasonic/service/DownloadService.java | 2 ++ .../service/DownloadServiceImpl.java | 23 ++++++++++++++++- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/DownloadActivity.java b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/DownloadActivity.java index 227170fc..d96c0b90 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/activity/DownloadActivity.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/activity/DownloadActivity.java @@ -1660,32 +1660,9 @@ public class DownloadActivity extends SubsonicTabActivity implements OnGestureLi private void setSongRating(final int rating) { if (currentSong == null) - { return; - } - final String id = currentSong.getId(); - - currentSong.setUserRating(rating); displaySongRating(); - getDownloadService().updateNotification(); - - new Thread(new Runnable() - { - @Override - public void run() - { - final MusicService musicService = MusicServiceFactory.getMusicService(DownloadActivity.this); - - try - { - musicService.setRating(id, rating, DownloadActivity.this, null); - } - catch (Exception e) - { - Log.e(TAG, e.getMessage(), e); - } - } - }).start(); + getDownloadService().setSongRating(rating); } } diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadService.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadService.java index 1d1c412d..9e69b722 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadService.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadService.java @@ -146,4 +146,6 @@ public interface DownloadService void startJukeboxService(); void updateNotification(); + + void setSongRating(final int rating); } diff --git a/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadServiceImpl.java b/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadServiceImpl.java index 0b76ce67..26703631 100644 --- a/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadServiceImpl.java +++ b/ultrasonic/src/main/java/org/moire/ultrasonic/service/DownloadServiceImpl.java @@ -2159,12 +2159,33 @@ public class DownloadServiceImpl extends Service implements DownloadService public void setSongRating(final int rating) { - if (!new FeatureStorage(this).isFeatureEnabled(Feature.FIVE_STAR_RATING)) + if (!KoinJavaComponent.get(FeatureStorage.class).isFeatureEnabled(Feature.FIVE_STAR_RATING)) + return; + + if (currentPlaying == null) return; final Entry song = currentPlaying.getSong(); song.setUserRating(rating); + new Thread(new Runnable() + { + @Override + public void run() + { + final MusicService musicService = MusicServiceFactory.getMusicService(DownloadServiceImpl.this); + + try + { + musicService.setRating(song.getId(), rating, DownloadServiceImpl.this, null); + } + catch (Exception e) + { + Log.e(TAG, e.getMessage(), e); + } + } + }).start(); + updateNotification(); }