Migrated to WorkManager to allow retrying
This commit is contained in:
parent
2b8c3ff04e
commit
ef121892f7
|
@ -143,6 +143,7 @@ dependencies {
|
||||||
implementation "androidx.recyclerview:recyclerview:1.0.0"
|
implementation "androidx.recyclerview:recyclerview:1.0.0"
|
||||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
|
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
|
||||||
implementation "androidx.media:media:1.1.0"
|
implementation "androidx.media:media:1.1.0"
|
||||||
|
implementation "android.arch.work:work-runtime:$workManagerVersion"
|
||||||
implementation "com.google.android.material:material:1.0.0"
|
implementation "com.google.android.material:material:1.0.0"
|
||||||
annotationProcessor "androidx.annotation:annotation:1.1.0"
|
annotationProcessor "androidx.annotation:annotation:1.1.0"
|
||||||
compileOnly "com.google.android.wearable:wearable:$wearableSupportVersion"
|
compileOnly "com.google.android.wearable:wearable:$wearableSupportVersion"
|
||||||
|
|
|
@ -25,11 +25,6 @@
|
||||||
<action android:name="android.media.browse.MediaBrowserService"/>
|
<action android:name="android.media.browse.MediaBrowserService"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
<service
|
|
||||||
android:name=".sync.SyncService"
|
|
||||||
android:permission="android.permission.BIND_JOB_SERVICE"
|
|
||||||
android:enabled="true"
|
|
||||||
android:exported="false" />
|
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".receiver.MediaButtonReceiver"
|
android:name=".receiver.MediaButtonReceiver"
|
||||||
|
|
|
@ -10,12 +10,19 @@ import android.util.Log;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.collection.ArrayMap;
|
import androidx.collection.ArrayMap;
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
import androidx.core.app.SafeJobIntentService;
|
|
||||||
import androidx.core.util.Pair;
|
import androidx.core.util.Pair;
|
||||||
|
import androidx.work.Constraints;
|
||||||
|
import androidx.work.ExistingWorkPolicy;
|
||||||
|
import androidx.work.NetworkType;
|
||||||
|
import androidx.work.OneTimeWorkRequest;
|
||||||
|
import androidx.work.WorkManager;
|
||||||
|
import androidx.work.Worker;
|
||||||
|
import androidx.work.WorkerParameters;
|
||||||
import de.danoeh.antennapod.core.R;
|
import de.danoeh.antennapod.core.R;
|
||||||
import de.danoeh.antennapod.core.feed.Feed;
|
import de.danoeh.antennapod.core.feed.Feed;
|
||||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||||
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
|
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
|
||||||
import de.danoeh.antennapod.core.storage.DBReader;
|
import de.danoeh.antennapod.core.storage.DBReader;
|
||||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||||
|
@ -29,7 +36,6 @@ import de.danoeh.antennapod.core.sync.model.ISyncService;
|
||||||
import de.danoeh.antennapod.core.sync.model.SubscriptionChanges;
|
import de.danoeh.antennapod.core.sync.model.SubscriptionChanges;
|
||||||
import de.danoeh.antennapod.core.sync.model.SyncServiceException;
|
import de.danoeh.antennapod.core.sync.model.SyncServiceException;
|
||||||
import de.danoeh.antennapod.core.sync.model.UploadChangesResponse;
|
import de.danoeh.antennapod.core.sync.model.UploadChangesResponse;
|
||||||
import de.danoeh.antennapod.core.util.NetworkUtils;
|
|
||||||
import de.danoeh.antennapod.core.util.URLChecker;
|
import de.danoeh.antennapod.core.util.URLChecker;
|
||||||
import de.danoeh.antennapod.core.util.gui.NotificationUtils;
|
import de.danoeh.antennapod.core.util.gui.NotificationUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
@ -39,8 +45,9 @@ import org.json.JSONException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class SyncService extends SafeJobIntentService {
|
public class SyncService extends Worker {
|
||||||
private static final String PREF_NAME = "SyncService";
|
private static final String PREF_NAME = "SyncService";
|
||||||
private static final String PREF_LAST_SUBSCRIPTION_SYNC_TIMESTAMP = "last_sync_timestamp";
|
private static final String PREF_LAST_SUBSCRIPTION_SYNC_TIMESTAMP = "last_sync_timestamp";
|
||||||
private static final String PREF_LAST_EPISODE_ACTIONS_SYNC_TIMESTAMP = "last_episode_actions_sync_timestamp";
|
private static final String PREF_LAST_EPISODE_ACTIONS_SYNC_TIMESTAMP = "last_episode_actions_sync_timestamp";
|
||||||
|
@ -49,21 +56,20 @@ public class SyncService extends SafeJobIntentService {
|
||||||
private static final String PREF_QUEUED_EPISODE_ACTIONS = "sync_queued_episode_actions";
|
private static final String PREF_QUEUED_EPISODE_ACTIONS = "sync_queued_episode_actions";
|
||||||
private static final String PREF_LAST_SYNC_ATTEMPT_TIMESTAMP = "last_sync_attempt_timestamp";
|
private static final String PREF_LAST_SYNC_ATTEMPT_TIMESTAMP = "last_sync_attempt_timestamp";
|
||||||
private static final String TAG = "SyncService";
|
private static final String TAG = "SyncService";
|
||||||
private static final int JOB_ID = -17000;
|
private static final String WORK_ID_SYNC = "SyncServiceWorkId";
|
||||||
private static final Object lock = new Object();
|
private static final Object lock = new Object();
|
||||||
private static boolean syncPending = false;
|
private static boolean syncPending = false;
|
||||||
|
|
||||||
private ISyncService syncServiceImpl;
|
private ISyncService syncServiceImpl;
|
||||||
|
|
||||||
@Override
|
public SyncService(@NonNull Context context, @NonNull WorkerParameters params) {
|
||||||
protected void onHandleWork(@NonNull Intent intent) {
|
super(context, params);
|
||||||
syncServiceImpl = new GpodnetService(AntennapodHttpClient.getHttpClient(), GpodnetService.DEFAULT_BASE_HOST);
|
}
|
||||||
|
|
||||||
if (!NetworkUtils.networkAvailable()) {
|
@Override
|
||||||
stopForeground(true);
|
@NonNull
|
||||||
stopSelf();
|
public Result doWork() {
|
||||||
return;
|
syncServiceImpl = new GpodnetService(AntennapodHttpClient.getHttpClient(), GpodnetService.DEFAULT_BASE_HOST);
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Leave some time, so other actions can be queued
|
// Leave some time, so other actions can be queued
|
||||||
|
@ -79,12 +85,15 @@ public class SyncService extends SafeJobIntentService {
|
||||||
syncEpisodeActions();
|
syncEpisodeActions();
|
||||||
syncServiceImpl.logout();
|
syncServiceImpl.logout();
|
||||||
clearErrorNotifications();
|
clearErrorNotifications();
|
||||||
|
return Result.success();
|
||||||
} catch (SyncServiceException e) {
|
} catch (SyncServiceException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
updateErrorNotification(e);
|
updateErrorNotification(e);
|
||||||
|
return Result.failure();
|
||||||
|
} finally {
|
||||||
|
getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE).edit()
|
||||||
|
.putLong(PREF_LAST_SYNC_ATTEMPT_TIMESTAMP, System.currentTimeMillis()).apply();
|
||||||
}
|
}
|
||||||
getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE).edit()
|
|
||||||
.putLong(PREF_LAST_SYNC_ATTEMPT_TIMESTAMP, System.currentTimeMillis()).apply();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void clearQueue(Context context) {
|
public static void clearQueue(Context context) {
|
||||||
|
@ -148,7 +157,19 @@ public class SyncService extends SafeJobIntentService {
|
||||||
public static void sync(Context context) {
|
public static void sync(Context context) {
|
||||||
if (!syncPending) {
|
if (!syncPending) {
|
||||||
syncPending = true;
|
syncPending = true;
|
||||||
enqueueWork(context, SyncService.class, JOB_ID, new Intent());
|
|
||||||
|
Constraints.Builder constraints = new Constraints.Builder();
|
||||||
|
if (UserPreferences.isAllowMobileFeedRefresh()) {
|
||||||
|
constraints.setRequiredNetworkType(NetworkType.CONNECTED);
|
||||||
|
} else {
|
||||||
|
constraints.setRequiredNetworkType(NetworkType.UNMETERED);
|
||||||
|
}
|
||||||
|
|
||||||
|
OneTimeWorkRequest workRequest = new OneTimeWorkRequest.Builder(SyncService.class)
|
||||||
|
.setConstraints(constraints.build())
|
||||||
|
.setInitialDelay(0L, TimeUnit.MILLISECONDS)
|
||||||
|
.build();
|
||||||
|
WorkManager.getInstance().enqueueUniqueWork(WORK_ID_SYNC, ExistingWorkPolicy.REPLACE, workRequest);
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "Ignored sync: Job already enqueued");
|
Log.d(TAG, "Ignored sync: Job already enqueued");
|
||||||
}
|
}
|
||||||
|
@ -169,7 +190,7 @@ public class SyncService extends SafeJobIntentService {
|
||||||
private List<EpisodeAction> getQueuedEpisodeActions() {
|
private List<EpisodeAction> getQueuedEpisodeActions() {
|
||||||
ArrayList<EpisodeAction> actions = new ArrayList<>();
|
ArrayList<EpisodeAction> actions = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
SharedPreferences prefs = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
|
SharedPreferences prefs = getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
|
||||||
String json = prefs.getString(PREF_QUEUED_EPISODE_ACTIONS, "[]");
|
String json = prefs.getString(PREF_QUEUED_EPISODE_ACTIONS, "[]");
|
||||||
JSONArray queue = new JSONArray(json);
|
JSONArray queue = new JSONArray(json);
|
||||||
for (int i = 0; i < queue.length(); i++) {
|
for (int i = 0; i < queue.length(); i++) {
|
||||||
|
@ -184,7 +205,7 @@ public class SyncService extends SafeJobIntentService {
|
||||||
private List<String> getQueuedRemovedFeeds() {
|
private List<String> getQueuedRemovedFeeds() {
|
||||||
ArrayList<String> actions = new ArrayList<>();
|
ArrayList<String> actions = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
SharedPreferences prefs = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
|
SharedPreferences prefs = getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
|
||||||
String json = prefs.getString(PREF_QUEUED_FEEDS_REMOVED, "[]");
|
String json = prefs.getString(PREF_QUEUED_FEEDS_REMOVED, "[]");
|
||||||
JSONArray queue = new JSONArray(json);
|
JSONArray queue = new JSONArray(json);
|
||||||
for (int i = 0; i < queue.length(); i++) {
|
for (int i = 0; i < queue.length(); i++) {
|
||||||
|
@ -199,7 +220,7 @@ public class SyncService extends SafeJobIntentService {
|
||||||
private List<String> getQueuedAddedFeeds() {
|
private List<String> getQueuedAddedFeeds() {
|
||||||
ArrayList<String> actions = new ArrayList<>();
|
ArrayList<String> actions = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
SharedPreferences prefs = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
|
SharedPreferences prefs = getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
|
||||||
String json = prefs.getString(PREF_QUEUED_FEEDS_ADDED, "[]");
|
String json = prefs.getString(PREF_QUEUED_FEEDS_ADDED, "[]");
|
||||||
JSONArray queue = new JSONArray(json);
|
JSONArray queue = new JSONArray(json);
|
||||||
for (int i = 0; i < queue.length(); i++) {
|
for (int i = 0; i < queue.length(); i++) {
|
||||||
|
@ -212,7 +233,7 @@ public class SyncService extends SafeJobIntentService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void syncSubscriptions() throws SyncServiceException {
|
private void syncSubscriptions() throws SyncServiceException {
|
||||||
final long lastSync = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
|
final long lastSync = getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
|
||||||
.getLong(PREF_LAST_SUBSCRIPTION_SYNC_TIMESTAMP, 0);
|
.getLong(PREF_LAST_SUBSCRIPTION_SYNC_TIMESTAMP, 0);
|
||||||
final List<String> localSubscriptions = DBReader.getFeedListDownloadUrls();
|
final List<String> localSubscriptions = DBReader.getFeedListDownloadUrls();
|
||||||
SubscriptionChanges subscriptionChanges = syncServiceImpl.getSubscriptionChanges(lastSync);
|
SubscriptionChanges subscriptionChanges = syncServiceImpl.getSubscriptionChanges(lastSync);
|
||||||
|
@ -226,7 +247,7 @@ public class SyncService extends SafeJobIntentService {
|
||||||
if (!URLChecker.containsUrl(localSubscriptions, downloadUrl) && !queuedRemovedFeeds.contains(downloadUrl)) {
|
if (!URLChecker.containsUrl(localSubscriptions, downloadUrl) && !queuedRemovedFeeds.contains(downloadUrl)) {
|
||||||
Feed feed = new Feed(downloadUrl, null);
|
Feed feed = new Feed(downloadUrl, null);
|
||||||
try {
|
try {
|
||||||
DownloadRequester.getInstance().downloadFeed(this, feed);
|
DownloadRequester.getInstance().downloadFeed(getApplicationContext(), feed);
|
||||||
} catch (DownloadRequestException e) {
|
} catch (DownloadRequestException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
@ -236,7 +257,7 @@ public class SyncService extends SafeJobIntentService {
|
||||||
// remove subscription if not just subscribed (again)
|
// remove subscription if not just subscribed (again)
|
||||||
for (String downloadUrl : subscriptionChanges.getRemoved()) {
|
for (String downloadUrl : subscriptionChanges.getRemoved()) {
|
||||||
if (!queuedAddedFeeds.contains(downloadUrl)) {
|
if (!queuedAddedFeeds.contains(downloadUrl)) {
|
||||||
DBTasks.removeFeedWithDownloadUrl(this, downloadUrl);
|
DBTasks.removeFeedWithDownloadUrl(getApplicationContext(), downloadUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,19 +275,19 @@ public class SyncService extends SafeJobIntentService {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
UploadChangesResponse uploadResponse = syncServiceImpl
|
UploadChangesResponse uploadResponse = syncServiceImpl
|
||||||
.uploadSubscriptionChanges(queuedAddedFeeds, queuedRemovedFeeds);
|
.uploadSubscriptionChanges(queuedAddedFeeds, queuedRemovedFeeds);
|
||||||
getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE).edit()
|
getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE).edit()
|
||||||
.putString(PREF_QUEUED_FEEDS_ADDED, "[]").apply();
|
.putString(PREF_QUEUED_FEEDS_ADDED, "[]").apply();
|
||||||
getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE).edit()
|
getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE).edit()
|
||||||
.putString(PREF_QUEUED_FEEDS_REMOVED, "[]").apply();
|
.putString(PREF_QUEUED_FEEDS_REMOVED, "[]").apply();
|
||||||
newTimeStamp = uploadResponse.timestamp;
|
newTimeStamp = uploadResponse.timestamp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE).edit()
|
getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE).edit()
|
||||||
.putLong(PREF_LAST_SUBSCRIPTION_SYNC_TIMESTAMP, newTimeStamp).apply();
|
.putLong(PREF_LAST_SUBSCRIPTION_SYNC_TIMESTAMP, newTimeStamp).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void syncEpisodeActions() throws SyncServiceException {
|
private void syncEpisodeActions() throws SyncServiceException {
|
||||||
final long lastSync = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
|
final long lastSync = getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
|
||||||
.getLong(PREF_LAST_EPISODE_ACTIONS_SYNC_TIMESTAMP, 0);
|
.getLong(PREF_LAST_EPISODE_ACTIONS_SYNC_TIMESTAMP, 0);
|
||||||
EpisodeActionChanges getResponse = syncServiceImpl.getEpisodeActionChanges(lastSync);
|
EpisodeActionChanges getResponse = syncServiceImpl.getEpisodeActionChanges(lastSync);
|
||||||
long newTimeStamp = getResponse.getTimestamp();
|
long newTimeStamp = getResponse.getTimestamp();
|
||||||
|
@ -281,11 +302,11 @@ public class SyncService extends SafeJobIntentService {
|
||||||
UploadChangesResponse postResponse = syncServiceImpl.uploadEpisodeActions(queuedEpisodeActions);
|
UploadChangesResponse postResponse = syncServiceImpl.uploadEpisodeActions(queuedEpisodeActions);
|
||||||
newTimeStamp = postResponse.timestamp;
|
newTimeStamp = postResponse.timestamp;
|
||||||
Log.d(TAG, "Upload episode response: " + postResponse);
|
Log.d(TAG, "Upload episode response: " + postResponse);
|
||||||
getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE).edit()
|
getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE).edit()
|
||||||
.putString(PREF_QUEUED_EPISODE_ACTIONS, "[]").apply();
|
.putString(PREF_QUEUED_EPISODE_ACTIONS, "[]").apply();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE).edit()
|
getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE).edit()
|
||||||
.putLong(PREF_LAST_EPISODE_ACTIONS_SYNC_TIMESTAMP, newTimeStamp).apply();
|
.putLong(PREF_LAST_EPISODE_ACTIONS_SYNC_TIMESTAMP, newTimeStamp).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,26 +377,32 @@ public class SyncService extends SafeJobIntentService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearErrorNotifications() {
|
private void clearErrorNotifications() {
|
||||||
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager nm = (NotificationManager) getApplicationContext()
|
||||||
|
.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
nm.cancel(R.id.notification_gpodnet_sync_error);
|
nm.cancel(R.id.notification_gpodnet_sync_error);
|
||||||
nm.cancel(R.id.notification_gpodnet_sync_autherror);
|
nm.cancel(R.id.notification_gpodnet_sync_autherror);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateErrorNotification(SyncServiceException exception) {
|
private void updateErrorNotification(SyncServiceException exception) {
|
||||||
Log.d(TAG, "Posting error notification");
|
Log.d(TAG, "Posting error notification");
|
||||||
final String description = getString(R.string.gpodnetsync_error_descr) + exception.getMessage();
|
final String description = getApplicationContext().getString(R.string.gpodnetsync_error_descr)
|
||||||
|
+ exception.getMessage();
|
||||||
|
|
||||||
Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName());
|
Intent intent = getApplicationContext().getPackageManager().getLaunchIntentForPackage(
|
||||||
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
getApplicationContext().getPackageName());
|
||||||
Notification notification = new NotificationCompat.Builder(this, NotificationUtils.CHANNEL_ID_ERROR)
|
PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent,
|
||||||
.setContentTitle(getString(R.string.gpodnetsync_error_title))
|
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
Notification notification = new NotificationCompat.Builder(getApplicationContext(),
|
||||||
|
NotificationUtils.CHANNEL_ID_ERROR)
|
||||||
|
.setContentTitle(getApplicationContext().getString(R.string.gpodnetsync_error_title))
|
||||||
.setContentText(description)
|
.setContentText(description)
|
||||||
.setContentIntent(pendingIntent)
|
.setContentIntent(pendingIntent)
|
||||||
.setSmallIcon(R.drawable.ic_notification_sync_error)
|
.setSmallIcon(R.drawable.ic_notification_sync_error)
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||||
.build();
|
.build();
|
||||||
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager nm = (NotificationManager) getApplicationContext()
|
||||||
|
.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
nm.notify(R.id.notification_gpodnet_sync_error, notification);
|
nm.notify(R.id.notification_gpodnet_sync_error, notification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue