widgets: add widget layout preview

Add a layout preview to the Android 12 widget metadata. I'm holding off
on implementing a drawable until the widgets are completely finalized.
This commit is contained in:
OxygenCobalt 2021-08-03 10:33:07 -06:00
parent 8551e90884
commit 49db7e0741
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
11 changed files with 54 additions and 29 deletions

View file

@ -369,6 +369,9 @@ class PlaybackService : Service(), Player.Listener, PlaybackStateManager.Callbac
onLoopUpdate(playbackManager.loopMode) onLoopUpdate(playbackManager.loopMode)
onSongUpdate(playbackManager.song) onSongUpdate(playbackManager.song)
onSeek(playbackManager.position) onSeek(playbackManager.position)
// Notify other classes that rely on this service to also update.
widgets.update()
} }
/** /**
@ -495,9 +498,11 @@ class PlaybackService : Service(), Player.Listener, PlaybackStateManager.Callbac
} }
} }
BaseWidget.ACTION_WIDGET_UPDATE -> widgets.initWidget( BaseWidget.ACTION_WIDGET_UPDATE -> {
intent.getIntExtra(BaseWidget.ACTION_WIDGET_UPDATE, -1) widgets.initWidget(
) intent.getIntExtra(BaseWidget.KEY_WIDGET_TYPE, -1)
)
}
} }
} }

View file

@ -155,8 +155,8 @@ enum class SortMode(@DrawableRes val iconRes: Int) {
val list = mutableListOf<Song>() val list = mutableListOf<Song>()
songs.groupBy { it.album }.entries.sortedWith(compareByDescending { it.key.year }).forEach { entry -> songs.groupBy { it.album }.entries.sortedWith(compareByDescending { it.key.year }).forEach { entry ->
list.addAll(entry.value.sortedWith(compareBy { it.track })) list.addAll(entry.value.sortedWith(compareBy { it.track }))
} }
list list
} }

View file

@ -45,8 +45,6 @@ abstract class BaseWidget : AppWidgetProvider() {
* Update the widget based on the playback state. * Update the widget based on the playback state.
*/ */
fun update(context: Context, playbackManager: PlaybackStateManager) { fun update(context: Context, playbackManager: PlaybackStateManager) {
logD("Dispatching playback state update")
val manager = AppWidgetManager.getInstance(context) val manager = AppWidgetManager.getInstance(context)
// View updates are often async due to image loading, so only push the views // View updates are often async due to image loading, so only push the views
@ -57,10 +55,10 @@ abstract class BaseWidget : AppWidgetProvider() {
} }
/* /*
* Stop this widget, reverting it to its default state. * Revert this widget to its default view
*/ */
fun stop(context: Context) { fun reset(context: Context) {
logD("Stopping widget") logD("Resetting widget")
val manager = AppWidgetManager.getInstance(context) val manager = AppWidgetManager.getInstance(context)
manager.applyViews(context, defaultViews(context)) manager.applyViews(context, defaultViews(context))
@ -71,10 +69,10 @@ abstract class BaseWidget : AppWidgetProvider() {
appWidgetManager: AppWidgetManager, appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray appWidgetIds: IntArray
) { ) {
appWidgetManager.applyViews(context, defaultViews(context))
logD("Sending update intent to PlaybackService") logD("Sending update intent to PlaybackService")
appWidgetManager.applyViews(context, defaultViews(context))
val intent = Intent(ACTION_WIDGET_UPDATE) val intent = Intent(ACTION_WIDGET_UPDATE)
.putExtra(KEY_WIDGET_TYPE, type) .putExtra(KEY_WIDGET_TYPE, type)
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY) .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)

View file

@ -51,7 +51,7 @@ class MinimalWidgetProvider : BaseWidget() {
val song = playbackManager.song val song = playbackManager.song
if (song != null) { if (song != null) {
logD("updating view to ${song.name}") logD("Updating view to ${song.name}")
val views = createViews(context, R.layout.widget_minimal) val views = createViews(context, R.layout.widget_minimal)
@ -88,6 +88,8 @@ class MinimalWidgetProvider : BaseWidget() {
onDone(views) onDone(views)
} }
} else { } else {
logD("No song playing, reverting to default view")
onDone(defaultViews(context)) onDone(defaultViews(context))
} }
} }

View file

