From e30533a810efa59bba6c101dd1405e776e1b451e Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Sat, 24 Apr 2021 16:18:02 +0200 Subject: [PATCH] Moved synchronization to its own module --- app/build.gradle | 2 + .../gpodnet/GPodnetServiceTest.java | 26 +++--- .../adapter/gpodnet/PodcastListAdapter.java | 2 +- .../adapter/gpodnet/TagListAdapter.java | 2 +- .../discovery/GpodnetPodcastSearcher.java | 9 +- .../discovery/PodcastSearchResult.java | 2 +- .../fragment/gpodnet/PodcastListFragment.java | 9 +- .../gpodnet/PodcastTopListFragment.java | 6 +- .../gpodnet/SuggestionListFragment.java | 8 +- .../fragment/gpodnet/TagFragment.java | 8 +- .../fragment/gpodnet/TagListFragment.java | 7 +- .../GpodderAuthenticationFragment.java | 11 ++- .../menuhandler/FeedItemMenuHandler.java | 2 +- core/build.gradle | 2 + .../core/preferences/GpodnetPreferences.java | 2 +- .../handler/MediaDownloadedHandler.java | 2 +- .../antennapod/core/storage/DBWriter.java | 2 +- .../antennapod/core/sync/SyncService.java | 18 ++-- net/sync/README.md | 3 + net/sync/gpoddernet/README.md | 3 + net/sync/gpoddernet/build.gradle | 57 +++++++++++++ .../gpoddernet/src/main/AndroidManifest.xml | 1 + .../net}/sync/gpoddernet/GpodnetService.java | 82 +++++++++---------- ...GpodnetServiceAuthenticationException.java | 2 +- .../GpodnetServiceBadStatusCodeException.java | 2 +- .../gpoddernet/GpodnetServiceException.java | 4 +- .../sync/gpoddernet/model/GpodnetDevice.java | 6 +- .../GpodnetEpisodeActionPostResponse.java | 4 +- .../sync/gpoddernet/model/GpodnetPodcast.java | 2 +- .../sync/gpoddernet/model/GpodnetTag.java | 2 +- .../model/GpodnetUploadChangesResponse.java | 6 +- net/sync/model/README.md | 3 + net/sync/model/build.gradle | 54 ++++++++++++ net/sync/model/src/main/AndroidManifest.xml | 1 + .../net}/sync/model/EpisodeAction.java | 17 ++-- .../net}/sync/model/EpisodeActionChanges.java | 2 +- .../net}/sync/model/ISyncService.java | 2 +- .../net}/sync/model/SubscriptionChanges.java | 2 +- .../net}/sync/model/SyncServiceException.java | 2 +- .../sync/model/UploadChangesResponse.java | 2 +- settings.gradle | 4 + 41 files changed, 262 insertions(+), 121 deletions(-) create mode 100644 net/sync/README.md create mode 100644 net/sync/gpoddernet/README.md create mode 100644 net/sync/gpoddernet/build.gradle create mode 100644 net/sync/gpoddernet/src/main/AndroidManifest.xml rename {core/src/main/java/de/danoeh/antennapod/core => net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net}/sync/gpoddernet/GpodnetService.java (93%) rename {core/src/main/java/de/danoeh/antennapod/core => net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net}/sync/gpoddernet/GpodnetServiceAuthenticationException.java (82%) rename {core/src/main/java/de/danoeh/antennapod/core => net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net}/sync/gpoddernet/GpodnetServiceBadStatusCodeException.java (86%) rename {core/src/main/java/de/danoeh/antennapod/core => net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net}/sync/gpoddernet/GpodnetServiceException.java (70%) rename {core/src/main/java/de/danoeh/antennapod/core => net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net}/sync/gpoddernet/model/GpodnetDevice.java (91%) rename {core/src/main/java/de/danoeh/antennapod/core => net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net}/sync/gpoddernet/model/GpodnetEpisodeActionPostResponse.java (93%) rename {core/src/main/java/de/danoeh/antennapod/core => net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net}/sync/gpoddernet/model/GpodnetPodcast.java (96%) rename {core/src/main/java/de/danoeh/antennapod/core => net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net}/sync/gpoddernet/model/GpodnetTag.java (96%) rename {core/src/main/java/de/danoeh/antennapod/core => net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net}/sync/gpoddernet/model/GpodnetUploadChangesResponse.java (90%) create mode 100644 net/sync/model/README.md create mode 100644 net/sync/model/build.gradle create mode 100644 net/sync/model/src/main/AndroidManifest.xml rename {core/src/main/java/de/danoeh/antennapod/core => net/sync/model/src/main/java/de/danoeh/antennapod/net}/sync/model/EpisodeAction.java (93%) rename {core/src/main/java/de/danoeh/antennapod/core => net/sync/model/src/main/java/de/danoeh/antennapod/net}/sync/model/EpisodeActionChanges.java (94%) rename {core/src/main/java/de/danoeh/antennapod/core => net/sync/model/src/main/java/de/danoeh/antennapod/net}/sync/model/ISyncService.java (93%) rename {core/src/main/java/de/danoeh/antennapod/core => net/sync/model/src/main/java/de/danoeh/antennapod/net}/sync/model/SubscriptionChanges.java (95%) rename {core/src/main/java/de/danoeh/antennapod/core => net/sync/model/src/main/java/de/danoeh/antennapod/net}/sync/model/SyncServiceException.java (85%) rename {core/src/main/java/de/danoeh/antennapod/core => net/sync/model/src/main/java/de/danoeh/antennapod/net}/sync/model/UploadChangesResponse.java (85%) diff --git a/app/build.gradle b/app/build.gradle index 6156d1536..2c622cd91 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -164,6 +164,8 @@ android { dependencies { implementation project(":core") implementation project(':model') + implementation project(':net:sync:gpoddernet') + implementation project(':net:sync:model') implementation project(':ui:app-start-intent') implementation project(':ui:common') diff --git a/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java b/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java index 9b3422a5d..f1d71b07a 100644 --- a/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java +++ b/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java @@ -6,10 +6,10 @@ import java.util.List; import androidx.test.ext.junit.runners.AndroidJUnit4; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; -import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService; -import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetServiceException; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetDevice; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetTag; +import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService; +import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetServiceException; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetDevice; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetTag; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -28,14 +28,16 @@ public class GPodnetServiceTest { private static final String USER = ""; private static final String PW = ""; + private static final String DEVICE_ID = "radio"; @Before public void setUp() { - service = new GpodnetService(AntennapodHttpClient.getHttpClient(), GpodnetService.DEFAULT_BASE_HOST); + service = new GpodnetService(AntennapodHttpClient.getHttpClient(), + GpodnetService.DEFAULT_BASE_HOST, DEVICE_ID, USER, PW); } private void authenticate() throws GpodnetServiceException { - service.authenticate(USER, PW); + service.login(); } @Test @@ -43,7 +45,7 @@ public class GPodnetServiceTest { authenticate(); ArrayList l = new ArrayList<>(); l.add("http://bitsundso.de/feed"); - service.uploadSubscriptions("radio", l); + service.uploadSubscriptions(DEVICE_ID, l); } @Test @@ -52,7 +54,7 @@ public class GPodnetServiceTest { ArrayList l = new ArrayList<>(); l.add("http://bitsundso.de/feed"); l.add("http://gamesundso.de/feed"); - service.uploadSubscriptions("radio", l); + service.uploadSubscriptions(DEVICE_ID, l); } @Test @@ -62,14 +64,14 @@ public class GPodnetServiceTest { List subscriptions = Arrays.asList(URLS[0], URLS[1]); List removed = singletonList(URLS[0]); List added = Arrays.asList(URLS[2], URLS[3]); - service.uploadSubscriptions("radio", subscriptions); - service.uploadChanges("radio", added, removed); + service.uploadSubscriptions(DEVICE_ID, subscriptions); + service.uploadSubscriptionChanges(added, removed); } @Test public void testGetSubscriptionChanges() throws GpodnetServiceException { authenticate(); - service.getSubscriptionChanges("radio", 1362322610L); + service.getSubscriptionChanges(1362322610L); } @Test @@ -83,7 +85,7 @@ public class GPodnetServiceTest { public void testGetSubscriptionsOfDevice() throws GpodnetServiceException { authenticate(); - service.getSubscriptionsOfDevice("radio"); + service.getSubscriptionsOfDevice(DEVICE_ID); } @Test diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java index 25fc0a05c..a125515cc 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java @@ -13,7 +13,7 @@ import com.bumptech.glide.Glide; import com.bumptech.glide.load.resource.bitmap.FitCenter; import com.bumptech.glide.load.resource.bitmap.RoundedCorners; import com.bumptech.glide.request.RequestOptions; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetPodcast; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetPodcast; import org.apache.commons.lang3.StringUtils; diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/TagListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/TagListAdapter.java index 698e43145..b0441688d 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/TagListAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/TagListAdapter.java @@ -8,7 +8,7 @@ import android.widget.ArrayAdapter; import android.widget.TextView; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetTag; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetTag; import java.util.List; diff --git a/app/src/main/java/de/danoeh/antennapod/discovery/GpodnetPodcastSearcher.java b/app/src/main/java/de/danoeh/antennapod/discovery/GpodnetPodcastSearcher.java index 6de2186e0..f97c1c7ab 100644 --- a/app/src/main/java/de/danoeh/antennapod/discovery/GpodnetPodcastSearcher.java +++ b/app/src/main/java/de/danoeh/antennapod/discovery/GpodnetPodcastSearcher.java @@ -2,9 +2,9 @@ package de.danoeh.antennapod.discovery; import de.danoeh.antennapod.core.preferences.GpodnetPreferences; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; -import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService; -import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetServiceException; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetPodcast; +import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService; +import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetServiceException; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetPodcast; import io.reactivex.Single; import io.reactivex.SingleOnSubscribe; import io.reactivex.android.schedulers.AndroidSchedulers; @@ -18,7 +18,8 @@ public class GpodnetPodcastSearcher implements PodcastSearcher { return Single.create((SingleOnSubscribe>) subscriber -> { try { GpodnetService service = new GpodnetService(AntennapodHttpClient.getHttpClient(), - GpodnetPreferences.getHosturl()); + GpodnetPreferences.getHosturl(), GpodnetPreferences.getDeviceID(), + GpodnetPreferences.getUsername(), GpodnetPreferences.getPassword()); List gpodnetPodcasts = service.searchPodcasts(query, 0); List results = new ArrayList<>(); for (GpodnetPodcast podcast : gpodnetPodcasts) { diff --git a/app/src/main/java/de/danoeh/antennapod/discovery/PodcastSearchResult.java b/app/src/main/java/de/danoeh/antennapod/discovery/PodcastSearchResult.java index bba438d1d..767845cb4 100644 --- a/app/src/main/java/de/danoeh/antennapod/discovery/PodcastSearchResult.java +++ b/app/src/main/java/de/danoeh/antennapod/discovery/PodcastSearchResult.java @@ -1,7 +1,7 @@ package de.danoeh.antennapod.discovery; import androidx.annotation.Nullable; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetPodcast; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetPodcast; import de.mfietz.fyydlin.SearchHit; import org.json.JSONArray; import org.json.JSONException; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java index 7ee0936d0..c813cbf7a 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java @@ -17,9 +17,9 @@ import de.danoeh.antennapod.activity.OnlineFeedViewActivity; import de.danoeh.antennapod.adapter.gpodnet.PodcastListAdapter; import de.danoeh.antennapod.core.preferences.GpodnetPreferences; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; -import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService; -import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetServiceException; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetPodcast; +import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService; +import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetServiceException; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetPodcast; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; @@ -76,7 +76,8 @@ public abstract class PodcastListFragment extends Fragment { disposable = Observable.fromCallable( () -> { GpodnetService service = new GpodnetService(AntennapodHttpClient.getHttpClient(), - GpodnetPreferences.getHosturl()); + GpodnetPreferences.getHosturl(), GpodnetPreferences.getDeviceID(), + GpodnetPreferences.getUsername(), GpodnetPreferences.getPassword()); return loadPodcastData(service); }) .subscribeOn(Schedulers.io()) diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastTopListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastTopListFragment.java index 64261493d..f51ab032f 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastTopListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastTopListFragment.java @@ -1,8 +1,8 @@ package de.danoeh.antennapod.fragment.gpodnet; -import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService; -import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetServiceException; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetPodcast; +import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService; +import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetServiceException; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetPodcast; import java.util.List; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SuggestionListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SuggestionListFragment.java index 41b99cdfc..e3cdb8959 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SuggestionListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SuggestionListFragment.java @@ -4,9 +4,9 @@ import java.util.Collections; import java.util.List; import de.danoeh.antennapod.core.preferences.GpodnetPreferences; -import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService; -import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetServiceException; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetPodcast; +import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService; +import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetServiceException; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetPodcast; /** * Displays suggestions from gpodder.net @@ -17,7 +17,7 @@ public class SuggestionListFragment extends PodcastListFragment { @Override protected List loadPodcastData(GpodnetService service) throws GpodnetServiceException { if (GpodnetPreferences.loggedIn()) { - service.authenticate(GpodnetPreferences.getUsername(), GpodnetPreferences.getPassword()); + service.login(); return service.getSuggestions(SUGGESTIONS_COUNT); } else { return Collections.emptyList(); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagFragment.java index c6c00eb34..62e2e30d1 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagFragment.java @@ -5,10 +5,10 @@ import androidx.annotation.NonNull; import java.util.List; -import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService; -import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetServiceException; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetPodcast; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetTag; +import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService; +import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetServiceException; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetPodcast; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetTag; /** * Shows all podcasts from gpodder.net that belong to a specific tag. diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java index 9d0f99aa9..f961e30bb 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java @@ -10,8 +10,8 @@ import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.adapter.gpodnet.TagListAdapter; import de.danoeh.antennapod.core.preferences.GpodnetPreferences; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; -import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetTag; +import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetTag; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; @@ -51,7 +51,8 @@ public class TagListFragment extends ListFragment { disposable = Observable.fromCallable( () -> { GpodnetService service = new GpodnetService(AntennapodHttpClient.getHttpClient(), - GpodnetPreferences.getHosturl()); + GpodnetPreferences.getHosturl(), GpodnetPreferences.getDeviceID(), + GpodnetPreferences.getUsername(), GpodnetPreferences.getPassword()); return service.getTopTags(COUNT); }) .subscribeOn(Schedulers.io()) diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderAuthenticationFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderAuthenticationFragment.java index 6eb19aff2..c0bf3e0ea 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderAuthenticationFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/GpodderAuthenticationFragment.java @@ -25,8 +25,8 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.preferences.GpodnetPreferences; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.sync.SyncService; -import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetDevice; +import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetDevice; import de.danoeh.antennapod.core.util.FileNameGenerator; import de.danoeh.antennapod.core.util.IntentUtils; import io.reactivex.Completable; @@ -96,7 +96,9 @@ public class GpodderAuthenticationFragment extends DialogFragment { } else { GpodnetPreferences.setHosturl(GpodnetService.DEFAULT_BASE_HOST); } - service = new GpodnetService(AntennapodHttpClient.getHttpClient(), GpodnetPreferences.getHosturl()); + service = new GpodnetService(AntennapodHttpClient.getHttpClient(), + GpodnetPreferences.getHosturl(), GpodnetPreferences.getDeviceID(), + GpodnetPreferences.getUsername(), GpodnetPreferences.getPassword()); getDialog().setTitle(GpodnetPreferences.getHosturl()); advance(); }); @@ -138,7 +140,8 @@ public class GpodderAuthenticationFragment extends DialogFragment { inputManager.hideSoftInputFromWindow(login.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); Completable.fromAction(() -> { - service.authenticate(usernameStr, passwordStr); + service.setCredentials(usernameStr, passwordStr); + service.login(); devices = service.getDevices(); GpodderAuthenticationFragment.this.username = usernameStr; GpodderAuthenticationFragment.this.password = passwordStr; diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java index 7cf483052..d478c581d 100644 --- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java +++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java @@ -20,7 +20,7 @@ import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.sync.SyncService; -import de.danoeh.antennapod.core.sync.model.EpisodeAction; +import de.danoeh.antennapod.net.sync.model.EpisodeAction; import de.danoeh.antennapod.core.util.FeedItemUtil; import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.ShareUtils; diff --git a/core/build.gradle b/core/build.gradle index e5ab13bcd..f9c09c7bc 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -75,6 +75,8 @@ android { dependencies { implementation project(':model') implementation project(':net:ssl') + implementation project(':net:sync:gpoddernet') + implementation project(':net:sync:model') implementation project(':ui:app-start-intent') implementation project(':ui:common') implementation project(':ui:png-icons') diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java index 209558b19..e338e0d01 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java @@ -6,7 +6,7 @@ import android.util.Log; import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.sync.SyncService; -import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService; +import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService; /** * Manages preferences for accessing gpodder.net service diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java index 2d0efd22a..8c9035621 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java @@ -19,7 +19,7 @@ import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.ChapterUtils; import de.danoeh.antennapod.core.util.DownloadError; import de.danoeh.antennapod.core.sync.SyncService; -import de.danoeh.antennapod.core.sync.model.EpisodeAction; +import de.danoeh.antennapod.net.sync.model.EpisodeAction; import org.greenrobot.eventbus.EventBus; /** diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index cf3983910..3231c3779 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -8,7 +8,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import de.danoeh.antennapod.core.sync.SyncService; -import de.danoeh.antennapod.core.sync.model.EpisodeAction; +import de.danoeh.antennapod.net.sync.model.EpisodeAction; import org.greenrobot.eventbus.EventBus; import java.io.File; 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 21b217e66..4736a2c33 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 @@ -32,17 +32,17 @@ import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.storage.DownloadRequester; -import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService; -import de.danoeh.antennapod.core.sync.model.EpisodeAction; -import de.danoeh.antennapod.core.sync.model.EpisodeActionChanges; -import de.danoeh.antennapod.core.sync.model.ISyncService; -import de.danoeh.antennapod.core.sync.model.SubscriptionChanges; -import de.danoeh.antennapod.core.sync.model.SyncServiceException; -import de.danoeh.antennapod.core.sync.model.UploadChangesResponse; import de.danoeh.antennapod.core.util.FeedItemUtil; import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.URLChecker; import de.danoeh.antennapod.core.util.gui.NotificationUtils; +import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService; +import de.danoeh.antennapod.net.sync.model.EpisodeAction; +import de.danoeh.antennapod.net.sync.model.EpisodeActionChanges; +import de.danoeh.antennapod.net.sync.model.ISyncService; +import de.danoeh.antennapod.net.sync.model.SubscriptionChanges; +import de.danoeh.antennapod.net.sync.model.SyncServiceException; +import de.danoeh.antennapod.net.sync.model.UploadChangesResponse; import io.reactivex.Completable; import io.reactivex.schedulers.Schedulers; import org.apache.commons.lang3.StringUtils; @@ -81,7 +81,9 @@ public class SyncService extends Worker { if (!GpodnetPreferences.loggedIn()) { return Result.success(); } - syncServiceImpl = new GpodnetService(AntennapodHttpClient.getHttpClient(), GpodnetPreferences.getHosturl()); + syncServiceImpl = new GpodnetService(AntennapodHttpClient.getHttpClient(), + GpodnetPreferences.getHosturl(), GpodnetPreferences.getDeviceID(), + GpodnetPreferences.getUsername(), GpodnetPreferences.getPassword()); SharedPreferences.Editor prefs = getApplicationContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) .edit(); prefs.putLong(PREF_LAST_SYNC_ATTEMPT_TIMESTAMP, System.currentTimeMillis()).apply(); diff --git a/net/sync/README.md b/net/sync/README.md new file mode 100644 index 000000000..ec3a5d3a7 --- /dev/null +++ b/net/sync/README.md @@ -0,0 +1,3 @@ +# :net:sync + +This folder contains modules related to external services for synchronization. The module `model` provides the basic interfaces for implementing a synchronization backend. The other modules contains backends for specific synchronization services. diff --git a/net/sync/gpoddernet/README.md b/net/sync/gpoddernet/README.md new file mode 100644 index 000000000..1f8bb95bd --- /dev/null +++ b/net/sync/gpoddernet/README.md @@ -0,0 +1,3 @@ +# :net:sync:gpoddernet + +This module contains the sync backend for the open-source podcast synchronization service "Gpodder.net". diff --git a/net/sync/gpoddernet/build.gradle b/net/sync/gpoddernet/build.gradle new file mode 100644 index 000000000..cd6d8d04c --- /dev/null +++ b/net/sync/gpoddernet/build.gradle @@ -0,0 +1,57 @@ +apply plugin: "com.android.library" + +android { + compileSdkVersion rootProject.ext.compileSdkVersion + + defaultConfig { + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + + multiDexEnabled false + + testApplicationId "de.danoeh.antennapod.core.tests" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile("proguard-android.txt") + } + debug { + // debug build has method count over 64k single-dex threshold. + // For building debug build to use on Android < 21 (pre-Android 5) devices, + // you need to manually change class + // de.danoeh.antennapod.PodcastApp to extend MultiDexApplication . + // See Issue #2813 + multiDexEnabled true + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + testOptions { + unitTests { + includeAndroidResources = true + } + } + + lintOptions { + disable 'GradleDependency' + checkDependencies true + warningsAsErrors true + abortOnError true + } +} + +dependencies { + implementation project(':net:sync:model') + + annotationProcessor "androidx.annotation:annotation:$annotationVersion" + implementation "androidx.appcompat:appcompat:$appcompatVersion" + + implementation "com.squareup.okhttp3:okhttp:$okhttpVersion" + implementation "org.apache.commons:commons-lang3:$commonslangVersion" +} diff --git a/net/sync/gpoddernet/src/main/AndroidManifest.xml b/net/sync/gpoddernet/src/main/AndroidManifest.xml new file mode 100644 index 000000000..df37bed3c --- /dev/null +++ b/net/sync/gpoddernet/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/GpodnetService.java similarity index 93% rename from core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java rename to net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/GpodnetService.java index cd0fc93ea..d41f613a7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetService.java +++ b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/GpodnetService.java @@ -1,20 +1,18 @@ -package de.danoeh.antennapod.core.sync.gpoddernet; +package de.danoeh.antennapod.net.sync.gpoddernet; import android.util.Log; import androidx.annotation.NonNull; -import de.danoeh.antennapod.core.BuildConfig; -import de.danoeh.antennapod.core.preferences.GpodnetPreferences; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetDevice; -import de.danoeh.antennapod.core.sync.model.EpisodeAction; -import de.danoeh.antennapod.core.sync.model.EpisodeActionChanges; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetEpisodeActionPostResponse; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetPodcast; -import de.danoeh.antennapod.core.sync.model.ISyncService; -import de.danoeh.antennapod.core.sync.model.SubscriptionChanges; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetTag; -import de.danoeh.antennapod.core.sync.gpoddernet.model.GpodnetUploadChangesResponse; -import de.danoeh.antennapod.core.sync.model.SyncServiceException; -import de.danoeh.antennapod.core.sync.model.UploadChangesResponse; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetDevice; +import de.danoeh.antennapod.net.sync.model.EpisodeAction; +import de.danoeh.antennapod.net.sync.model.EpisodeActionChanges; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetEpisodeActionPostResponse; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetPodcast; +import de.danoeh.antennapod.net.sync.model.ISyncService; +import de.danoeh.antennapod.net.sync.model.SubscriptionChanges; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetTag; +import de.danoeh.antennapod.net.sync.gpoddernet.model.GpodnetUploadChangesResponse; +import de.danoeh.antennapod.net.sync.model.SyncServiceException; +import de.danoeh.antennapod.net.sync.model.UploadChangesResponse; import okhttp3.Credentials; import okhttp3.MediaType; import okhttp3.OkHttpClient; @@ -36,7 +34,6 @@ import java.net.URISyntaxException; import java.net.URL; import java.nio.charset.Charset; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; @@ -55,17 +52,24 @@ public class GpodnetService implements ISyncService { 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 String baseScheme; - private String baseHost; private int basePort; + private final String baseHost; + private final String deviceId; + private String username; + private String password; + private boolean loggedIn = false; private final OkHttpClient httpClient; - private String username = null; // split into schema, host and port - missing parts are null private static Pattern urlsplit_regex = Pattern.compile("(?:(https?)://)?([^:]+)(?::(\\d+))?"); - public GpodnetService(OkHttpClient httpClient, String baseHosturl) { + public GpodnetService(OkHttpClient httpClient, String baseHosturl, + String deviceId, String username, String password) { this.httpClient = httpClient; + this.deviceId = deviceId; + this.username = username; + this.password = password; Matcher m = urlsplit_regex.matcher(baseHosturl); if (m.matches()) { @@ -97,7 +101,7 @@ public class GpodnetService implements ISyncService { } private void requireLoggedIn() { - if (username == null) { + if (!loggedIn) { throw new IllegalStateException("Not logged in"); } } @@ -454,7 +458,6 @@ public class GpodnetService implements ISyncService { *

* This method requires authentication. * - * @param deviceId The ID of the device whose subscriptions should be updated. * @param added Collection of feed URLs of added feeds. This Collection MUST NOT contain any duplicates * @param removed Collection of feed URLs of removed feeds. This Collection MUST NOT contain any duplicates * @return a GpodnetUploadChangesResponse. See {@link GpodnetUploadChangesResponse} @@ -462,8 +465,9 @@ public class GpodnetService implements ISyncService { * @throws GpodnetServiceException if added or removed contain duplicates or if there * is an authentication error. */ - public GpodnetUploadChangesResponse uploadChanges(@NonNull String deviceId, @NonNull Collection added, - @NonNull Collection removed) throws GpodnetServiceException { + @Override + public UploadChangesResponse uploadSubscriptionChanges(List added, List removed) + throws GpodnetServiceException { requireLoggedIn(); try { URL url = new URI(baseScheme, null, baseHost, basePort, @@ -490,14 +494,12 @@ public class GpodnetService implements ISyncService { *

* This method requires authentication. * - * @param deviceId The ID of the device whose subscription changes should be - * downloaded. * @param timestamp A timestamp that can be used to receive all changes since a * specific point in time. * @throws GpodnetServiceAuthenticationException If there is an authentication error. */ - public SubscriptionChanges getSubscriptionChanges(@NonNull String deviceId, long timestamp) - throws GpodnetServiceException { + @Override + public SubscriptionChanges getSubscriptionChanges(long timestamp) throws GpodnetServiceException { requireLoggedIn(); String params = String.format(Locale.US, "since=%d", timestamp); String path = String.format("/api/2/subscriptions/%s/%s.json", username, deviceId); @@ -552,7 +554,7 @@ public class GpodnetService implements ISyncService { EpisodeAction episodeAction = episodeActions.get(i); JSONObject obj = episodeAction.writeToJsonObject(); if (obj != null) { - obj.put("device", GpodnetPreferences.getDeviceID()); + obj.put("device", deviceId); list.put(obj); } } @@ -606,7 +608,8 @@ public class GpodnetService implements ISyncService { * * @throws IllegalArgumentException If username or password is null. */ - public void authenticate(@NonNull String username, @NonNull String password) throws GpodnetServiceException { + @Override + public void login() throws GpodnetServiceException { URL url; try { url = new URI(baseScheme, null, baseHost, basePort, @@ -623,7 +626,7 @@ public class GpodnetService implements ISyncService { Response response = httpClient.newCall(authRequest).execute(); checkStatusCode(response); response.body().close(); - this.username = username; + this.loggedIn = true; } catch (Exception e) { e.printStackTrace(); throw new GpodnetServiceException(e); @@ -803,24 +806,13 @@ public class GpodnetService implements ISyncService { return new EpisodeActionChanges(episodeActions, timestamp); } - @Override - public void login() throws GpodnetServiceException { - authenticate(GpodnetPreferences.getUsername(), GpodnetPreferences.getPassword()); - } - - @Override - public SubscriptionChanges getSubscriptionChanges(long lastSync) throws GpodnetServiceException { - return getSubscriptionChanges(GpodnetPreferences.getDeviceID(), lastSync); - } - - @Override - public UploadChangesResponse uploadSubscriptionChanges(List addedFeeds, List removedFeeds) - throws GpodnetServiceException { - return uploadChanges(GpodnetPreferences.getDeviceID(), addedFeeds, removedFeeds); - } - @Override public void logout() { } + + public void setCredentials(String username, String password) { + this.username = username; + this.password = password; + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceAuthenticationException.java b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/GpodnetServiceAuthenticationException.java similarity index 82% rename from core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceAuthenticationException.java rename to net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/GpodnetServiceAuthenticationException.java index 0aec8e97e..d0a9c2dd6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceAuthenticationException.java +++ b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/GpodnetServiceAuthenticationException.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.sync.gpoddernet; +package de.danoeh.antennapod.net.sync.gpoddernet; public class GpodnetServiceAuthenticationException extends GpodnetServiceException { private static final long serialVersionUID = 1L; diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceBadStatusCodeException.java b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/GpodnetServiceBadStatusCodeException.java similarity index 86% rename from core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceBadStatusCodeException.java rename to net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/GpodnetServiceBadStatusCodeException.java index c24b5fc0a..e403d8fff 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceBadStatusCodeException.java +++ b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/GpodnetServiceBadStatusCodeException.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.sync.gpoddernet; +package de.danoeh.antennapod.net.sync.gpoddernet; class GpodnetServiceBadStatusCodeException extends GpodnetServiceException { private static final long serialVersionUID = 1L; diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceException.java b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/GpodnetServiceException.java similarity index 70% rename from core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceException.java rename to net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/GpodnetServiceException.java index 10c4fdc11..298c59073 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/GpodnetServiceException.java +++ b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/GpodnetServiceException.java @@ -1,6 +1,6 @@ -package de.danoeh.antennapod.core.sync.gpoddernet; +package de.danoeh.antennapod.net.sync.gpoddernet; -import de.danoeh.antennapod.core.sync.model.SyncServiceException; +import de.danoeh.antennapod.net.sync.model.SyncServiceException; public class GpodnetServiceException extends SyncServiceException { private static final long serialVersionUID = 1L; diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetDevice.java b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/model/GpodnetDevice.java similarity index 91% rename from core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetDevice.java rename to net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/model/GpodnetDevice.java index 454b3301d..ed7d80ee0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetDevice.java +++ b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/model/GpodnetDevice.java @@ -1,7 +1,9 @@ -package de.danoeh.antennapod.core.sync.gpoddernet.model; +package de.danoeh.antennapod.net.sync.gpoddernet.model; import androidx.annotation.NonNull; +import java.util.Locale; + public class GpodnetDevice { private final String id; @@ -49,7 +51,7 @@ public class GpodnetDevice { @Override public String toString() { - return super.toString().toLowerCase(); + return super.toString().toLowerCase(Locale.US); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetEpisodeActionPostResponse.java b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/model/GpodnetEpisodeActionPostResponse.java similarity index 93% rename from core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetEpisodeActionPostResponse.java rename to net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/model/GpodnetEpisodeActionPostResponse.java index ae9ab9d70..6d573ebfc 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetEpisodeActionPostResponse.java +++ b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/model/GpodnetEpisodeActionPostResponse.java @@ -1,8 +1,8 @@ -package de.danoeh.antennapod.core.sync.gpoddernet.model; +package de.danoeh.antennapod.net.sync.gpoddernet.model; import androidx.collection.ArrayMap; -import de.danoeh.antennapod.core.sync.model.UploadChangesResponse; +import de.danoeh.antennapod.net.sync.model.UploadChangesResponse; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.json.JSONArray; diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetPodcast.java b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/model/GpodnetPodcast.java similarity index 96% rename from core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetPodcast.java rename to net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/model/GpodnetPodcast.java index bc4969758..f09ab1244 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetPodcast.java +++ b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/model/GpodnetPodcast.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.sync.gpoddernet.model; +package de.danoeh.antennapod.net.sync.gpoddernet.model; import androidx.annotation.NonNull; diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetTag.java b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/model/GpodnetTag.java similarity index 96% rename from core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetTag.java rename to net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/model/GpodnetTag.java index 93abf4688..d3d683598 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetTag.java +++ b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/model/GpodnetTag.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.sync.gpoddernet.model; +package de.danoeh.antennapod.net.sync.gpoddernet.model; import android.os.Parcel; import android.os.Parcelable; diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetUploadChangesResponse.java b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/model/GpodnetUploadChangesResponse.java similarity index 90% rename from core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetUploadChangesResponse.java rename to net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/model/GpodnetUploadChangesResponse.java index 790ba547f..7b09531a5 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/gpoddernet/model/GpodnetUploadChangesResponse.java +++ b/net/sync/gpoddernet/src/main/java/de/danoeh/antennapod/net/sync/gpoddernet/model/GpodnetUploadChangesResponse.java @@ -1,9 +1,9 @@ -package de.danoeh.antennapod.core.sync.gpoddernet.model; +package de.danoeh.antennapod.net.sync.gpoddernet.model; import androidx.collection.ArrayMap; -import de.danoeh.antennapod.core.sync.gpoddernet.GpodnetService; -import de.danoeh.antennapod.core.sync.model.UploadChangesResponse; +import de.danoeh.antennapod.net.sync.gpoddernet.GpodnetService; +import de.danoeh.antennapod.net.sync.model.UploadChangesResponse; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; diff --git a/net/sync/model/README.md b/net/sync/model/README.md new file mode 100644 index 000000000..21d842914 --- /dev/null +++ b/net/sync/model/README.md @@ -0,0 +1,3 @@ +# :net:sync:model + +This module contains the basic interfaces for implementing a sync backend. diff --git a/net/sync/model/build.gradle b/net/sync/model/build.gradle new file mode 100644 index 000000000..299359602 --- /dev/null +++ b/net/sync/model/build.gradle @@ -0,0 +1,54 @@ +apply plugin: "com.android.library" + +android { + compileSdkVersion rootProject.ext.compileSdkVersion + + defaultConfig { + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + + multiDexEnabled false + + testApplicationId "de.danoeh.antennapod.core.tests" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile("proguard-android.txt") + } + debug { + // debug build has method count over 64k single-dex threshold. + // For building debug build to use on Android < 21 (pre-Android 5) devices, + // you need to manually change class + // de.danoeh.antennapod.PodcastApp to extend MultiDexApplication . + // See Issue #2813 + multiDexEnabled true + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + testOptions { + unitTests { + includeAndroidResources = true + } + } + + lintOptions { + disable 'GradleDependency' + checkDependencies true + warningsAsErrors true + abortOnError true + } +} + +dependencies { + implementation project(':model') + + annotationProcessor "androidx.annotation:annotation:$annotationVersion" + implementation "androidx.appcompat:appcompat:$appcompatVersion" +} diff --git a/net/sync/model/src/main/AndroidManifest.xml b/net/sync/model/src/main/AndroidManifest.xml new file mode 100644 index 000000000..a7bd1e34b --- /dev/null +++ b/net/sync/model/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeAction.java b/net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/EpisodeAction.java similarity index 93% rename from core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeAction.java rename to net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/EpisodeAction.java index 7a97b7755..1aae5c811 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeAction.java +++ b/net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/EpisodeAction.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.sync.model; +package de.danoeh.antennapod.net.sync.model; import android.text.TextUtils; import android.util.Log; @@ -6,10 +6,10 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.core.util.ObjectsCompat; import de.danoeh.antennapod.model.feed.FeedItem; -import de.danoeh.antennapod.core.util.DateUtils; import org.json.JSONException; import org.json.JSONObject; +import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; @@ -17,6 +17,7 @@ import java.util.TimeZone; public class EpisodeAction { private static final String TAG = "EpisodeAction"; + private static final String PATTERN_ISO_DATEFORMAT = "yyyy-MM-dd'T'HH:mm:ss"; public static final Action NEW = Action.NEW; public static final Action DOWNLOAD = Action.DOWNLOAD; public static final Action PLAY = Action.PLAY; @@ -56,14 +57,20 @@ public class EpisodeAction { } EpisodeAction.Action action; try { - action = EpisodeAction.Action.valueOf(actionString.toUpperCase()); + action = EpisodeAction.Action.valueOf(actionString.toUpperCase(Locale.US)); } catch (IllegalArgumentException e) { return null; } EpisodeAction.Builder builder = new EpisodeAction.Builder(podcast, episode, action); String utcTimestamp = object.optString("timestamp", null); if (!TextUtils.isEmpty(utcTimestamp)) { - builder.timestamp(DateUtils.parse(utcTimestamp)); + try { + SimpleDateFormat parser = new SimpleDateFormat(PATTERN_ISO_DATEFORMAT, Locale.US); + parser.setTimeZone(TimeZone.getTimeZone("UTC")); + builder.timestamp(parser.parse(utcTimestamp)); + } catch (ParseException e) { + e.printStackTrace(); + } } if (action == EpisodeAction.Action.PLAY) { int started = object.optInt("started", -1); @@ -92,7 +99,7 @@ public class EpisodeAction { } private String getActionString() { - return this.action.name().toLowerCase(); + return this.action.name().toLowerCase(Locale.US); } public Date getTimestamp() { diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeActionChanges.java b/net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/EpisodeActionChanges.java similarity index 94% rename from core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeActionChanges.java rename to net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/EpisodeActionChanges.java index 90af585af..570e012c5 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/model/EpisodeActionChanges.java +++ b/net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/EpisodeActionChanges.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.sync.model; +package de.danoeh.antennapod.net.sync.model; import androidx.annotation.NonNull; diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/model/ISyncService.java b/net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/ISyncService.java similarity index 93% rename from core/src/main/java/de/danoeh/antennapod/core/sync/model/ISyncService.java rename to net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/ISyncService.java index 473072b97..9c75e5dac 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/model/ISyncService.java +++ b/net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/ISyncService.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.sync.model; +package de.danoeh.antennapod.net.sync.model; import java.util.List; diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/model/SubscriptionChanges.java b/net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/SubscriptionChanges.java similarity index 95% rename from core/src/main/java/de/danoeh/antennapod/core/sync/model/SubscriptionChanges.java rename to net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/SubscriptionChanges.java index 51f2ed10d..2fbc8b45e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/model/SubscriptionChanges.java +++ b/net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/SubscriptionChanges.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.sync.model; +package de.danoeh.antennapod.net.sync.model; import androidx.annotation.NonNull; diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/model/SyncServiceException.java b/net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/SyncServiceException.java similarity index 85% rename from core/src/main/java/de/danoeh/antennapod/core/sync/model/SyncServiceException.java rename to net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/SyncServiceException.java index d7e999b45..57262db17 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/model/SyncServiceException.java +++ b/net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/SyncServiceException.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.sync.model; +package de.danoeh.antennapod.net.sync.model; public class SyncServiceException extends Exception { private static final long serialVersionUID = 1L; diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/model/UploadChangesResponse.java b/net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/UploadChangesResponse.java similarity index 85% rename from core/src/main/java/de/danoeh/antennapod/core/sync/model/UploadChangesResponse.java rename to net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/UploadChangesResponse.java index 44850bb03..7503f429b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/sync/model/UploadChangesResponse.java +++ b/net/sync/model/src/main/java/de/danoeh/antennapod/net/sync/model/UploadChangesResponse.java @@ -1,4 +1,4 @@ -package de.danoeh.antennapod.core.sync.model; +package de.danoeh.antennapod.net.sync.model; public abstract class UploadChangesResponse { diff --git a/settings.gradle b/settings.gradle index 1b3ecc497..27cc1a863 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,7 +1,11 @@ include ':app' include ':core' include ':model' + include ':net:ssl' +include ':net:sync:gpoddernet' +include ':net:sync:model' + include ':ui:app-start-intent' include ':ui:common' include ':ui:png-icons'