Add volume up/down buttons on media player widget (#2139)

This commit is contained in:
Jamie Macdonald 2022-02-16 17:45:39 -08:00 committed by GitHub
parent e21d095195
commit 5d9a9df0bb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 168 additions and 5 deletions

View file

@ -48,9 +48,14 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
"io.homeassistant.companion.android.widgets.media_player_controls.MediaPlayerControlsWidget.CALL_FASTFORWARD"
internal const val CALL_NEXT_TRACK =
"io.homeassistant.companion.android.widgets.media_player_controls.MediaPlayerControlsWidget.CALL_NEXT_TRACK"
internal const val CALL_VOLUME_DOWN =
"io.homeassistant.companion.android.widgets.media_player_controls.MediaPlayerControlsWidget.CALL_VOLUME_DOWN"
internal const val CALL_VOLUME_UP =
"io.homeassistant.companion.android.widgets.media_player_controls.MediaPlayerControlsWidget.CALL_VOLUME_UP"
internal const val EXTRA_ENTITY_ID = "EXTRA_ENTITY_ID"
internal const val EXTRA_LABEL = "EXTRA_LABEL"
internal const val EXTRA_SHOW_VOLUME = "EXTRA_SHOW_VOLUME"
internal const val EXTRA_SHOW_SKIP = "EXTRA_INCLUDE_SKIP"
internal const val EXTRA_SHOW_SEEK = "EXTRA_INCLUDE_SEEK"
}
@ -122,11 +127,22 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
}
val volumeDownIntent = Intent(context, MediaPlayerControlsWidget::class.java).apply {
action = CALL_VOLUME_DOWN
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
}
val volumeUpIntent = Intent(context, MediaPlayerControlsWidget::class.java).apply {
action = CALL_VOLUME_UP
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
}
return RemoteViews(context.packageName, R.layout.widget_media_controls).apply {
val widget = mediaPlayCtrlWidgetDao.get(appWidgetId)
if (widget != null) {
val entityId: String = widget.entityId
var label: String? = widget.label
val showVolume: Boolean = widget.showVolume
val showSkip: Boolean = widget.showSkip
val showSeek: Boolean = widget.showSeek
val entity = getEntity(context, widget.entityId, suggestedEntity)
@ -284,6 +300,32 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
)
)
if (showVolume) {
setOnClickPendingIntent(
R.id.widgetVolumeDownButton,
PendingIntent.getBroadcast(
context,
appWidgetId,
volumeDownIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
)
setOnClickPendingIntent(
R.id.widgetVolumeUpButton,
PendingIntent.getBroadcast(
context,
appWidgetId,
volumeUpIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
)
setViewVisibility(R.id.widgetVolumeDownButton, View.VISIBLE)
setViewVisibility(R.id.widgetVolumeUpButton, View.VISIBLE)
} else {
setViewVisibility(R.id.widgetVolumeDownButton, View.GONE)
setViewVisibility(R.id.widgetVolumeUpButton, View.GONE)
}
if (showSkip) {
setOnClickPendingIntent(
R.id.widgetPrevTrackButton,
@ -390,6 +432,8 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
CALL_PLAYPAUSE -> callPlayPauseService(appWidgetId)
CALL_FASTFORWARD -> callFastForwardService(context, appWidgetId)
CALL_NEXT_TRACK -> callNextTrackService(appWidgetId)
CALL_VOLUME_DOWN -> callVolumeDownService(appWidgetId)
CALL_VOLUME_UP -> callVolumeUpService(appWidgetId)
}
}
@ -400,8 +444,9 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
val labelSelection: String? = extras.getString(EXTRA_LABEL)
val showSkip: Boolean? = extras.getBoolean(EXTRA_SHOW_SKIP)
val showSeek: Boolean? = extras.getBoolean(EXTRA_SHOW_SEEK)
val showVolume: Boolean? = extras.getBoolean(EXTRA_SHOW_VOLUME)
if (entitySelection == null || showSkip == null || showSeek == null) {
if (entitySelection == null || showSkip == null || showSeek == null || showVolume == null) {
Log.e(TAG, "Did not receive complete configuration data")
return
}
@ -418,7 +463,8 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
entitySelection,
labelSelection,
showSkip,
showSeek
showSeek,
showVolume
)
)
@ -600,6 +646,56 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
}
}
private fun callVolumeDownService(appWidgetId: Int) {
mainScope.launch {
Log.d(TAG, "Retrieving media player entity for app widget $appWidgetId")
val entity: MediaPlayerControlsWidgetEntity? = mediaPlayCtrlWidgetDao.get(appWidgetId)
if (entity == null) {
Log.d(TAG, "Failed to retrieve media player entity")
return@launch
}
Log.d(
TAG,
"Calling volume down service:" + System.lineSeparator() +
"entity id: " + entity.entityId + System.lineSeparator()
)
val domain = "media_player"
val service = "volume_down"
val serviceDataMap: HashMap<String, Any> = hashMapOf("entity_id" to entity.entityId)
integrationUseCase.callService(domain, service, serviceDataMap)
}
}
private fun callVolumeUpService(appWidgetId: Int) {
mainScope.launch {
Log.d(TAG, "Retrieving media player entity for app widget $appWidgetId")
val entity: MediaPlayerControlsWidgetEntity? = mediaPlayCtrlWidgetDao.get(appWidgetId)
if (entity == null) {
Log.d(TAG, "Failed to retrieve media player entity")
return@launch
}
Log.d(
TAG,
"Calling volume up service:" + System.lineSeparator() +
"entity id: " + entity.entityId + System.lineSeparator()
)
val domain = "media_player"
val service = "volume_up"
val serviceDataMap: HashMap<String, Any> = hashMapOf("entity_id" to entity.entityId)
integrationUseCase.callService(domain, service, serviceDataMap)
}
}
override fun onDeleted(context: Context, appWidgetIds: IntArray) {
mediaPlayCtrlWidgetDao = AppDatabase.getInstance(context).mediaPlayCtrlWidgetDao()
// When the user deletes the widget, delete the preference associated with it.

View file

@ -103,6 +103,7 @@ class MediaPlayerControlsWidgetConfigureActivity : BaseActivity() {
if (mediaPlayerWidget != null) {
binding.label.setText(mediaPlayerWidget.label)
binding.widgetTextConfigEntityId.setText(mediaPlayerWidget.entityId)
binding.widgetShowVolumeButtonCheckbox.isChecked = mediaPlayerWidget.showVolume
binding.widgetShowSeekButtonsCheckbox.isChecked = mediaPlayerWidget.showSeek
binding.widgetShowSkipButtonsCheckbox.isChecked = mediaPlayerWidget.showSkip
val entity = runBlocking {
@ -187,6 +188,10 @@ class MediaPlayerControlsWidgetConfigureActivity : BaseActivity() {
MediaPlayerControlsWidget.EXTRA_LABEL,
binding.label.text.toString()
)
intent.putExtra(
MediaPlayerControlsWidget.EXTRA_SHOW_VOLUME,
binding.widgetShowVolumeButtonCheckbox.isChecked
)
intent.putExtra(
MediaPlayerControlsWidget.EXTRA_SHOW_SKIP,
binding.widgetShowSkipButtonsCheckbox.isChecked

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M19,13H5V11H19V13Z" />
</vector>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z" />
</vector>

View file

@ -118,6 +118,30 @@
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<ImageButton
android:id="@+id/widgetVolumeDownButton"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?android:selectableItemBackground"
android:contentDescription="@string/widget_media_volume_down_button"
android:padding="4dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_volume_down"
android:tint="@color/colorIcon" />
<ImageButton
android:id="@+id/widgetVolumeUpButton"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?android:selectableItemBackground"
android:contentDescription="@string/widget_media_volume_up_button"
android:padding="4dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_volume_up"
android:tint="@color/colorIcon" />
<ImageButton
android:id="@+id/widgetPrevTrackButton"
android:layout_width="0dp"

View file

@ -38,6 +38,16 @@
android:inputType="text" />
</LinearLayout>
<CheckBox
android:id="@+id/widget_show_volume_button_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_margin="5dp"
android:checked="true"
android:layoutDirection="rtl"
android:text="@string/widget_media_show_volume" />
<CheckBox
android:id="@+id/widget_show_skip_buttons_checkbox"
android:layout_width="wrap_content"

View file

@ -65,7 +65,7 @@ import io.homeassistant.companion.android.common.R as commonR
Favorites::class,
Setting::class
],
version = 22,
version = 23,
exportSchema = false
)
@TypeConverters(
@ -129,7 +129,8 @@ abstract class AppDatabase : RoomDatabase() {
MIGRATION_18_19,
MIGRATION_19_20,
MIGRATION_20_21,
MIGRATION_21_22
MIGRATION_21_22,
MIGRATION_22_23
)
.fallbackToDestructiveMigration()
.build()
@ -476,6 +477,12 @@ abstract class AppDatabase : RoomDatabase() {
}
}
private val MIGRATION_22_23 = object : Migration(22, 23) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE `mediaplayctrls_widgets` ADD `showVolume` INTEGER NOT NULL DEFAULT '0'")
}
}
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager = appContext.getSystemService<NotificationManager>()!!

View file

@ -15,5 +15,7 @@ data class MediaPlayerControlsWidgetEntity(
@ColumnInfo(name = "showSkip")
val showSkip: Boolean,
@ColumnInfo(name = "showSeek")
val showSeek: Boolean
val showSeek: Boolean,
@ColumnInfo(name = "showVolume")
val showVolume: Boolean
)

View file

@ -722,7 +722,10 @@
<string name="widget_media_player_description">Media Player Widget</string>
<string name="widget_media_playpause_button">Play/Pause</string>
<string name="widget_media_prev_track_button">Previous Track</string>
<string name="widget_media_volume_down_button">Volume Down</string>
<string name="widget_media_volume_up_button">Volume Up</string>
<string name="widget_media_rewind_button">Rewind</string>
<string name="widget_media_show_volume">Show Volume Buttons</string>
<string name="widget_media_show_seek">Show Seek Buttons</string>
<string name="widget_media_show_skip">Show Skip Buttons</string>
<string name="widget_separator_input_hint">No separator</string>