@ -1,33 +1,44 @@
package org.oxycblt.auxio.widgets package org.oxycblt.auxio.widgets
import android.content.Context import android.content.Context
import org.oxycblt.auxio.logD
import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.playback.state.PlaybackStateManager import org.oxycblt.auxio.playback.state.PlaybackStateManager
class WidgetController(private val context: Context) : PlaybackStateManager.Callback { class WidgetController(private val context: Context) : PlaybackStateManager.Callback {
private val manager = PlaybackStateManager.getInstance() private val playbackManager = PlaybackStateManager.getInstance()
private val minimal = MinimalWidgetProvider() private val minimal = MinimalWidgetProvider()
init { init {
manager.addCallback(this) playbackManager.addCallback(this)
} }
fun initWidget(type: Int) { fun initWidget(type: Int) {
logD("Updating new widget $type")
when (type) { when (type) {
MinimalWidgetProvider.TYPE -> minimal.update(context, manager) MinimalWidgetProvider.TYPE -> minimal.update(context, playbackManager)
} }
} }
fun update() {
logD("Updating all widgets")
minimal.update(context, playbackManager)
}
fun release() { fun release() {
minimal.stop(context) logD("Resetting widgets")
manager.removeCallback(this)
minimal.reset(context)
playbackManager.removeCallback(this)
} }
override fun onSongUpdate(song: Song?) { override fun onSongUpdate(song: Song?) {
minimal.update(context, manager) minimal.update(context, playbackManager)
} }
override fun onPlayingUpdate(isPlaying: Boolean) { override fun onPlayingUpdate(isPlaying: Boolean) {
minimal.update(context, manager) minimal.update(context, playbackManager)
} }
} }

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="@android:dimen/system_app_widget_inner_radius" />
</shape>

View file

@ -15,13 +15,13 @@
android:background="?attr/colorSurface" android:background="?attr/colorSurface"
android:scaleType="centerCrop" android:scaleType="centerCrop"
tools:ignore="contentDescription" tools:ignore="contentDescription"
tools:src="@drawable/ic_song" /> android:src="@drawable/ic_song" />
<android.widget.LinearLayout <android.widget.LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:background="?android:attr/colorBackground" android:background="?attr/colorSurface"
android:orientation="vertical" android:orientation="vertical"
android:padding="@dimen/spacing_medium"> android:padding="@dimen/spacing_medium">
@ -35,7 +35,7 @@
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6" android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
android:textColor="?android:attr/textColorPrimary" android:textColor="?android:attr/textColorPrimary"
android:textStyle="bold" android:textStyle="bold"
tools:text="Song Name" /> android:text="@string/placeholder_widget_song" />
<android.widget.TextView <android.widget.TextView
android:id="@+id/widget_artist" android:id="@+id/widget_artist"
@ -46,13 +46,12 @@
android:singleLine="true" android:singleLine="true"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1" android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
tools:text="Artist Name" /> android:text="@string/placeholder_widget_artist" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:layout_marginTop="@dimen/spacing_small"
android:layout_marginTop="@dimen/spacing_medium"
android:orientation="horizontal"> android:orientation="horizontal">
<ImageButton <ImageButton

View file

@ -3,6 +3,7 @@
android:id="@android:id/background" android:id="@android:id/background"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="?attr/colorSurface"
android:theme="@style/Theme.Widget"> android:theme="@style/Theme.Widget">
<android.widget.ImageView <android.widget.ImageView

View file

@ -52,9 +52,7 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_medium" android:layout_marginTop="@dimen/spacing_small">
android:gravity="center"
android:orientation="horizontal">
<!-- <!--
Can't use a normal unbounded ripple here since it causes a weird bug Can't use a normal unbounded ripple here since it causes a weird bug

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools" <resources xmlns:tools="http://schemas.android.com/tools"
tools:ignore="MissingTranslation"> tools:ignore="MissingTranslation">
<!-- Info namespace | App labels --> <!-- Info namespace | App labels -->
<string name="info_app_desc">A simple, rational music player for android.</string> <string name="info_app_desc">A simple, rational music player for android.</string>
<string name="info_channel_name">Music Playback</string> <string name="info_channel_name">Music Playback</string>
@ -137,6 +138,8 @@
<string name="placeholder_album">Unknown Album</string> <string name="placeholder_album">Unknown Album</string>
<string name="placeholder_no_date">No Date</string> <string name="placeholder_no_date">No Date</string>
<string name="placeholder_playback">No music playing</string> <string name="placeholder_playback">No music playing</string>
<string name="placeholder_widget_song">Song Name</string>
<string name="placeholder_widget_artist">Artist Name</string>
<!-- Color Label namespace | Accent names --> <!-- Color Label namespace | Accent names -->
<string name="color_label_red">Red</string> <string name="color_label_red">Red</string>

View file

@ -5,6 +5,7 @@
android:targetCellHeight="2" android:targetCellHeight="2"
android:minResizeWidth="110dp" android:minResizeWidth="110dp"
android:minResizeHeight="110dp" android:minResizeHeight="110dp"
android:previewLayout="@layout/widget_minimal"
android:resizeMode="horizontal|vertical" android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="0" android:updatePeriodMillis="0"
android:widgetCategory="home_screen"> android:widgetCategory="home_screen">