summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java64
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/SyncServiceEvent.java13
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java60
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java18
-rw-r--r--core/src/main/res/values/strings.xml10
5 files changed, 109 insertions, 56 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java
index 5b622b5c8..95af40d47 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderPreferencesFragment.java
@@ -10,10 +10,15 @@ import android.text.format.DateUtils;
import android.widget.Toast;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.PreferenceActivity;
+import de.danoeh.antennapod.core.event.SyncServiceEvent;
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
import de.danoeh.antennapod.core.sync.SyncService;
import de.danoeh.antennapod.dialog.AuthenticationDialog;
import de.danoeh.antennapod.dialog.GpodnetSetHostnameDialog;
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
public class GpodderPreferencesFragment extends PreferenceFragmentCompat {
private static final String PREF_GPODNET_LOGIN = "pref_gpodnet_authenticate";
@@ -34,28 +39,27 @@ public class GpodderPreferencesFragment extends PreferenceFragmentCompat {
public void onStart() {
super.onStart();
((PreferenceActivity) getActivity()).getSupportActionBar().setTitle(R.string.gpodnet_main_label);
- }
-
- @Override
- public void onResume() {
- super.onResume();
- GpodnetPreferences.registerOnSharedPreferenceChangeListener(gpoddernetListener);
updateGpodnetPreferenceScreen();
+ EventBus.getDefault().register(this);
}
@Override
- public void onPause() {
- super.onPause();
- GpodnetPreferences.unregisterOnSharedPreferenceChangeListener(gpoddernetListener);
+ public void onStop() {
+ super.onStop();
+ EventBus.getDefault().unregister(this);
+ ((PreferenceActivity) getActivity()).getSupportActionBar().setSubtitle("");
}
- private final SharedPreferences.OnSharedPreferenceChangeListener gpoddernetListener =
- (sharedPreferences, key) -> {
- //if (GpodnetPreferences.PREF_LAST_SYNC_ATTEMPT_TIMESTAMP.equals(key)) {
- // updateLastGpodnetSyncReport(GpodnetPreferences.getLastSyncAttemptResult(),
- // GpodnetPreferences.getLastSyncAttemptTimestamp());
- //}
- };
+ @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
+ public void syncStatusChanged(SyncServiceEvent event) {
+ if (event.getMessageResId() == R.string.sync_status_error
+ || event.getMessageResId() == R.string.sync_status_success) {
+ updateLastGpodnetSyncReport(SyncService.isLastSyncSuccessful(getContext()),
+ SyncService.getLastSyncAttempt(getContext()));
+ } else {
+ ((PreferenceActivity) getActivity()).getSupportActionBar().setSubtitle(event.getMessageResId());
+ }
+ }
private void setupGpodderScreen() {
final Activity activity = getActivity();
@@ -76,12 +80,10 @@ public class GpodderPreferencesFragment extends PreferenceFragmentCompat {
});
findPreference(PREF_GPODNET_SYNC).setOnPreferenceClickListener(preference -> {
SyncService.sync(getActivity().getApplicationContext());
- Toast.makeText(getActivity(), R.string.pref_gpodnet_sync_started, Toast.LENGTH_SHORT).show();
return true;
});
findPreference(PREF_GPODNET_FORCE_FULL_SYNC).setOnPreferenceClickListener(preference -> {
SyncService.fullSync(getContext());
- Toast.makeText(getActivity(), R.string.pref_gpodnet_sync_started, Toast.LENGTH_SHORT).show();
return true;
});
findPreference(PREF_GPODNET_LOGOUT).setOnPreferenceClickListener(preference -> {
@@ -106,13 +108,13 @@ public class GpodderPreferencesFragment extends PreferenceFragmentCompat {
findPreference(PREF_GPODNET_FORCE_FULL_SYNC).setEnabled(loggedIn);
findPreference(PREF_GPODNET_LOGOUT).setEnabled(loggedIn);
findPreference(PREF_GPODNET_NOTIFICATIONS).setEnabled(loggedIn);
- if(loggedIn) {
+ if (loggedIn) {
String format = getActivity().getString(R.string.pref_gpodnet_login_status);
String summary = String.format(format, GpodnetPreferences.getUsername(),
GpodnetPreferences.getDeviceID());
findPreference(PREF_GPODNET_LOGOUT).setSummary(Html.fromHtml(summary));
- //updateLastGpodnetSyncReport(GpodnetPreferences.getLastSyncAttemptResult(),
- // GpodnetPreferences.getLastSyncAttemptTimestamp());
+ updateLastGpodnetSyncReport(SyncService.isLastSyncSuccessful(getContext()),
+ SyncService.getLastSyncAttempt(getContext()));
} else {
findPreference(PREF_GPODNET_LOGOUT).setSummary(null);
updateLastGpodnetSyncReport(false, 0);
@@ -121,20 +123,10 @@ public class GpodderPreferencesFragment extends PreferenceFragmentCompat {
}
private void updateLastGpodnetSyncReport(boolean successful, long lastTime) {
- Preference sync = findPreference(PREF_GPODNET_SYNC);
- if (lastTime != 0) {
- sync.setSummary(getActivity().getString(R.string.pref_gpodnet_sync_changes_sum) + "\n" +
- getActivity().getString(R.string.pref_gpodnet_sync_sum_last_sync_line,
- getActivity().getString(successful ?
- R.string.gpodnetsync_pref_report_successful :
- R.string.gpodnetsync_pref_report_failed),
- DateUtils.getRelativeDateTimeString(getActivity(),
- lastTime,
- DateUtils.MINUTE_IN_MILLIS,
- DateUtils.WEEK_IN_MILLIS,
- DateUtils.FORMAT_SHOW_TIME)));
- } else {
- sync.setSummary(getActivity().getString(R.string.pref_gpodnet_sync_changes_sum));
- }
+ String status = String.format("%1$s (%2$s)", getString(successful
+ ? R.string.gpodnetsync_pref_report_successful : R.string.gpodnetsync_pref_report_failed),
+ DateUtils.getRelativeDateTimeString(getContext(),
+ lastTime, DateUtils.MINUTE_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, DateUtils.FORMAT_SHOW_TIME));
+ ((PreferenceActivity) getActivity()).getSupportActionBar().setSubtitle(status);
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/SyncServiceEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/SyncServiceEvent.java
new file mode 100644
index 000000000..7aa5f6bf1
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/event/SyncServiceEvent.java
@@ -0,0 +1,13 @@
+package de.danoeh.antennapod.core.event;
+
+public class SyncServiceEvent {
+ private final int messageResId;
+
+ public SyncServiceEvent(int messageResId) {
+ this.messageResId = messageResId;
+ }
+
+ public int getMessageResId() {
+ return messageResId;
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java b/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java
index 6ca3d3422..a31c19562 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java
@@ -19,6 +19,7 @@ import androidx.work.WorkManager;
import androidx.work.Worker;
import androidx.work.WorkerParameters;
import de.danoeh.antennapod.core.R;
+import de.danoeh.antennapod.core.event.SyncServiceEvent;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
@@ -39,6 +40,7 @@ import de.danoeh.antennapod.core.sync.model.UploadChangesResponse;
import de.danoeh.antennapod.core.util.URLChecker;
import de.danoeh.antennapod.core.util.gui.NotificationUtils;
import org.apache.commons.lang3.StringUtils;
+import org.greenrobot.eventbus.EventBus;
import org.json.JSONArray;
import org.json.JSONException;
@@ -55,6 +57,7 @@ public class SyncService extends Worker {
private static final String PREF_QUEUED_FEEDS_REMOVED = "sync_removed";
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_SUCCESS = "last_sync_attempt_success";
private static final String TAG = "SyncService";
private static final String WORK_ID_SYNC = "SyncServiceWorkId";
private static final Object lock = new Object();
@@ -69,20 +72,26 @@ public class SyncService extends Worker {
@NonNull
public Result doWork() {
syncServiceImpl = new GpodnetService(AntennapodHttpClient.getHttpClient(), GpodnetService.DEFAULT_BASE_HOST);
+ SharedPreferences.Editor prefs = getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
+ .edit();
+ prefs.putLong(PREF_LAST_SYNC_ATTEMPT_TIMESTAMP, System.currentTimeMillis()).apply();
try {
syncServiceImpl.login();
+ EventBus.getDefault().post(new SyncServiceEvent(R.string.sync_status_subscriptions));
syncSubscriptions();
+ EventBus.getDefault().post(new SyncServiceEvent(R.string.sync_status_episodes));
syncEpisodeActions();
syncServiceImpl.logout();
clearErrorNotifications();
+ EventBus.getDefault().post(new SyncServiceEvent(R.string.sync_status_success));
+ prefs.putBoolean(PREF_LAST_SYNC_ATTEMPT_SUCCESS, true).apply();
return Result.success();
} catch (SyncServiceException e) {
+ EventBus.getDefault().post(new SyncServiceEvent(R.string.sync_status_error));
+ prefs.putBoolean(PREF_LAST_SYNC_ATTEMPT_SUCCESS, false).apply();
e.printStackTrace();
updateErrorNotification(e);
return Result.failure();
- } finally {
- getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE).edit()
- .putLong(PREF_LAST_SYNC_ATTEMPT_TIMESTAMP, System.currentTimeMillis()).apply();
}
}
@@ -145,18 +154,9 @@ public class SyncService extends Worker {
}
public static void sync(Context context) {
- 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(5L, TimeUnit.SECONDS) // Give it some time, so other actions can be queued
- .build();
+ OneTimeWorkRequest workRequest = getWorkRequest().build();
WorkManager.getInstance().enqueueUniqueWork(WORK_ID_SYNC, ExistingWorkPolicy.REPLACE, workRequest);
+ EventBus.getDefault().post(new SyncServiceEvent(R.string.sync_status_started));
}
public static void fullSync(Context context) {
@@ -167,9 +167,35 @@ public class SyncService extends Worker {
.putLong(PREF_LAST_SYNC_ATTEMPT_TIMESTAMP, 0)
.apply();
}
- sync(context);
+ OneTimeWorkRequest workRequest = getWorkRequest()
+ .setInitialDelay(0L, TimeUnit.SECONDS)
+ .build();
+ WorkManager.getInstance().enqueueUniqueWork(WORK_ID_SYNC, ExistingWorkPolicy.REPLACE, workRequest);
+ EventBus.getDefault().post(new SyncServiceEvent(R.string.sync_status_started));
}
+ private static OneTimeWorkRequest.Builder getWorkRequest() {
+ Constraints.Builder constraints = new Constraints.Builder();
+ if (UserPreferences.isAllowMobileFeedRefresh()) {
+ constraints.setRequiredNetworkType(NetworkType.CONNECTED);
+ } else {
+ constraints.setRequiredNetworkType(NetworkType.UNMETERED);
+ }
+
+ return new OneTimeWorkRequest.Builder(SyncService.class)
+ .setConstraints(constraints.build())
+ .setInitialDelay(5L, TimeUnit.SECONDS); // Give it some time, so other actions can be queued
+ }
+
+ public static boolean isLastSyncSuccessful(Context context) {
+ return context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
+ .getBoolean(PREF_LAST_SYNC_ATTEMPT_SUCCESS, false);
+ }
+
+ public static long getLastSyncAttempt(Context context) {
+ return context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
+ .getLong(PREF_LAST_SYNC_ATTEMPT_TIMESTAMP, 0);
+ }
private List<EpisodeAction> getQueuedEpisodeActions() {
ArrayList<EpisodeAction> actions = new ArrayList<>();
@@ -281,6 +307,7 @@ public class SyncService extends Worker {
// upload local actions
List<EpisodeAction> queuedEpisodeActions = getQueuedEpisodeActions();
if (lastSync == 0) {
+ EventBus.getDefault().post(new SyncServiceEvent(R.string.sync_status_upload_played));
List<FeedItem> readItems = DBReader.getPlayedItems();
Log.d(TAG, "First sync. Upload state for all " + readItems.size() + " played episodes");
for (FeedItem item : readItems) {
@@ -300,7 +327,8 @@ public class SyncService extends Worker {
}
if (queuedEpisodeActions.size() > 0) {
synchronized (lock) {
- Log.d(TAG, "Uploading actions: " + StringUtils.join(queuedEpisodeActions, ", "));
+ Log.d(TAG, "Uploading " + queuedEpisodeActions.size() + " actions: "
+ + StringUtils.join(queuedEpisodeActions, ", "));
UploadChangesResponse postResponse = syncServiceImpl.uploadEpisodeActions(queuedEpisodeActions);
newTimeStamp = postResponse.timestamp;
Log.d(TAG, "Upload episode response: " + postResponse);
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java b/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java
index 678545321..327232e1d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java
@@ -1,5 +1,6 @@
package de.danoeh.antennapod.core.sync.gpoddernet;
+import android.util.Log;
import androidx.annotation.NonNull;
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetDevice;
@@ -42,8 +43,10 @@ import java.util.List;
* Communicates with the gpodder.net service.
*/
public class GpodnetService implements ISyncService {
+ public static final String TAG = "GpodnetService";
public static final String DEFAULT_BASE_HOST = "gpodder.net";
private static final String BASE_SCHEME = "https";
+ private static final int UPLOAD_BULK_SIZE = 30;
private static final MediaType TEXT = MediaType.parse("plain/text; charset=utf-8");
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
private final String baseHost;
@@ -415,12 +418,24 @@ public class GpodnetService implements ISyncService {
@Override
public UploadChangesResponse uploadEpisodeActions(List<EpisodeAction> episodeActions) throws SyncServiceException {
requireLoggedIn();
+ UploadChangesResponse response = null;
+ for (int i = 0; i < episodeActions.size(); i += UPLOAD_BULK_SIZE) {
+ response = uploadEpisodeActionsPartial(episodeActions,
+ i, Math.min(episodeActions.size(), i + UPLOAD_BULK_SIZE));
+ }
+ return response;
+ }
+
+ private UploadChangesResponse uploadEpisodeActionsPartial(List<EpisodeAction> episodeActions, int from, int to)
+ throws SyncServiceException {
try {
+ Log.d(TAG, "Uploading partial actions " + from + " to " + to + " of " + episodeActions.size());
URL url = new URI(BASE_SCHEME, baseHost, String.format(
"/api/2/episodes/%s.json", username), null).toURL();
final JSONArray list = new JSONArray();
- for (EpisodeAction episodeAction : episodeActions) {
+ for (int i = from; i < to; i++) {
+ EpisodeAction episodeAction = episodeActions.get(i);
JSONObject obj = episodeAction.writeToJSONObject();
if (obj != null) {
obj.put("device", GpodnetPreferences.getDeviceID());
@@ -437,7 +452,6 @@ public class GpodnetService implements ISyncService {
e.printStackTrace();
throw new SyncServiceException(e);
}
-
}
/**
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index 694ea0df2..829355f81 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -441,8 +441,6 @@
<string name="pref_gpodnet_sync_changes_sum">Sync subscription and episode state changes with gpodder.net.</string>
<string name="pref_gpodnet_full_sync_title">Full sync now</string>
<string name="pref_gpodnet_full_sync_sum">Sync all subscriptions and episode states with gpodder.net.</string>
- <string name="pref_gpodnet_sync_sum_last_sync_line">Last sync attempt: %1$s (%2$s)</string>
- <string name="pref_gpodnet_sync_started">Sync started</string>
<string name="pref_gpodnet_login_status"><![CDATA[Logged in as <i>%1$s</i> with device <i>%2$s</i>]]></string>
<string name="pref_gpodnet_notifications_title">Show sync error notifications</string>
<string name="pref_gpodnet_notifications_sum">This setting does not apply to authentication errors.</string>
@@ -536,6 +534,14 @@
<string name="search_label">Search</string>
<string name="no_results_for_query">No results were found for \"%1$s\"</string>
+ <!-- Synchronization -->
+ <string name="sync_status_started">Sync started</string>
+ <string name="sync_status_episodes">Synchronizing episodes…</string>
+ <string name="sync_status_upload_played">Uploading played status…</string>
+ <string name="sync_status_subscriptions">Synchronizing subscriptions…</string>
+ <string name="sync_status_success">Synchronization successful</string>
+ <string name="sync_status_error">Synchronization failed</string>
+
<!-- import and export -->
<string name="import_export_summary">Move subscriptions and queue to another device</string>
<string name="database">Database</string>