From 14204d1789deba299c9eb729a17d3b6d7ceee4d5 Mon Sep 17 00:00:00 2001 From: Karim Abou Zeid Date: Mon, 4 Apr 2016 15:35:12 +0200 Subject: [PATCH] Added big app widget. --- app/src/main/AndroidManifest.xml | 13 ++ .../gramophone/appwidgets/AppWidgetBig.java | 203 ++++++++++++++++++ .../palette/BitmapPaletteTranscoder.java | 2 +- .../gramophone/service/MusicService.java | 16 +- .../main/res/drawable-v21/widget_selector.xml | 3 + .../main/res/drawable/shadow_down_strong.xml | 8 + .../main/res/drawable/shadow_up_strong.xml | 8 + app/src/main/res/drawable/widget_selector.xml | 9 + app/src/main/res/layout/app_widget_big.xml | 97 +++++++++ .../main/res/layout/app_widget_classic.xml | 12 +- app/src/main/res/layout/app_widget_small.xml | 12 +- app/src/main/res/values/dimens.xml | 3 + app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/app_widget_big_info.xml | 12 ++ 14 files changed, 381 insertions(+), 18 deletions(-) create mode 100644 app/src/main/java/com/kabouzeid/gramophone/appwidgets/AppWidgetBig.java create mode 100644 app/src/main/res/drawable-v21/widget_selector.xml create mode 100644 app/src/main/res/drawable/shadow_down_strong.xml create mode 100644 app/src/main/res/drawable/shadow_up_strong.xml create mode 100644 app/src/main/res/drawable/widget_selector.xml create mode 100644 app/src/main/res/layout/app_widget_big.xml create mode 100644 app/src/main/res/xml/app_widget_big_info.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 94cd758c..c20d1349 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -126,6 +126,19 @@ + + + + + + + + 0; + } + + /** + * Handle a change notification coming over from + * {@link MusicService} + */ + public void notifyChange(final MusicService service, final String what) { + if (hasInstances(service)) { + if (MusicService.META_CHANGED.equals(what) || MusicService.PLAY_STATE_CHANGED.equals(what)) { + performUpdate(service, null); + } + } + } + + /** + * Update all active widget instances by pushing changes + */ + public void performUpdate(final MusicService service, final int[] appWidgetIds) { + final RemoteViews appWidgetView = new RemoteViews(service.getPackageName(), R.layout.app_widget_big); + + final boolean isPlaying = service.isPlaying(); + final Song song = service.getCurrentSong(); + + // Set the titles and artwork + if (TextUtils.isEmpty(song.title) && TextUtils.isEmpty(song.artistName)) { + appWidgetView.setViewVisibility(R.id.media_titles, View.INVISIBLE); + } else { + appWidgetView.setViewVisibility(R.id.media_titles, View.VISIBLE); + appWidgetView.setTextViewText(R.id.title, song.title); + appWidgetView.setTextViewText(R.id.text, song.artistName); + } + + // Set correct drawable for pause state + int playPauseRes = isPlaying ? R.drawable.ic_pause_white_24dp : R.drawable.ic_play_arrow_white_24dp; + appWidgetView.setImageViewBitmap(R.id.button_toggle_play_pause, createBitmap(Util.getTintedDrawable(service, playPauseRes, MaterialValueHelper.getPrimaryTextColor(service, false)), 1f)); + + // set prev/next button drawables + appWidgetView.setImageViewBitmap(R.id.button_next, createBitmap(Util.getTintedDrawable(service, R.drawable.ic_skip_next_white_24dp, MaterialValueHelper.getPrimaryTextColor(service, false)), 1f)); + appWidgetView.setImageViewBitmap(R.id.button_prev, createBitmap(Util.getTintedDrawable(service, R.drawable.ic_skip_previous_white_24dp, MaterialValueHelper.getPrimaryTextColor(service, false)), 1f)); + + // Link actions buttons to intents + linkButtons(service, appWidgetView); + + // load the album cover async and push the update on completion + Point p = Util.getScreenSize(service); + final int widgetImageSize = Math.min(p.x, p.y); + final Context appContext = service.getApplicationContext(); + service.runOnUiThread(new Runnable() { + @Override + public void run() { + if (target != null) { + Glide.clear(target); + } + target = SongGlideRequest.Builder.from(Glide.with(appContext), song) + .checkIgnoreMediaStore(appContext) + .asBitmap().build() + .into(new SimpleTarget(widgetImageSize, widgetImageSize) { + @Override + public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) { + update(resource); + } + + @Override + public void onLoadFailed(Exception e, Drawable errorDrawable) { + super.onLoadFailed(e, errorDrawable); + update(null); + } + + private void update(@Nullable Bitmap bitmap) { + appWidgetView.setViewVisibility(R.id.image, View.VISIBLE); + if (bitmap == null) { + appWidgetView.setImageViewResource(R.id.image, R.drawable.default_album_art); + } else { + appWidgetView.setImageViewBitmap(R.id.image, bitmap); + } + pushUpdate(appContext, appWidgetIds, appWidgetView); + } + }); + } + }); + } + + private Target target; // for cancellation + + /** + * Link up various button actions using {@link PendingIntent}. + */ + private void linkButtons(final Context context, final RemoteViews views) { + Intent action; + PendingIntent pendingIntent; + + final ComponentName serviceName = new ComponentName(context, MusicService.class); + + // Home + action = new Intent(context, MainActivity.class); + action.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); + pendingIntent = PendingIntent.getActivity(context, 0, action, 0); + views.setOnClickPendingIntent(R.id.clickable_area, pendingIntent); + + // Previous track + pendingIntent = buildPendingIntent(context, MusicService.ACTION_REWIND, serviceName); + views.setOnClickPendingIntent(R.id.button_prev, pendingIntent); + + // Play and pause + pendingIntent = buildPendingIntent(context, MusicService.ACTION_TOGGLE_PAUSE, serviceName); + views.setOnClickPendingIntent(R.id.button_toggle_play_pause, pendingIntent); + + // Next track + pendingIntent = buildPendingIntent(context, MusicService.ACTION_SKIP, serviceName); + views.setOnClickPendingIntent(R.id.button_next, pendingIntent); + } +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/glide/palette/BitmapPaletteTranscoder.java b/app/src/main/java/com/kabouzeid/gramophone/glide/palette/BitmapPaletteTranscoder.java index eee8f931..da05fec6 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/glide/palette/BitmapPaletteTranscoder.java +++ b/app/src/main/java/com/kabouzeid/gramophone/glide/palette/BitmapPaletteTranscoder.java @@ -29,6 +29,6 @@ public class BitmapPaletteTranscoder implements ResourceTranscoder playingQueue = new ArrayList<>(); @@ -938,6 +940,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP private void sendChangeInternal(final String what) { sendBroadcast(new Intent(what)); + appWidgetBig.notifyChange(this, what); appWidgetClassic.notifyChange(this, what); appWidgetSmall.notifyChange(this, what); } @@ -1162,11 +1165,14 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP final String command = intent.getStringExtra(EXTRA_APP_WIDGET_NAME); if (AppWidgetClassic.NAME.equals(command)) { - final int[] small = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS); - appWidgetClassic.performUpdate(MusicService.this, small); + final int[] ids = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS); + appWidgetClassic.performUpdate(MusicService.this, ids); } else if (AppWidgetSmall.NAME.equals(command)) { - final int[] small = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS); - appWidgetSmall.performUpdate(MusicService.this, small); + final int[] ids = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS); + appWidgetSmall.performUpdate(MusicService.this, ids); + } else if (AppWidgetBig.NAME.equals(command)) { + final int[] ids = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS); + appWidgetBig.performUpdate(MusicService.this, ids); } } }; diff --git a/app/src/main/res/drawable-v21/widget_selector.xml b/app/src/main/res/drawable-v21/widget_selector.xml new file mode 100644 index 00000000..f0360419 --- /dev/null +++ b/app/src/main/res/drawable-v21/widget_selector.xml @@ -0,0 +1,3 @@ + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shadow_down_strong.xml b/app/src/main/res/drawable/shadow_down_strong.xml new file mode 100644 index 00000000..c56b0959 --- /dev/null +++ b/app/src/main/res/drawable/shadow_down_strong.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shadow_up_strong.xml b/app/src/main/res/drawable/shadow_up_strong.xml new file mode 100644 index 00000000..bbe3ed2c --- /dev/null +++ b/app/src/main/res/drawable/shadow_up_strong.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/widget_selector.xml b/app/src/main/res/drawable/widget_selector.xml new file mode 100644 index 00000000..d7867f86 --- /dev/null +++ b/app/src/main/res/drawable/widget_selector.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/app_widget_big.xml b/app/src/main/res/layout/app_widget_big.xml new file mode 100644 index 00000000..11c19548 --- /dev/null +++ b/app/src/main/res/layout/app_widget_big.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/app_widget_classic.xml b/app/src/main/res/layout/app_widget_classic.xml index 35e33fe5..4451342f 100644 --- a/app/src/main/res/layout/app_widget_classic.xml +++ b/app/src/main/res/layout/app_widget_classic.xml @@ -32,27 +32,27 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" - android:background="@drawable/notification_selector" + android:background="@drawable/widget_selector" tools:src="@drawable/ic_skip_previous_white_24dp" - tools:tint="#fff" /> + tools:tint="@color/ate_secondary_text_dark" /> + tools:tint="@color/ate_secondary_text_dark" /> + tools:tint="@color/ate_secondary_text_dark" /> diff --git a/app/src/main/res/layout/app_widget_small.xml b/app/src/main/res/layout/app_widget_small.xml index 0121481b..fbfb1040 100644 --- a/app/src/main/res/layout/app_widget_small.xml +++ b/app/src/main/res/layout/app_widget_small.xml @@ -27,30 +27,30 @@ android:layout_width="0dp" android:layout_height="@dimen/app_widget_small_button_height" android:layout_weight="1" - android:background="@drawable/notification_selector" + android:background="@drawable/widget_selector" tools:ignore="ContentDescription" tools:src="@drawable/ic_skip_previous_white_24dp" - tools:tint="#fff" /> + tools:tint="@color/ate_secondary_text_dark" /> + tools:tint="@color/ate_secondary_text_dark" /> + tools:tint="@color/ate_secondary_text_dark" /> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 9b200137..304c8dc8 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -69,4 +69,7 @@ http://developer.android.com/guide/topics/appwidgets/index.html#CreatingLayout 250dp 40dp + 250dp + 110dp + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 613b69b4..2fdc304b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -245,6 +245,7 @@ Could not scan %d files. Listing files %s is the new start directory. + Phonograph - Big Phonograph - Classic Phonograph - Small diff --git a/app/src/main/res/xml/app_widget_big_info.xml b/app/src/main/res/xml/app_widget_big_info.xml new file mode 100644 index 00000000..da852169 --- /dev/null +++ b/app/src/main/res/xml/app_widget_big_info.xml @@ -0,0 +1,12 @@ + + + + \ No newline at end of file