feat(widget): add 4x1 AppWidgetProvider with play/pause and track info

This commit is contained in:
nk
2026-06-01 13:21:37 +03:00
parent 9ce9758361
commit af8fb333d9
7 changed files with 175 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
package com.radiola.widget
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.content.Intent
import android.widget.RemoteViews
import com.radiola.MainActivity
import com.radiola.R
import com.radiola.service.PlayerService
class PlayerWidgetProvider : AppWidgetProvider() {
companion object {
const val ACTION_PLAY_PAUSE = "com.radiola.widget.ACTION_PLAY_PAUSE"
fun updateWidget(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetId: Int,
stationName: String,
trackTitle: String,
isPlaying: Boolean
) {
val views = RemoteViews(context.packageName, R.layout.widget_player)
views.setTextViewText(R.id.widget_station_name, stationName)
views.setTextViewText(R.id.widget_track_title, trackTitle)
views.setImageViewResource(
R.id.widget_play_pause,
if (isPlaying) R.drawable.ic_pause else R.drawable.ic_play
)
// Open app on click
val openAppIntent = Intent(context, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
}
val openAppPendingIntent = PendingIntent.getActivity(
context, 0, openAppIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
views.setOnClickPendingIntent(R.id.widget_root, openAppPendingIntent)
// Play/Pause button
val playPauseIntent = Intent(context, PlayerWidgetProvider::class.java).apply {
action = ACTION_PLAY_PAUSE
}
val playPausePendingIntent = PendingIntent.getBroadcast(
context, 1, playPauseIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
views.setOnClickPendingIntent(R.id.widget_play_pause, playPausePendingIntent)
appWidgetManager.updateAppWidget(appWidgetId, views)
}
}
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
for (appWidgetId in appWidgetIds) {
updateWidget(context, appWidgetManager, appWidgetId, "radiOLA", "", false)
}
}
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
if (intent.action == ACTION_PLAY_PAUSE) {
// Start service to handle play/pause
val serviceIntent = Intent(context, PlayerService::class.java).apply {
action = ACTION_PLAY_PAUSE
}
context.startService(serviceIntent)
}
}
}

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#FFFFFF">
<path
android:fillColor="#FFFFFF"
android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z" />
</vector>

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#FFFFFF">
<path
android:fillColor="#FFFFFF"
android:pathData="M8,5v14l11,-7z" />
</vector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#1E1E1E" />
<corners android:radius="16dp" />
</shape>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient
android:startColor="#667eea"
android:endColor="#764ba2"
android:angle="135" />
<corners android:radius="8dp" />
</shape>

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/widget_root"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/widget_background"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="12dp">
<ImageView
android:id="@+id/widget_cover"
android:layout_width="48dp"
android:layout_height="48dp"
android:background="@drawable/widget_cover_placeholder"
android:scaleType="centerCrop" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/widget_station_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:textSize="14sp"
android:textStyle="bold"
android:maxLines="1"
android:ellipsize="end" />
<TextView
android:id="@+id/widget_track_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#AAAAAA"
android:textSize="12sp"
android:maxLines="1"
android:ellipsize="end" />
</LinearLayout>
<ImageButton
android:id="@+id/widget_play_pause"
android:layout_width="40dp"
android:layout_height="40dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:src="@drawable/ic_play"
android:contentDescription="@string/player_play" />
</LinearLayout>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/widget_player"
android:minWidth="250dp"
android:minHeight="40dp"
android:previewImage="@drawable/widget_cover_placeholder"
android:resizeMode="horizontal"
android:updatePeriodMillis="0"
android:widgetCategory="home_screen" />