summaryrefslogtreecommitdiff
path: root/core/src/main/java/de
diff options
context:
space:
mode:
authorByteHamster <ByteHamster@users.noreply.github.com>2021-02-03 23:56:33 +0100
committerGitHub <noreply@github.com>2021-02-03 23:56:33 +0100
commit9924952e2f33cca36f44463426d63411d56edfe5 (patch)
tree84392a19995f3872a9b1908dc7c50cec133552d7 /core/src/main/java/de
parent1297a168507d691a29092c89f46000736a753a04 (diff)
parentb6f72f8847f834eecfb392d1c5057d789cc87b04 (diff)
downloadAntennaPod-9924952e2f33cca36f44463426d63411d56edfe5.zip
Merge pull request #4900 from ByteHamster/decouple-widget
Reduce coupling between widget and playback service
Diffstat (limited to 'core/src/main/java/de')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/receiver/PlayerWidget.java11
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java9
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java22
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java1
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/widget/WidgetUpdater.java (renamed from core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java)197
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/widget/WidgetUpdaterJobService.java32
6 files changed, 130 insertions, 142 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/receiver/PlayerWidget.java b/core/src/main/java/de/danoeh/antennapod/core/receiver/PlayerWidget.java
index 9e9663205..cf0debed2 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/receiver/PlayerWidget.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/receiver/PlayerWidget.java
@@ -9,7 +9,7 @@ import android.util.Log;
import java.util.Arrays;
-import de.danoeh.antennapod.core.service.PlayerWidgetJobService;
+import de.danoeh.antennapod.core.widget.WidgetUpdaterJobService;
public class PlayerWidget extends AppWidgetProvider {
private static final String TAG = "PlayerWidget";
@@ -25,7 +25,7 @@ public class PlayerWidget extends AppWidgetProvider {
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "onReceive");
super.onReceive(context, intent);
- PlayerWidgetJobService.updateWidget(context);
+ WidgetUpdaterJobService.performBackgroundUpdate(context);
}
@Override
@@ -33,13 +33,14 @@ public class PlayerWidget extends AppWidgetProvider {
super.onEnabled(context);
Log.d(TAG, "Widget enabled");
setEnabled(context, true);
- PlayerWidgetJobService.updateWidget(context);
+ WidgetUpdaterJobService.performBackgroundUpdate(context);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
- Log.d(TAG, "onUpdate() called with: " + "context = [" + context + "], appWidgetManager = [" + appWidgetManager + "], appWidgetIds = [" + Arrays.toString(appWidgetIds) + "]");
- PlayerWidgetJobService.updateWidget(context);
+ Log.d(TAG, "onUpdate() called with: " + "context = [" + context + "], appWidgetManager = ["
+ + appWidgetManager + "], appWidgetIds = [" + Arrays.toString(appWidgetIds) + "]");
+ WidgetUpdaterJobService.performBackgroundUpdate(context);
}
@Override
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
index c635243c7..5bc1b19f7 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
@@ -69,7 +69,6 @@ import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.preferences.SleepTimerPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.receiver.MediaButtonReceiver;
-import de.danoeh.antennapod.core.service.PlayerWidgetJobService;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
@@ -81,6 +80,7 @@ import de.danoeh.antennapod.core.util.gui.NotificationUtils;
import de.danoeh.antennapod.core.util.playback.ExternalMedia;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
+import de.danoeh.antennapod.core.widget.WidgetUpdater;
import io.reactivex.Observable;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
@@ -794,8 +794,9 @@ public class PlaybackService extends MediaBrowserServiceCompat {
}
@Override
- public void onWidgetUpdaterTick() {
- PlayerWidgetJobService.updateWidget(getBaseContext());
+ public WidgetUpdater.WidgetState requestWidgetState() {
+ return new WidgetUpdater.WidgetState(getPlayable(), getStatus(),
+ getCurrentPosition(), getDuration(), getCurrentPlaybackSpeed());
}
@Override
@@ -866,9 +867,9 @@ public class PlaybackService extends MediaBrowserServiceCompat {
}
IntentUtils.sendLocalBroadcast(getApplicationContext(), ACTION_PLAYER_STATUS_CHANGED);
- PlayerWidgetJobService.updateWidget(getBaseContext());
bluetoothNotifyChange(newInfo, AVRCP_ACTION_PLAYER_STATUS_CHANGED);
bluetoothNotifyChange(newInfo, AVRCP_ACTION_META_CHANGED);
+ taskManager.requestWidgetUpdate();
}
@Override
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java
index 05d64ea3e..b9bc0c712 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java
@@ -8,6 +8,7 @@ import androidx.annotation.NonNull;
import android.util.Log;
import de.danoeh.antennapod.core.preferences.SleepTimerPreferences;
+import de.danoeh.antennapod.core.widget.WidgetUpdater;
import io.reactivex.disposables.Disposable;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -199,11 +200,10 @@ public class PlaybackServiceTaskManager {
*/
public synchronized void startWidgetUpdater() {
if (!isWidgetUpdaterActive() && !schedExecutor.isShutdown()) {
- Runnable widgetUpdater = callback::onWidgetUpdaterTick;
+ Runnable widgetUpdater = this::requestWidgetUpdate;
widgetUpdater = useMainThreadIfNecessary(widgetUpdater);
- widgetUpdaterFuture = schedExecutor.scheduleWithFixedDelay(widgetUpdater, WIDGET_UPDATER_NOTIFICATION_INTERVAL,
- WIDGET_UPDATER_NOTIFICATION_INTERVAL, TimeUnit.MILLISECONDS);
-
+ widgetUpdaterFuture = schedExecutor.scheduleWithFixedDelay(widgetUpdater,
+ WIDGET_UPDATER_NOTIFICATION_INTERVAL, WIDGET_UPDATER_NOTIFICATION_INTERVAL, TimeUnit.MILLISECONDS);
Log.d(TAG, "Started WidgetUpdater");
} else {
Log.d(TAG, "Call to startWidgetUpdater was ignored.");
@@ -211,6 +211,18 @@ public class PlaybackServiceTaskManager {
}
/**
+ * Retrieves information about the widget state in the calling thread and then displays it in a background thread.
+ */
+ public synchronized void requestWidgetUpdate() {
+ WidgetUpdater.WidgetState state = callback.requestWidgetState();
+ if (!schedExecutor.isShutdown()) {
+ schedExecutor.execute(() -> WidgetUpdater.updateWidget(context, state));
+ } else {
+ Log.d(TAG, "Call to requestWidgetUpdate was ignored.");
+ }
+ }
+
+ /**
* Starts a new sleep timer with the given waiting time. If another sleep timer is already active, it will be
* cancelled first.
* After waitingTime has elapsed, onSleepTimerExpired() will be called.
@@ -464,7 +476,7 @@ public class PlaybackServiceTaskManager {
void onSleepTimerReset();
- void onWidgetUpdaterTick();
+ WidgetUpdater.WidgetState requestWidgetState();
void onChapterLoaded(Playable media);
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java
index 59abdd10a..e2ce86ceb 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java
@@ -21,6 +21,7 @@ import java.util.List;
*/
public interface Playable extends Parcelable,
ShownotesProvider, ImageResource {
+ public static final int INVALID_TIME = -1;
/**
* Save information about the playable in a preference so that it can be
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java b/core/src/main/java/de/danoeh/antennapod/core/widget/WidgetUpdater.java
index 2ed887fbb..1622fcb8f 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/widget/WidgetUpdater.java
@@ -1,17 +1,13 @@
-package de.danoeh.antennapod.core.service;
+package de.danoeh.antennapod.core.widget;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.os.Bundle;
-import android.os.IBinder;
-import androidx.annotation.NonNull;
-import androidx.core.app.SafeJobIntentService;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
@@ -24,7 +20,6 @@ import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
-import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils;
import de.danoeh.antennapod.core.receiver.MediaButtonReceiver;
import de.danoeh.antennapod.core.receiver.PlayerWidget;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
@@ -35,107 +30,65 @@ import de.danoeh.antennapod.core.util.TimeSpeedConverter;
import de.danoeh.antennapod.core.util.playback.Playable;
/**
- * Updates the state of the player widget
+ * Updates the state of the player widget.
*/
-public class PlayerWidgetJobService extends SafeJobIntentService {
-
- private static final String TAG = "PlayerWidgetJobService";
-
- private PlaybackService playbackService;
- private final Object waitForService = new Object();
- private final Object waitUsingService = new Object();
-
- private static final int JOB_ID = -17001;
-
- public static void updateWidget(Context context) {
- enqueueWork(context, PlayerWidgetJobService.class, JOB_ID, new Intent(context, PlayerWidgetJobService.class));
- }
-
- @Override
- protected void onHandleWork(@NonNull Intent intent) {
- if (!PlayerWidget.isEnabled(getApplicationContext())) {
- return;
+public abstract class WidgetUpdater {
+ private static final String TAG = "WidgetUpdater";
+
+ public static class WidgetState {
+ final Playable media;
+ final PlayerStatus status;
+ final int position;
+ final int duration;
+ final float playbackSpeed;
+
+ public WidgetState(Playable media, PlayerStatus status, int position, int duration, float playbackSpeed) {
+ this.media = media;
+ this.status = status;
+ this.position = position;
+ this.duration = duration;
+ this.playbackSpeed = playbackSpeed;
}
- synchronized (waitForService) {
- if (PlaybackService.isRunning && playbackService == null) {
- bindService(new Intent(this, PlaybackService.class), mConnection, 0);
- while (playbackService == null) {
- try {
- waitForService.wait();
- } catch (InterruptedException e) {
- return;
- }
- }
- }
- }
-
- synchronized (waitUsingService) {
- updateViews();
- }
-
- if (playbackService != null) {
- try {
- unbindService(mConnection);
- } catch (IllegalArgumentException e) {
- Log.w(TAG, "IllegalArgumentException when trying to unbind service");
- }
+ public WidgetState(PlayerStatus status) {
+ this(null, status, Playable.INVALID_TIME, Playable.INVALID_TIME, 1.0f);
}
}
/**
- * Returns number of cells needed for given size of the widget.
- *
- * @param size Widget size in dp.
- * @return Size in number of cells.
+ * Update the widgets with the given parameters. Must be called in a background thread.
*/
- private static int getCellsForSize(int size) {
- int n = 2;
- while (70 * n - 30 < size) {
- ++n;
+ public static void updateWidget(Context context, WidgetState widgetState) {
+ if (!PlayerWidget.isEnabled(context) || widgetState == null) {
+ return;
}
- return n - 1;
- }
-
- private void updateViews() {
-
- ComponentName playerWidget = new ComponentName(this, PlayerWidget.class);
- AppWidgetManager manager = AppWidgetManager.getInstance(this);
+ ComponentName playerWidget = new ComponentName(context, PlayerWidget.class);
+ AppWidgetManager manager = AppWidgetManager.getInstance(context);
int[] widgetIds = manager.getAppWidgetIds(playerWidget);
- final PendingIntent startMediaPlayer = PendingIntent.getActivity(this, R.id.pending_intent_player_activity,
- PlaybackService.getPlayerActivityIntent(this), PendingIntent.FLAG_UPDATE_CURRENT);
+ final PendingIntent startMediaPlayer = PendingIntent.getActivity(context, R.id.pending_intent_player_activity,
+ PlaybackService.getPlayerActivityIntent(context), PendingIntent.FLAG_UPDATE_CURRENT);
RemoteViews views;
- views = new RemoteViews(getPackageName(), R.layout.player_widget);
+ views = new RemoteViews(context.getPackageName(), R.layout.player_widget);
- Playable media;
- PlayerStatus status;
- if (playbackService != null) {
- media = playbackService.getPlayable();
- status = playbackService.getStatus();
- } else {
- media = Playable.PlayableUtils.createInstanceFromPreferences(getApplicationContext());
- status = PlayerStatus.STOPPED;
- }
-
- if (media != null) {
+ if (widgetState.media != null) {
Bitmap icon;
- int iconSize = getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
+ int iconSize = context.getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
views.setOnClickPendingIntent(R.id.layout_left, startMediaPlayer);
views.setOnClickPendingIntent(R.id.imgvCover, startMediaPlayer);
try {
- icon = Glide.with(PlayerWidgetJobService.this)
+ icon = Glide.with(context)
.asBitmap()
- .load(ImageResourceUtils.getImageLocation(media))
+ .load(ImageResourceUtils.getImageLocation(widgetState.media))
.apply(RequestOptions.diskCacheStrategyOf(ApGlideSettings.AP_DISK_CACHE_STRATEGY))
.submit(iconSize, iconSize)
.get(500, TimeUnit.MILLISECONDS);
views.setImageViewBitmap(R.id.imgvCover, icon);
} catch (Throwable tr1) {
try {
- icon = Glide.with(PlayerWidgetJobService.this)
+ icon = Glide.with(context)
.asBitmap()
- .load(ImageResourceUtils.getFallbackImageLocation(media))
+ .load(ImageResourceUtils.getFallbackImageLocation(widgetState.media))
.apply(RequestOptions.diskCacheStrategyOf(ApGlideSettings.AP_DISK_CACHE_STRATEGY))
.submit(iconSize, iconSize)
.get(500, TimeUnit.MILLISECONDS);
@@ -146,50 +99,44 @@ public class PlayerWidgetJobService extends SafeJobIntentService {
}
}
- views.setTextViewText(R.id.txtvTitle, media.getEpisodeTitle());
+ views.setTextViewText(R.id.txtvTitle, widgetState.media.getEpisodeTitle());
views.setViewVisibility(R.id.txtvTitle, View.VISIBLE);
views.setViewVisibility(R.id.txtNoPlaying, View.GONE);
- String progressString;
- if (playbackService != null) {
- progressString = getProgressString(playbackService.getCurrentPosition(),
- playbackService.getDuration(), playbackService.getCurrentPlaybackSpeed());
- } else {
- progressString = getProgressString(media.getPosition(), media.getDuration(), PlaybackSpeedUtils.getCurrentPlaybackSpeed(media));
- }
-
+ String progressString = getProgressString(widgetState.position,
+ widgetState.duration, widgetState.playbackSpeed);
if (progressString != null) {
views.setViewVisibility(R.id.txtvProgress, View.VISIBLE);
views.setTextViewText(R.id.txtvProgress, progressString);
}
- if (status == PlayerStatus.PLAYING) {
+ if (widgetState.status == PlayerStatus.PLAYING) {
views.setImageViewResource(R.id.butPlay, R.drawable.ic_av_pause_white_48dp);
- views.setContentDescription(R.id.butPlay, getString(R.string.pause_label));
+ views.setContentDescription(R.id.butPlay, context.getString(R.string.pause_label));
views.setImageViewResource(R.id.butPlayExtended, R.drawable.ic_av_pause_white_48dp);
- views.setContentDescription(R.id.butPlayExtended, getString(R.string.pause_label));
+ views.setContentDescription(R.id.butPlayExtended, context.getString(R.string.pause_label));
} else {
views.setImageViewResource(R.id.butPlay, R.drawable.ic_av_play_white_48dp);
- views.setContentDescription(R.id.butPlay, getString(R.string.play_label));
+ views.setContentDescription(R.id.butPlay, context.getString(R.string.play_label));
views.setImageViewResource(R.id.butPlayExtended, R.drawable.ic_av_play_white_48dp);
- views.setContentDescription(R.id.butPlayExtended, getString(R.string.play_label));
+ views.setContentDescription(R.id.butPlayExtended, context.getString(R.string.play_label));
}
views.setOnClickPendingIntent(R.id.butPlay,
- createMediaButtonIntent(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
+ createMediaButtonIntent(context, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
views.setOnClickPendingIntent(R.id.butPlayExtended,
- createMediaButtonIntent(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
+ createMediaButtonIntent(context, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
views.setOnClickPendingIntent(R.id.butRew,
- createMediaButtonIntent(KeyEvent.KEYCODE_MEDIA_REWIND));
+ createMediaButtonIntent(context, KeyEvent.KEYCODE_MEDIA_REWIND));
views.setOnClickPendingIntent(R.id.butFastForward,
- createMediaButtonIntent(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD));
+ createMediaButtonIntent(context, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD));
views.setOnClickPendingIntent(R.id.butSkip,
- createMediaButtonIntent(KeyEvent.KEYCODE_MEDIA_NEXT));
+ createMediaButtonIntent(context, KeyEvent.KEYCODE_MEDIA_NEXT));
} else {
// start the app if they click anything
views.setOnClickPendingIntent(R.id.layout_left, startMediaPlayer);
views.setOnClickPendingIntent(R.id.butPlay, startMediaPlayer);
views.setOnClickPendingIntent(R.id.butPlayExtended,
- createMediaButtonIntent(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
+ createMediaButtonIntent(context, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
views.setViewVisibility(R.id.txtvProgress, View.GONE);
views.setViewVisibility(R.id.txtvTitle, View.GONE);
views.setViewVisibility(R.id.txtNoPlaying, View.VISIBLE);
@@ -201,7 +148,7 @@ public class PlayerWidgetJobService extends SafeJobIntentService {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
for (int id : widgetIds) {
Bundle options = manager.getAppWidgetOptions(id);
- SharedPreferences prefs = getSharedPreferences(PlayerWidget.PREFS_NAME, Context.MODE_PRIVATE);
+ SharedPreferences prefs = context.getSharedPreferences(PlayerWidget.PREFS_NAME, Context.MODE_PRIVATE);
int minWidth = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
int columns = getCellsForSize(minWidth);
if (columns < 3) {
@@ -232,18 +179,32 @@ public class PlayerWidgetJobService extends SafeJobIntentService {
}
/**
- * Creates an intent which fakes a mediabutton press
+ * Returns number of cells needed for given size of the widget.
+ *
+ * @param size Widget size in dp.
+ * @return Size in number of cells.
*/
- private PendingIntent createMediaButtonIntent(int eventCode) {
+ private static int getCellsForSize(int size) {
+ int n = 2;
+ while (70 * n - 30 < size) {
+ ++n;
+ }
+ return n - 1;
+ }
+
+ /**
+ * Creates an intent which fakes a mediabutton press.
+ */
+ private static PendingIntent createMediaButtonIntent(Context context, int eventCode) {
KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, eventCode);
- Intent startingIntent = new Intent(getBaseContext(), MediaButtonReceiver.class);
+ Intent startingIntent = new Intent(context, MediaButtonReceiver.class);
startingIntent.setAction(MediaButtonReceiver.NOTIFY_BUTTON_RECEIVER);
startingIntent.putExtra(Intent.EXTRA_KEY_EVENT, event);
- return PendingIntent.getBroadcast(this, eventCode, startingIntent, 0);
+ return PendingIntent.getBroadcast(context, eventCode, startingIntent, 0);
}
- private String getProgressString(int position, int duration, float speed) {
+ private static String getProgressString(int position, int duration, float speed) {
if (position >= 0 && duration > 0) {
TimeSpeedConverter converter = new TimeSpeedConverter(speed);
position = converter.convert(position);
@@ -254,24 +215,4 @@ public class PlayerWidgetJobService extends SafeJobIntentService {
return null;
}
}
-
- private final ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- Log.d(TAG, "Connection to service established");
- if (service instanceof PlaybackService.LocalBinder) {
- synchronized (waitForService) {
- playbackService = ((PlaybackService.LocalBinder) service).getService();
- waitForService.notifyAll();
- }
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- synchronized (waitUsingService) {
- playbackService = null;
- }
- Log.d(TAG, "Disconnected from service");
- }
- };
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/widget/WidgetUpdaterJobService.java b/core/src/main/java/de/danoeh/antennapod/core/widget/WidgetUpdaterJobService.java
new file mode 100644
index 000000000..1db7928b4
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/widget/WidgetUpdaterJobService.java
@@ -0,0 +1,32 @@
+package de.danoeh.antennapod.core.widget;
+
+import android.content.Context;
+import android.content.Intent;
+import androidx.annotation.NonNull;
+import androidx.core.app.SafeJobIntentService;
+import de.danoeh.antennapod.core.feed.util.PlaybackSpeedUtils;
+import de.danoeh.antennapod.core.service.playback.PlayerStatus;
+import de.danoeh.antennapod.core.util.playback.Playable;
+
+public class WidgetUpdaterJobService extends SafeJobIntentService {
+ private static final int JOB_ID = -17001;
+
+ /**
+ * Loads the current media from the database and updates the widget in a background job.
+ */
+ public static void performBackgroundUpdate(Context context) {
+ enqueueWork(context, WidgetUpdaterJobService.class,
+ WidgetUpdaterJobService.JOB_ID, new Intent(context, WidgetUpdaterJobService.class));
+ }
+
+ @Override
+ protected void onHandleWork(@NonNull Intent intent) {
+ Playable media = Playable.PlayableUtils.createInstanceFromPreferences(getApplicationContext());
+ if (media != null) {
+ WidgetUpdater.updateWidget(this, new WidgetUpdater.WidgetState(media, PlayerStatus.STOPPED,
+ media.getPosition(), media.getDuration(), PlaybackSpeedUtils.getCurrentPlaybackSpeed(media)));
+ } else {
+ WidgetUpdater.updateWidget(this, new WidgetUpdater.WidgetState(PlayerStatus.STOPPED));
+ }
+ }
+} \ No newline at end of file