Merge pull request #597 from KeyboardHammer/widget

Android Home Screen Widget
This commit is contained in:
advplyr 2023-02-26 11:30:16 -06:00 committed by GitHub
commit 20cf5a6132
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 381 additions and 190 deletions

View file

@ -23,18 +23,18 @@
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true" >
<!-- TODO: Incomplete desktop widget -->
<!-- <receiver-->
<!-- android:name=".NewAppWidget"-->
<!-- android:exported="true" >-->
<!-- <intent-filter>-->
<!-- <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />-->
<!-- </intent-filter>-->
<!-- Android app widget -->
<receiver
android:name="MediaPlayerWidget"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<!-- <meta-data-->
<!-- android:name="android.appwidget.provider"-->
<!-- android:resource="@xml/new_app_widget_info" />-->
<!-- </receiver>-->
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/media_player_widget_info" />
</receiver>
<!-- Used by Android Auto -->
<meta-data

View file

@ -0,0 +1,123 @@
package com.audiobookshelf.app
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
import android.support.v4.media.session.PlaybackStateCompat
import android.util.Log
import android.view.View
import android.widget.RemoteViews
import androidx.media.session.MediaButtonReceiver
import com.audiobookshelf.app.data.PlaybackSession
import com.audiobookshelf.app.device.DeviceManager
import com.audiobookshelf.app.device.WidgetEventEmitter
import com.audiobookshelf.app.player.PlayerNotificationService
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.AppWidgetTarget
import com.bumptech.glide.request.transition.Transition
/**
* Implementation of App Widget functionality.
*/
class MediaPlayerWidget : AppWidgetProvider() {
val tag = "MediaPlayerWidget"
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
// There may be multiple widgets active, so update all of them
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId, null, false, PlayerNotificationService.isClosed)
}
}
override fun onEnabled(context: Context) {
Log.i(tag, "onEnabled check context ${context.packageName}")
DeviceManager.deviceData.lastPlaybackSession?.let {
val appWidgetManager = AppWidgetManager.getInstance(context)
val componentName = ComponentName(context, MediaPlayerWidget::class.java)
val ids = appWidgetManager.getAppWidgetIds(componentName)
Log.d(tag, "Setting initial widget state with last playback session ${it.displayTitle}")
for (widgetId in ids) {
updateAppWidget(context, appWidgetManager, widgetId, it, false, true)
}
}
// Enter relevant functionality for when the first widget is created
DeviceManager.widgetUpdater = (object : WidgetEventEmitter {
override fun onPlayerChanged(pns: PlayerNotificationService) {
val isPlaying = pns.currentPlayer.isPlaying
val appWidgetManager = AppWidgetManager.getInstance(context)
val componentName = ComponentName(context, MediaPlayerWidget::class.java)
val ids = appWidgetManager.getAppWidgetIds(componentName)
val playbackSession = pns.getCurrentPlaybackSessionCopy()
for (widgetId in ids) {
updateAppWidget(context, appWidgetManager, widgetId, playbackSession, isPlaying, PlayerNotificationService.isClosed)
}
}
})
}
override fun onDisabled(context: Context) {
// Enter relevant functionality for when the last widget is disabled
}
}
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int, playbackSession: PlaybackSession?, isPlaying:Boolean, isAppClosed:Boolean) {
val tag = "MediaPlayerWidget"
val views = RemoteViews(context.packageName, R.layout.media_player_widget)
val wholeWidgetClickI = Intent(context, MainActivity::class.java)
wholeWidgetClickI.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
val wholeWidgetClickPI = PendingIntent.getActivity(
context,
System.currentTimeMillis().toInt(),
wholeWidgetClickI,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val playPausePI = MediaButtonReceiver.buildMediaButtonPendingIntent(context, PlaybackStateCompat.ACTION_PLAY_PAUSE)
views.setOnClickPendingIntent(R.id.widgetPlayPauseButton, playPausePI)
val fastForwardPI = MediaButtonReceiver.buildMediaButtonPendingIntent(context, PlaybackStateCompat.ACTION_FAST_FORWARD)
views.setOnClickPendingIntent(R.id.widgetFastForwardButton, fastForwardPI)
val rewindPI = MediaButtonReceiver.buildMediaButtonPendingIntent(context, PlaybackStateCompat.ACTION_REWIND)
views.setOnClickPendingIntent(R.id.widgetRewindButton, rewindPI)
// Show/Hide button container
views.setViewVisibility(R.id.widgetButtonContainer, if (isAppClosed) View.GONE else View.VISIBLE)
views.setOnClickPendingIntent(R.id.widgetBackground, wholeWidgetClickPI)
val imageUri = playbackSession?.getCoverUri() ?: Uri.parse("android.resource://com.audiobookshelf.app/" + R.drawable.icon)
val awt: AppWidgetTarget = object : AppWidgetTarget(context.applicationContext, R.id.widgetAlbumArt, views, appWidgetId) {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
super.onResourceReady(resource, transition)
}
}
val artist = playbackSession?.displayAuthor ?: "Unknown"
views.setTextViewText(R.id.widgetArtistText, artist)
val title = playbackSession?.displayTitle ?: "Unknown"
views.setTextViewText(R.id.widgetMediaTitle, title)
val options = RequestOptions().override(300, 300).placeholder(R.drawable.icon).error(R.drawable.icon)
Glide.with(context.applicationContext).asBitmap().load(imageUri).apply(options).into(awt)
Log.i(tag, "Update App Widget | Is Playing=$isPlaying | isAppClosed=$isAppClosed")
val playPauseResource = if (isPlaying) R.drawable.ic_media_pause_dark else R.drawable.ic_media_play_dark
views.setImageViewResource(R.id.widgetPlayPauseButton, playPauseResource)
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views)
}

