summaryrefslogtreecommitdiff
path: root/core/src/main/java/de/danoeh
diff options
context:
space:
mode:
authorByteHamster <info@bytehamster.com>2021-01-26 12:40:16 +0100
committerByteHamster <info@bytehamster.com>2021-02-03 23:37:51 +0100
commitb6f72f8847f834eecfb392d1c5057d789cc87b04 (patch)
tree07cc1c2bae2120f72d68921d507c8c6251baea5b /core/src/main/java/de/danoeh
parentf3bf708e260822645a65963ff402794cb0cca66e (diff)
downloadAntennaPod-b6f72f8847f834eecfb392d1c5057d789cc87b04.zip
Reduce coupling between widget and playback service
Instead of binding to the service, pass the required data. This also ensures that the widget is updated instantly when calling from PlaybackService. JobService had the problem that the OS sometimes took some seconds before actually executing the job.
Diffstat (limited to 'core/src/main/java/de/danoeh')
-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 495ac40c7..8f0697e24 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;
@@ -801,8 +801,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
@@ -873,9 +874,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