diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 5e4a8f29..44833801 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -23,18 +23,18 @@
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true" >
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
?) {
+ 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)
+}
diff --git a/android/app/src/main/java/com/audiobookshelf/app/NewAppWidget.kt b/android/app/src/main/java/com/audiobookshelf/app/NewAppWidget.kt
deleted file mode 100644
index c160ca06..00000000
--- a/android/app/src/main/java/com/audiobookshelf/app/NewAppWidget.kt
+++ /dev/null
@@ -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?) {
- 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)
-}
diff --git a/android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionCallback.kt b/android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionCallback.kt
index 222bd5f6..036856d2 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionCallback.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/player/MediaSessionCallback.kt
@@ -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()
+ }
}
}
diff --git a/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt b/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt
index 71f12af6..f21b93a2 100644
--- a/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt
+++ b/android/app/src/main/java/com/audiobookshelf/app/player/PlayerNotificationService.kt
@@ -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
diff --git a/android/app/src/main/res/drawable-nodpi/example_appwidget_preview.png b/android/app/src/main/res/drawable-nodpi/example_appwidget_preview.png
deleted file mode 100644
index 894b069a..00000000
Binary files a/android/app/src/main/res/drawable-nodpi/example_appwidget_preview.png and /dev/null differ
diff --git a/android/app/src/main/res/drawable-nodpi/media_player_widget_preview.png b/android/app/src/main/res/drawable-nodpi/media_player_widget_preview.png
new file mode 100644
index 00000000..27a07efe
Binary files /dev/null and b/android/app/src/main/res/drawable-nodpi/media_player_widget_preview.png differ
diff --git a/android/app/src/main/res/drawable/icon_monochrome.xml b/android/app/src/main/res/drawable/icon_monochrome.xml
new file mode 100644
index 00000000..594c52c7
--- /dev/null
+++ b/android/app/src/main/res/drawable/icon_monochrome.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/android/app/src/main/res/layout/media_player_widget.xml b/android/app/src/main/res/layout/media_player_widget.xml
new file mode 100644
index 00000000..a71a7d33
--- /dev/null
+++ b/android/app/src/main/res/layout/media_player_widget.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/layout/new_app_widget.xml b/android/app/src/main/res/layout/new_app_widget.xml
deleted file mode 100644
index 99ac1b46..00000000
--- a/android/app/src/main/res/layout/new_app_widget.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
diff --git a/android/app/src/main/res/values-night-v31/themes.xml b/android/app/src/main/res/values-night-v31/themes.xml
new file mode 100644
index 00000000..db9d77f0
--- /dev/null
+++ b/android/app/src/main/res/values-night-v31/themes.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
diff --git a/android/app/src/main/res/values-v31/styles.xml b/android/app/src/main/res/values-v31/styles.xml
new file mode 100644
index 00000000..3a0135c0
--- /dev/null
+++ b/android/app/src/main/res/values-v31/styles.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
diff --git a/android/app/src/main/res/values-v31/themes.xml b/android/app/src/main/res/values-v31/themes.xml
new file mode 100644
index 00000000..8ffe2e9f
--- /dev/null
+++ b/android/app/src/main/res/values-v31/themes.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/android/app/src/main/res/values/attrs.xml b/android/app/src/main/res/values/attrs.xml
index 7781ac86..3f37ec30 100644
--- a/android/app/src/main/res/values/attrs.xml
+++ b/android/app/src/main/res/values/attrs.xml
@@ -1,7 +1,9 @@
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml
index 713e8445..4234d998 100644
--- a/android/app/src/main/res/values/styles.xml
+++ b/android/app/src/main/res/values/styles.xml
@@ -1,33 +1,42 @@
-
-
+
+
-
+
-
-
+
-
+
+
+
+
+
diff --git a/android/app/src/main/res/values/themes.xml b/android/app/src/main/res/values/themes.xml
index 254f4a55..fc7585c3 100644
--- a/android/app/src/main/res/values/themes.xml
+++ b/android/app/src/main/res/values/themes.xml
@@ -1,17 +1,17 @@
-
+ - 0dp
+
-
+
diff --git a/android/app/src/main/res/xml/media_player_widget_info.xml b/android/app/src/main/res/xml/media_player_widget_info.xml
new file mode 100644
index 00000000..45dab3b3
--- /dev/null
+++ b/android/app/src/main/res/xml/media_player_widget_info.xml
@@ -0,0 +1,14 @@
+
+
diff --git a/android/app/src/main/res/xml/new_app_widget_info.xml b/android/app/src/main/res/xml/new_app_widget_info.xml
deleted file mode 100644
index ffa76ee7..00000000
--- a/android/app/src/main/res/xml/new_app_widget_info.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-