View file

@ -1,96 +0,0 @@
package com.audiobookshelf.app
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
import android.support.v4.media.session.PlaybackStateCompat.ACTION_PLAY_PAUSE
import android.util.Log
import android.widget.RemoteViews
import androidx.media.session.MediaButtonReceiver.buildMediaButtonPendingIntent
import com.audiobookshelf.app.device.DeviceManager
import com.audiobookshelf.app.device.WidgetEventEmitter
import com.audiobookshelf.app.player.PlayerNotificationService
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.AppWidgetTarget
import com.bumptech.glide.request.transition.Transition
/**
* Implementation of App Widget functionality.
*/
class NewAppWidget : AppWidgetProvider() {
val tag = "NewAppWidget"
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
// There may be multiple widgets active, so update all of them
for (appWidgetId in appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId, null,false)
}
}
override fun onEnabled(context: Context) {
Log.w(tag, "onEnabled check context ${context.packageName}")
// Enter relevant functionality for when the first widget is created
DeviceManager.widgetUpdater = (object : WidgetEventEmitter {
override fun onPlayerChanged(pns:PlayerNotificationService) {
val isPlaying = pns.currentPlayer.isPlaying
Log.i(tag, "onPlayerChanged | Is Playing? $isPlaying")
val appWidgetManager = AppWidgetManager.getInstance(context)
val componentName = ComponentName(context, NewAppWidget::class.java)
val ids = appWidgetManager.getAppWidgetIds(componentName)
val playbackSession = pns.getCurrentPlaybackSessionCopy()
val cover = playbackSession?.getCoverUri()
for (widgetId in ids) {
updateAppWidget(context, appWidgetManager, widgetId, cover, isPlaying)
}
}
})
}
override fun onDisabled(context: Context) {
// Enter relevant functionality for when the last widget is disabled
}
}
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int, coverUri:Uri?, isPlaying:Boolean) {
val views = RemoteViews(context.packageName, R.layout.new_app_widget)
val playPausePI = buildMediaButtonPendingIntent(context, ACTION_PLAY_PAUSE)
views.setOnClickPendingIntent(R.id.playPauseIcon, playPausePI)
val wholeWidgetClickI = Intent(context, MainActivity::class.java)
wholeWidgetClickI.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
val wholeWidgetClickPI = PendingIntent.getActivity(
context,
System.currentTimeMillis().toInt(),
wholeWidgetClickI,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
views.setOnClickPendingIntent(R.id.appWidget, wholeWidgetClickPI)
val imageUri = coverUri ?: Uri.parse("android.resource://com.audiobookshelf.app/" + R.drawable.icon)
val awt: AppWidgetTarget = object : AppWidgetTarget(context.applicationContext, R.id.imageView, views, appWidgetId) {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
super.onResourceReady(resource, transition)
}
}
val options = RequestOptions().override(300, 300).placeholder(R.drawable.icon).error(R.drawable.icon)
Glide.with(context.applicationContext).asBitmap().load(imageUri).apply(options).into(awt)
val playPauseResource = if (isPlaying) R.drawable.ic_media_pause_dark else R.drawable.ic_media_play_dark
views.setImageViewResource(R.id.playPauseIcon, playPauseResource)
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views)
}

View file

@ -190,6 +190,16 @@ class MediaSessionCallback(var playerNotificationService:PlayerNotificationServi
handleMediaButtonClickCount()
}
}
KeyEvent.KEYCODE_MEDIA_FAST_FORWARD -> {
Log.d(tag, "handleCallMediaButton: Media Fast Forward")
if (0 == mediaButtonClickCount) playerNotificationService.jumpForward()
handleMediaButtonClickCount()
}
KeyEvent.KEYCODE_MEDIA_REWIND -> {
Log.d(tag, "handleCallMediaButton: Media Rewind")
if (0 == mediaButtonClickCount) playerNotificationService.jumpBackward()
handleMediaButtonClickCount()
}
}
}

View file

@ -1,6 +1,8 @@
package com.audiobookshelf.app.player
import android.app.*
import android.appwidget.AppWidgetManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
@ -21,12 +23,15 @@ import android.support.v4.media.session.MediaControllerCompat
import android.support.v4.media.session.MediaSessionCompat
import android.support.v4.media.session.PlaybackStateCompat
import android.util.Log
import android.view.View
import android.widget.RemoteViews
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.media.MediaBrowserServiceCompat
import androidx.media.utils.MediaConstants
import com.audiobookshelf.app.BuildConfig
import com.audiobookshelf.app.MediaPlayerWidget
import com.audiobookshelf.app.R
import com.audiobookshelf.app.data.*
import com.audiobookshelf.app.data.DeviceInfo
@ -170,12 +175,16 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
}
Log.d(tag, "onDestroy")
isStarted = false
isClosed = true
DeviceManager.widgetUpdater?.onPlayerChanged(this)
playerNotificationManager.setPlayer(null)
mPlayer.release()
castPlayer?.release()
mediaSession.release()
mediaProgressSyncer.reset()
isStarted = false
super.onDestroy()
}
@ -184,6 +193,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
override fun onTaskRemoved(rootIntent: Intent?) {
super.onTaskRemoved(rootIntent)
Log.d(tag, "onTaskRemoved")
stopSelf()
}
@ -258,7 +268,7 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
playerNotificationManager.setPriority(NotificationCompat.PRIORITY_MAX)
playerNotificationManager.setUseFastForwardActionInCompactView(true)
playerNotificationManager.setUseRewindActionInCompactView(true)
playerNotificationManager.setSmallIcon(R.drawable.exo_icon_localaudio)
playerNotificationManager.setSmallIcon(R.drawable.icon_monochrome)
// Unknown action
playerNotificationManager.setBadgeIconType(NotificationCompat.BADGE_ICON_LARGE)
@ -409,9 +419,12 @@ class PlayerNotificationService : MediaBrowserServiceCompat() {
DeviceManager.setLastPlaybackSession(playbackSession) // Save playback session to use when app is closed
Log.d(tag, "Set CurrentPlaybackSession MediaPlayer ${currentPlaybackSession?.mediaPlayer}")
// Notify client
clientEventEmitter?.onPlaybackSession(playbackSession)
// Update widget
DeviceManager.widgetUpdater?.onPlayerChanged(this)
if (mediaItems.isEmpty()) {
Log.e(tag, "Invalid playback session no media items to play")
currentPlaybackSession = null

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="862dp"
android:height="1024dp"
android:viewportWidth="862"
android:viewportHeight="1024">
<path
android:fillColor="#FFFFFF"
android:pathData="M855,504.4c-5.3,-4.4 -13.5,-10.9 -24.7,-18.6v-86.5c0,-220.5 -178.8,-399.3 -399.3,-399.3v0c-220.5,0 -399.3,178.8 -399.3,399.3v86.5c-11.1,7.7 -19.4,14.2 -24.7,18.6 -4.4,3.7 -7.1,9.1 -7.1,15.2 0,0 0,0 0,0v-0,103.6c0,0 0,0 0,0 0,6.1 2.8,11.6 7.1,15.2l0,0c12.3,10.3 40.6,31.8 84.7,53.8v10.1c0,27.2 17.5,49.2 39.1,49.2v0c21.6,0 39.1,-22 39.1,-49.2v-248.5c0,-27.2 -17.5,-49.2 -39.1,-49.2v0c-20.7,0 -37.7,20.2 -39,45.8l-0.1,0v-51.2c0,-187.4 151.9,-339.3 339.3,-339.3v0c187.4,0 339.3,151.9 339.3,339.3v51.2l-0.1,-0c-1.4,-25.6 -18.3,-45.8 -39,-45.8v0c-21.6,0 -39.1,22 -39.1,49.2v248.5c0,27.2 17.5,49.2 39.1,49.2v0c21.6,0 39.1,-22 39.1,-49.2v-10.1c44,-22.1 72.3,-43.6 84.7,-53.8 4.4,-3.7 7.1,-9.1 7.1,-15.2 0,-0 0,-0 0,-0v0,-103.6c0,-0 0,-0 0,-0 0,-6.1 -2.8,-11.6 -7.1,-15.2l-0,-0zM291.8,936.4c26.1,0 47.3,-21.2 47.3,-47.3v0,-529.4c0,-0 0,-0 0,-0 0,-26.1 -21.2,-47.3 -47.3,-47.3h-48.8c-26.1,0 -47.3,21.2 -47.3,47.3v0,529.4c0,26.1 21.2,47.3 47.3,47.3 0,0 0,0 0,0v0zM213.5,439.4h107.8v11.3h-107.8zM455.5,936.4c26.1,0 47.3,-21.2 47.3,-47.3v0,-529.4c0,-0 0,-0 0,-0 0,-26.1 -21.2,-47.3 -47.3,-47.3h-48.8c-26.1,0 -47.3,21.2 -47.3,47.3v0,529.4c0,26.1 21.2,47.3 47.3,47.3 0,0 0,0 0,0v0zM377.2,439.4h107.8v11.3h-107.8zM619.1,936.4c26.1,0 47.3,-21.2 47.3,-47.3v0,-529.4c0,-0 0,-0 0,-0 0,-26.1 -21.2,-47.3 -47.3,-47.3h-48.8c-26.1,0 -47.3,21.2 -47.3,47.3v0,529.4c0,26.1 21.2,47.3 47.3,47.3 0,0 0,0 0,0v0zM540.8,439.4h107.8v11.3h-107.8zM114.1,952.7h633.9c19.7,0 35.6,15.9 35.6,35.6v0c0,19.7 -15.9,35.6 -35.6,35.6h-633.9c-19.7,0 -35.6,-15.9 -35.6,-35.6v-0c0,-19.7 15.9,-35.6 35.6,-35.6z"/>
</vector>

View file

@ -0,0 +1,108 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/widgetBackground"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:theme="@style/AppTheme.AppWidgetContainer"
style="@style/Widget.Android.AppWidget.Container">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:background="?android:attr/colorAccent"
android:theme="@style/MediaPlayerWidgetTheme"
android:orientation="horizontal">
<ImageView
android:id="@+id/widgetAlbumArt"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"
android:scaleType="centerCrop"
android:src="@drawable/icon" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
android:layout_marginVertical="8dp"
android:orientation="vertical"
android:gravity="center_vertical">
<TextView
android:id="@+id/widgetArtistText"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:layout_marginLeft="8dp"
android:gravity="bottom"
android:ellipsize="end"
android:maxLines="1"
android:text="Artist"/>
<TextView
android:id="@+id/widgetMediaTitle"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:layout_marginLeft="8dp"
android:gravity="top"
android:ellipsize="end"
android:maxLines="1"
android:text="Title"/>
<LinearLayout
android:id="@+id/widgetButtonContainer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3"
android:orientation="horizontal"
android:background="?android:attr/colorAccent"
android:theme="@style/MediaPlayerWidgetTheme">
<ImageView
android:id="@+id/widgetRewindButton"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_margin="8dp"
android:src="@drawable/exo_icon_rewind"
style="@style/Widget.Android.AppWidget.InnerView"/>
<ImageView
android:id="@+id/widgetPlayPauseButton"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_margin="6dp"
android:src="@drawable/ic_media_play_dark" />
<ImageView
android:id="@+id/widgetFastForwardButton"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_margin="8dp"
android:src="@drawable/exo_icon_fastforward" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="36dp"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/tinyCornerIcon"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_margin="6dp"
android:adjustViewBounds ="true"
android:src="@drawable/icon_monochrome" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View file

@ -1,26 +0,0 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
style="@style/Widget.Android.AppWidget.Container"
android:id="@+id/appWidget"
android:theme="@style/AppTheme.AppWidgetContainer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:adjustViewBounds="true"
android:alpha="0.75"
android:contentDescription="Cover image"
android:visibility="visible" />
<ImageView
android:id="@+id/playPauseIcon"
android:layout_width="71dp"
android:layout_height="55dp"
android:layout_centerInParent="true"
app:srcCompat="@drawable/cast_ic_expanded_controller_play" />
</RelativeLayout>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--
Having themes.xml for night-v31 because of the priority order of the resource qualifiers.
-->
<style name="AppTheme.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault.DayNight">
<item name="appWidgetRadius">@android:dimen/system_app_widget_background_radius</item>
<item name="appWidgetInnerRadius">@android:dimen/system_app_widget_inner_radius</item>
</style>
</resources>

View file

@ -0,0 +1,16 @@
<resources>
<style name="Widget.Android.AppWidget.Container" parent="android:Widget">
<item name="android:id">@android:id/background</item>
<item name="android:padding">?attr/appWidgetPadding</item>
<item name="android:background">@drawable/app_widget_background</item>
<item name="android:clipToOutline">true</item>
</style>
<style name="Widget.Android.AppWidget.InnerView" parent="android:Widget">
<item name="android:padding">?attr/appWidgetPadding</item>
<!-- <item name="android:background">@drawable/app_widget_inner_view_background</item>-->
<!-- <item name="android:textColor">?android:attr/textColorPrimary</item>-->
<item name="android:clipToOutline">true</item>
</style>
</resources>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--
Having themes.xml for v31 variant because @android:dimen/system_app_widget_background_radius
and @android:dimen/system_app_widget_internal_padding requires API level 31
-->
<style name="AppTheme.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault.DayNight">
<item name="appWidgetRadius">@android:dimen/system_app_widget_background_radius</item>
<item name="appWidgetInnerRadius">@android:dimen/system_app_widget_inner_radius</item>
</style>
</resources>

View file

@ -1,7 +1,9 @@
<resources>
<declare-styleable name="AppWidgetAttrs">
<attr name="appWidgetPadding" format="dimension" />
<attr name="appWidgetInnerRadius" format="dimension" />
<attr name="appWidgetRadius" format="dimension" />
</declare-styleable>
</resources>
<declare-styleable name="AppWidgetAttrs">
<attr name="appWidgetPadding" format="dimension" />
<attr name="appWidgetInnerRadius" format="dimension" />
<attr name="appWidgetRadius" format="dimension" />
<attr name="backgroundRadius" format="dimension" />
<attr name="appWidgetViewPadding" format="dimension" />
</declare-styleable>
</resources>

View file

@ -1,33 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="AppTheme.NoActionBar" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:background">@null</item>
<item name="android:statusBarColor">@color/background_dark</item>
<item name="android:navigationBarColor">@color/background_dark</item>
</style>
<style name="AppTheme.NoActionBar" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:background">@null</item>
<item name="android:statusBarColor">@color/background_dark</item>
<item name="android:navigationBarColor">@color/background_dark</item>
</style>
<style name="AppTheme.NoActionBarLaunch" parent="Theme.SplashScreen">
<!-- <item name="android:background">@drawable/screen</item>-->
</style>
<style name="Widget.Android.AppWidget.Container" parent="android:Widget">
<item name="android:id">@android:id/background</item>
<item name="android:background">?android:attr/colorBackground</item>
</style>
<style name="AppTheme.NoActionBarLaunch" parent="Theme.SplashScreen">
<!-- <item name="android:background">@drawable/screen</item>-->
</style>
<style name="Widget.Android.AppWidget.InnerView" parent="android:Widget">
<item name="android:background">?android:attr/colorBackground</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="MediaPlayerWidgetTheme" parent="Theme.AppCompat.DayNight">
<!-- These colors match the vue pages -->
<item name="android:colorBackground">#232323</item>
<item name="android:colorAccent">#373838</item>
<item name="android:textColor">#ffffff</item>
</style>
<style name="Widget.Android.AppWidget.Container" parent="android:Widget">
<item name="android:id">@android:id/background</item>
<item name="android:background">?android:attr/colorBackground</item>
</style>
<style name="Widget.Android.AppWidget.InnerView" parent="android:Widget">
<!-- <item name="android:background">?android:attr/colorBackground</item>-->
<!-- <item name="android:textColor">?android:attr/textColorPrimary</item>-->
<item name="android:padding">0dp</item>
</style>
</resources>

View file

@ -1,17 +1,17 @@
<resources>
<style name="AppTheme.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault">
<!-- Radius of the outer bound of widgets to make the rounded corners -->
<item name="appWidgetRadius">16dp</item>
<!--
<style name="AppTheme.AppWidgetContainerParent" parent="@android:style/Theme.DeviceDefault">
<!-- Radius of the outer bound of widgets to make the rounded corners -->
<item name="appWidgetRadius">0dp</item>
<!--
Radius of the inner view's bound of widgets to make the rounded corners.
It needs to be 8dp or less than the value of appWidgetRadius
-->
<item name="appWidgetInnerRadius">8dp</item>
</style>
<item name="appWidgetInnerRadius">0dp</item>
</style>
<style name="AppTheme.AppWidgetContainer"
parent="AppTheme.AppWidgetContainerParent">
<!-- Apply padding to avoid the content of the widget colliding with the rounded corners -->
<item name="appWidgetPadding">16dp</item>
</style>
<style name="AppTheme.AppWidgetContainer" parent="AppTheme.AppWidgetContainerParent">
<!-- Apply padding to avoid the content of the widget colliding with the rounded corners -->
<item name="appWidgetPadding">0dp</item>
</style>
</resources>

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/app_widget_description"
android:initialKeyguardLayout="@layout/media_player_widget"
android:initialLayout="@layout/media_player_widget"
android:minWidth="275dp"
android:minHeight="50dp"
android:previewImage="@drawable/media_player_widget_preview"
android:previewLayout="@layout/media_player_widget"
android:resizeMode="horizontal"
android:targetCellWidth="4"
android:targetCellHeight="1"
android:updatePeriodMillis="86400000"
android:widgetCategory="home_screen" />

View file

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="110dp"
android:minHeight="40dp"
android:updatePeriodMillis="86400000"
android:previewImage="@drawable/example_appwidget_preview"
android:initialLayout="@layout/new_app_widget"
android:description="@string/app_widget_description"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen"
android:initialKeyguardLayout="@layout/new_app_widget"
/>