diff options
24 files changed, 163 insertions, 91 deletions
diff --git a/app/src/androidTest/java/de/test/antennapod/service/download/DownloadServiceTest.java b/app/src/androidTest/java/de/test/antennapod/service/download/DownloadServiceTest.java index 8aae95e69..4e255baeb 100644 --- a/app/src/androidTest/java/de/test/antennapod/service/download/DownloadServiceTest.java +++ b/app/src/androidTest/java/de/test/antennapod/service/download/DownloadServiceTest.java @@ -9,6 +9,7 @@ import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.ext.junit.runners.AndroidJUnit4; import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; import de.test.antennapod.EspressoTestUtils; import org.awaitility.Awaitility; import org.awaitility.core.ConditionTimeoutException; @@ -80,7 +81,7 @@ public class DownloadServiceTest { public void tearDown() throws Exception { DownloadService.setDownloaderFactory(origFactory); Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); - DownloadService.cancelAll(context); + DownloadServiceInterface.get().cancelAll(context); context.stopService(new Intent(context, DownloadService.class)); EspressoTestUtils.tryKillDownloadService(); } @@ -113,7 +114,8 @@ public class DownloadServiceTest { assertFalse("The media in test should not yet been downloaded", DBReader.getFeedMedia(testMedia11.getId()).isDownloaded()); - DownloadService.download(InstrumentationRegistry.getInstrumentation().getTargetContext(), false, + DownloadServiceInterface.get() + .download(InstrumentationRegistry.getInstrumentation().getTargetContext(), false, DownloadRequestCreator.create(testMedia11).build()); Awaitility.await() .atMost(5000, TimeUnit.MILLISECONDS) @@ -158,7 +160,8 @@ public class DownloadServiceTest { } withFeedItemEventListener(feedItemEventListener -> { - DownloadService.download(InstrumentationRegistry.getInstrumentation().getTargetContext(), false, + DownloadServiceInterface.get() + .download(InstrumentationRegistry.getInstrumentation().getTargetContext(), false, DownloadRequestCreator.create(testMedia11).build()); withDownloadEventListener(downloadEventListener -> Awaitility.await("download is actually running") @@ -175,7 +178,7 @@ public class DownloadServiceTest { .atMost(2000, TimeUnit.MILLISECONDS) .until(() -> feedItemEventListener.getEvents().size() >= 1); } - DownloadService.cancel(context, testMedia11.getDownload_url()); + DownloadServiceInterface.get().cancel(context, testMedia11.getDownload_url()); final int totalNumEventsExpected = itemAlreadyInQueue ? 1 : 3; Awaitility.await("item dequeue event + download termination event") .atMost(2000, TimeUnit.MILLISECONDS) diff --git a/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java index fb4c7c2d2..81756d6c8 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java @@ -4,7 +4,7 @@ import android.os.Bundle; import android.text.TextUtils; import androidx.appcompat.app.AppCompatActivity; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.service.download.DownloadService; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.model.feed.FeedPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; @@ -62,7 +62,8 @@ public class DownloadAuthenticationActivity extends AppCompatActivity { .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(() -> { - DownloadService.download(DownloadAuthenticationActivity.this, false, request); + DownloadServiceInterface.get() + .download(DownloadAuthenticationActivity.this, false, request); finish(); }); } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java index 008e28ae2..46d39f005 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java @@ -35,6 +35,7 @@ import de.danoeh.antennapod.core.event.DownloadEvent; import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; import de.danoeh.antennapod.core.feed.FeedUrlNotFoundException; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; import de.danoeh.antennapod.core.service.playback.PlaybackServiceInterface; import de.danoeh.antennapod.core.util.DownloadErrorLabel; import de.danoeh.antennapod.event.FeedListUpdateEvent; @@ -455,7 +456,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity { openFeed(); } else { Feed f = new Feed(selectedDownloadUrl, null, feed.getTitle()); - DownloadService.download(this, false, DownloadRequestCreator.create(f) + DownloadServiceInterface.get().download(this, false, DownloadRequestCreator.create(f) .withAuthentication(username, password) .build()); didPressSubscribe = true; diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportActivity.java index f92d422d0..62c4be051 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportActivity.java @@ -28,8 +28,8 @@ import de.danoeh.antennapod.core.export.opml.OpmlElement; import de.danoeh.antennapod.core.export.opml.OpmlReader; import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; import de.danoeh.antennapod.databinding.OpmlSelectionBinding; import de.danoeh.antennapod.model.feed.Feed; import io.reactivex.Completable; @@ -96,7 +96,7 @@ public class OpmlImportActivity extends AppCompatActivity { } OpmlElement element = readElements.get(checked.keyAt(i)); Feed feed = new Feed(element.getXmlUrl(), null, element.getText()); - DownloadService.download(this, false, DownloadRequestCreator.create(feed).build()); + DownloadServiceInterface.get().download(this, false, DownloadRequestCreator.create(feed).build()); } }) .subscribeOn(Schedulers.io()) diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java index 914546ab2..4c46b6428 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java @@ -13,7 +13,7 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.core.service.download.DownloadRequest; import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; -import de.danoeh.antennapod.core.service.download.DownloadService; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; import de.danoeh.antennapod.core.service.download.Downloader; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBTasks; @@ -139,7 +139,8 @@ public class DownloadLogAdapter extends BaseAdapter { Log.e(TAG, "Could not find feed media for feed id: " + status.getFeedfileId()); return; } - DownloadService.download(context, true, DownloadRequestCreator.create(media).build()); + DownloadServiceInterface.get() + .download(context, true, DownloadRequestCreator.create(media).build()); ((MainActivity) context).showSnackbarAbovePlayer( R.string.status_downloading_label, Toast.LENGTH_SHORT); }); @@ -156,7 +157,7 @@ public class DownloadLogAdapter extends BaseAdapter { holder.secondaryActionButton.setVisibility(View.VISIBLE); holder.secondaryActionButton.setTag(downloader); holder.secondaryActionButton.setOnClickListener(v -> { - DownloadService.cancel(context, request.getSource()); + DownloadServiceInterface.get().cancel(context, request.getSource()); if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { FeedMedia media = DBReader.getFeedMedia(request.getFeedfileId()); FeedItem feedItem = media.getItem(); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/CancelDownloadActionButton.java b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/CancelDownloadActionButton.java index 636c974d9..18127d289 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/CancelDownloadActionButton.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/CancelDownloadActionButton.java @@ -5,7 +5,7 @@ import androidx.annotation.DrawableRes; import androidx.annotation.StringRes; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.service.download.DownloadService; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UserPreferences; @@ -32,7 +32,7 @@ public class CancelDownloadActionButton extends ItemActionButton { @Override public void onClick(Context context) { FeedMedia media = item.getMedia(); - DownloadService.cancel(context, media.getDownload_url()); + DownloadServiceInterface.get().cancel(context, media.getDownload_url()); if (UserPreferences.isEnableAutodownload()) { item.disableAutoDownload(); DBWriter.setFeedItem(item); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/DownloadActionButton.java b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/DownloadActionButton.java index 553512882..60f55507d 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/DownloadActionButton.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/DownloadActionButton.java @@ -11,6 +11,7 @@ import androidx.annotation.StringRes; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; import de.danoeh.antennapod.core.service.download.DownloadService; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UsageStatistics; @@ -50,7 +51,8 @@ public class DownloadActionButton extends ItemActionButton { UsageStatistics.logAction(UsageStatistics.ACTION_DOWNLOAD); if (NetworkUtils.isEpisodeDownloadAllowed() || MobileDownloadHelper.userAllowedMobileDownloads()) { - DownloadService.download(context, false, DownloadRequestCreator.create(item.getMedia()).build()); + DownloadServiceInterface.get() + .download(context, false, DownloadRequestCreator.create(item.getMedia()).build()); } else if (MobileDownloadHelper.userChoseAddToQueue() && !item.isTagged(FeedItem.TAG_QUEUE)) { DBWriter.addQueueItem(context, item); Toast.makeText(context, R.string.added_to_queue_label, Toast.LENGTH_SHORT).show(); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/MobileDownloadHelper.java b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/MobileDownloadHelper.java index 4c68a559d..dfabcd0d9 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/MobileDownloadHelper.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/actionbutton/MobileDownloadHelper.java @@ -5,7 +5,7 @@ import android.content.Context; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; -import de.danoeh.antennapod.core.service.download.DownloadService; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; @@ -44,6 +44,6 @@ class MobileDownloadHelper { private static void downloadFeedItems(Context context, FeedItem item) { allowMobileDownloadTimestamp = System.currentTimeMillis(); - DownloadService.download(context, true, DownloadRequestCreator.create(item.getMedia()).build()); + DownloadServiceInterface.get().download(context, true, DownloadRequestCreator.create(item.getMedia()).build()); } }
\ No newline at end of file diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/actions/EpisodeMultiSelectActionHandler.java b/app/src/main/java/de/danoeh/antennapod/fragment/actions/EpisodeMultiSelectActionHandler.java index 0e7c019f1..1103a35d5 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/actions/EpisodeMultiSelectActionHandler.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/actions/EpisodeMultiSelectActionHandler.java @@ -13,7 +13,7 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.core.service.download.DownloadRequest; import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; -import de.danoeh.antennapod.core.service.download.DownloadService; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.model.feed.FeedItem; @@ -99,7 +99,7 @@ public class EpisodeMultiSelectActionHandler { requests.add(DownloadRequestCreator.create(episode.getMedia()).build()); } } - DownloadService.download(activity, true, requests.toArray(new DownloadRequest[0])); + DownloadServiceInterface.get().download(activity, true, requests.toArray(new DownloadRequest[0])); showMessage(R.plurals.downloading_batch_label, requests.size()); } diff --git a/app/src/main/java/de/danoeh/antennapod/receiver/PowerConnectionReceiver.java b/app/src/main/java/de/danoeh/antennapod/receiver/PowerConnectionReceiver.java index db392523e..ed873b300 100644 --- a/app/src/main/java/de/danoeh/antennapod/receiver/PowerConnectionReceiver.java +++ b/app/src/main/java/de/danoeh/antennapod/receiver/PowerConnectionReceiver.java @@ -7,7 +7,7 @@ import android.util.Log; import de.danoeh.antennapod.core.ClientConfigurator; import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.service.download.DownloadService; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; import de.danoeh.antennapod.core.storage.DBTasks; // modified from http://developer.android.com/training/monitoring-device-state/battery-monitoring.html @@ -37,7 +37,7 @@ public class PowerConnectionReceiver extends BroadcastReceiver { // if we're not supposed to be auto-downloading when we're not charging, stop it if (!UserPreferences.isEnableAutodownloadOnBattery()) { Log.d(TAG, "not charging anymore, canceling auto-download"); - DownloadService.cancelAll(context); + DownloadServiceInterface.get().cancelAll(context); } else { Log.d(TAG, "not charging anymore, but the user allows auto-download " + "when on battery so we'll keep going"); diff --git a/app/src/main/java/de/danoeh/antennapod/receiver/SPAReceiver.java b/app/src/main/java/de/danoeh/antennapod/receiver/SPAReceiver.java index 38dfc7061..0ed60b23e 100644 --- a/app/src/main/java/de/danoeh/antennapod/receiver/SPAReceiver.java +++ b/app/src/main/java/de/danoeh/antennapod/receiver/SPAReceiver.java @@ -11,8 +11,8 @@ import java.util.Arrays; import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.ClientConfigurator; -import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; import de.danoeh.antennapod.model.feed.Feed; /** @@ -44,7 +44,7 @@ public class SPAReceiver extends BroadcastReceiver{ ClientConfigurator.initialize(context); for (String url : feedUrls) { Feed f = new Feed(url, null); - DownloadService.download(context, false, DownloadRequestCreator.create(f).build()); + DownloadServiceInterface.get().download(context, false, DownloadRequestCreator.create(f).build()); } Toast.makeText(context, R.string.sp_apps_importing_feeds_msg, Toast.LENGTH_LONG).show(); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/ClientConfigurator.java b/core/src/main/java/de/danoeh/antennapod/core/ClientConfigurator.java index cdd516f16..b70a3a61a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/ClientConfigurator.java +++ b/core/src/main/java/de/danoeh/antennapod/core/ClientConfigurator.java @@ -6,6 +6,8 @@ import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; import de.danoeh.antennapod.core.preferences.UsageStatistics; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterfaceImpl; import de.danoeh.antennapod.core.sync.SyncService; import de.danoeh.antennapod.core.sync.queue.SynchronizationQueueSink; import de.danoeh.antennapod.core.util.NetworkUtils; @@ -30,6 +32,7 @@ public class ClientConfigurator { SslProviderInstaller.install(context); NetworkUtils.init(context); NetworkConnectionChangeHandler.init(context); + DownloadServiceInterface.setImpl(new DownloadServiceInterfaceImpl()); SynchronizationQueueSink.setServiceStarterImpl(() -> SyncService.sync(context)); AntennapodHttpClient.setCacheDirectory(new File(context.getCacheDir(), "okhttp")); AntennapodHttpClient.setProxyConfig(UserPreferences.getProxyConfig()); diff --git a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java index 37849c296..d026e1a7b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java +++ b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java @@ -9,8 +9,8 @@ import android.os.ParcelFileDescriptor; import android.util.Log; import de.danoeh.antennapod.core.service.download.DownloadRequest; -import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; import org.apache.commons.io.IOUtils; import org.xmlpull.v1.XmlPullParserException; @@ -145,7 +145,7 @@ public class OpmlBackupAgent extends BackupAgentHelper { for (OpmlElement opmlElem : opmlElements) { Feed feed = new Feed(opmlElem.getXmlUrl(), null, opmlElem.getText()); DownloadRequest request = DownloadRequestCreator.create(feed).build(); - DownloadService.download(mContext, false, request); + DownloadServiceInterface.get().download(mContext, false, request); } } catch (XmlPullParserException e) { Log.e(TAG, "Error while parsing the OPML file", e); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 8c26a6d74..12bbf83d0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -17,8 +17,6 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.core.app.ServiceCompat; -import androidx.core.content.ContextCompat; -import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.feed.LocalFeedUpdater; import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithmFactory; @@ -141,58 +139,6 @@ public class DownloadService extends Service { } } - public static void download(Context context, boolean cleanupMedia, DownloadRequest... requests) { - ArrayList<DownloadRequest> requestsToSend = new ArrayList<>(); - for (DownloadRequest request : requests) { - if (!isDownloadingFile(request.getSource())) { - requestsToSend.add(request); - } - } - if (requestsToSend.isEmpty()) { - return; - } else if (requestsToSend.size() > 100) { - if (BuildConfig.DEBUG) { - throw new IllegalArgumentException("Android silently drops intent payloads that are too large"); - } else { - Log.d(TAG, "Too many download requests. Dropping some to avoid Android dropping all."); - requestsToSend = new ArrayList<>(requestsToSend.subList(0, 100)); - } - } - - Intent launchIntent = new Intent(context, DownloadService.class); - launchIntent.putParcelableArrayListExtra(DownloadService.EXTRA_REQUESTS, requestsToSend); - if (cleanupMedia) { - launchIntent.putExtra(DownloadService.EXTRA_CLEANUP_MEDIA, true); - } - ContextCompat.startForegroundService(context, launchIntent); - } - - public static void refreshAllFeeds(Context context, boolean initiatedByUser) { - Intent launchIntent = new Intent(context, DownloadService.class); - launchIntent.putExtra(DownloadService.EXTRA_REFRESH_ALL, true); - launchIntent.putExtra(DownloadService.EXTRA_INITIATED_BY_USER, initiatedByUser); - ContextCompat.startForegroundService(context, launchIntent); - } - - public static void cancel(Context context, String url) { - if (!isRunning) { - return; - } - Intent cancelIntent = new Intent(DownloadService.ACTION_CANCEL_DOWNLOAD); - cancelIntent.putExtra(DownloadService.EXTRA_DOWNLOAD_URL, url); - cancelIntent.setPackage(context.getPackageName()); - context.sendBroadcast(cancelIntent); - } - - public static void cancelAll(Context context) { - if (!isRunning) { - return; - } - Intent cancelIntent = new Intent(DownloadService.ACTION_CANCEL_ALL_DOWNLOADS); - cancelIntent.setPackage(context.getPackageName()); - context.sendBroadcast(cancelIntent); - } - public static boolean isDownloadingFeeds() { if (!isRunning) { return false; @@ -373,7 +319,7 @@ public class DownloadService extends Service { Log.d(TAG, "Requested invalid range, restarting download from the beginning"); FileUtils.deleteQuietly(new File(downloader.getDownloadRequest().getDestination())); - download(this, false, downloader.getDownloadRequest()); + DownloadServiceInterface.get().download(this, false, downloader.getDownloadRequest()); } else { Log.e(TAG, "Download failed"); saveDownloadStatus(status); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceInterface.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceInterface.java new file mode 100644 index 000000000..aa4b16490 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceInterface.java @@ -0,0 +1,23 @@ +package de.danoeh.antennapod.core.service.download; + +import android.content.Context; + +public abstract class DownloadServiceInterface { + private static DownloadServiceInterface impl; + + public static DownloadServiceInterface get() { + return impl; + } + + public static void setImpl(DownloadServiceInterface impl) { + DownloadServiceInterface.impl = impl; + } + + public abstract void download(Context context, boolean cleanupMedia, DownloadRequest... requests); + + public abstract void refreshAllFeeds(Context context, boolean initiatedByUser); + + public abstract void cancel(Context context, String url); + + public abstract void cancelAll(Context context); +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceInterfaceImpl.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceInterfaceImpl.java new file mode 100644 index 000000000..f8d34174e --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadServiceInterfaceImpl.java @@ -0,0 +1,67 @@ +package de.danoeh.antennapod.core.service.download; + +import android.content.Context; +import android.content.Intent; +import androidx.core.content.ContextCompat; +import com.google.android.exoplayer2.util.Log; +import de.danoeh.antennapod.core.BuildConfig; + +import java.util.ArrayList; + +import static de.danoeh.antennapod.core.service.download.DownloadService.isDownloadingFile; + +public class DownloadServiceInterfaceImpl extends DownloadServiceInterface { + private static final String TAG = "DownloadServiceInterface"; + + public void download(Context context, boolean cleanupMedia, DownloadRequest... requests) { + ArrayList<DownloadRequest> requestsToSend = new ArrayList<>(); + for (DownloadRequest request : requests) { + if (!isDownloadingFile(request.getSource())) { + requestsToSend.add(request); + } + } + if (requestsToSend.isEmpty()) { + return; + } else if (requestsToSend.size() > 100) { + if (BuildConfig.DEBUG) { + throw new IllegalArgumentException("Android silently drops intent payloads that are too large"); + } else { + Log.d(TAG, "Too many download requests. Dropping some to avoid Android dropping all."); + requestsToSend = new ArrayList<>(requestsToSend.subList(0, 100)); + } + } + + Intent launchIntent = new Intent(context, DownloadService.class); + launchIntent.putParcelableArrayListExtra(DownloadService.EXTRA_REQUESTS, requestsToSend); + if (cleanupMedia) { + launchIntent.putExtra(DownloadService.EXTRA_CLEANUP_MEDIA, true); + } + ContextCompat.startForegroundService(context, launchIntent); + } + + public void refreshAllFeeds(Context context, boolean initiatedByUser) { + Intent launchIntent = new Intent(context, DownloadService.class); + launchIntent.putExtra(DownloadService.EXTRA_REFRESH_ALL, true); + launchIntent.putExtra(DownloadService.EXTRA_INITIATED_BY_USER, initiatedByUser); + ContextCompat.startForegroundService(context, launchIntent); + } + + public void cancel(Context context, String url) { + if (!DownloadService.isRunning) { + return; + } + Intent cancelIntent = new Intent(DownloadService.ACTION_CANCEL_DOWNLOAD); + cancelIntent.putExtra(DownloadService.EXTRA_DOWNLOAD_URL, url); + cancelIntent.setPackage(context.getPackageName()); + context.sendBroadcast(cancelIntent); + } + + public void cancelAll(Context context) { + if (!DownloadService.isRunning) { + return; + } + Intent cancelIntent = new Intent(DownloadService.ACTION_CANCEL_ALL_DOWNLOADS); + cancelIntent.setPackage(context.getPackageName()); + context.sendBroadcast(cancelIntent); + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/AutomaticDownloadAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/AutomaticDownloadAlgorithm.java index 5e1e1127a..4d8a0c25e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/AutomaticDownloadAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/AutomaticDownloadAlgorithm.java @@ -9,7 +9,7 @@ import java.util.List; import de.danoeh.antennapod.core.service.download.DownloadRequest; import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; -import de.danoeh.antennapod.core.service.download.DownloadService; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; import de.danoeh.antennapod.core.util.PlaybackStatus; import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedPreferences; @@ -100,7 +100,7 @@ public class AutomaticDownloadAlgorithm { request.withInitiatedByUser(false); requests.add(request.build()); } - DownloadService.download(context, false, requests.toArray(new DownloadRequest[0])); + DownloadServiceInterface.get().download(context, false, requests.toArray(new DownloadRequest[0])); } } }; diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index 3cc607433..13a18b0d7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -12,7 +12,7 @@ import androidx.annotation.VisibleForTesting; import de.danoeh.antennapod.core.service.download.DownloadRequest; import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; -import de.danoeh.antennapod.core.service.download.DownloadService; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; import de.danoeh.antennapod.storage.database.PodDBAdapter; import de.danoeh.antennapod.storage.database.mapper.FeedCursorMapper; import org.greenrobot.eventbus.EventBus; @@ -113,7 +113,7 @@ public final class DBTasks { * @param initiatedByUser a boolean indicating if the refresh was triggered by user action. */ public static void refreshAllFeeds(final Context context, boolean initiatedByUser) { - DownloadService.refreshAllFeeds(context, initiatedByUser); + DownloadServiceInterface.get().refreshAllFeeds(context, initiatedByUser); SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, MODE_PRIVATE); prefs.edit().putLong(PREF_LAST_REFRESH, System.currentTimeMillis()).apply(); @@ -145,7 +145,7 @@ public final class DBTasks { DownloadRequest.Builder builder = DownloadRequestCreator.create(nextFeed); builder.loadAllPages(loadAllPages); - DownloadService.download(context, false, builder.build()); + DownloadServiceInterface.get().download(context, false, builder.build()); } else { Log.e(TAG, "loadNextPageOfFeed: Feed was either not paged or contained no nextPageLink"); } @@ -164,7 +164,7 @@ public final class DBTasks { builder.withInitiatedByUser(initiatedByUser); builder.setForce(true); builder.loadAllPages(loadAllPages); - DownloadService.download(context, false, builder.build()); + DownloadServiceInterface.get().download(context, false, builder.build()); } /** 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 083916ff9..fbcb86586 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 androidx.core.app.NotificationManagerCompat; -import de.danoeh.antennapod.core.service.download.DownloadService; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; import de.danoeh.antennapod.core.service.playback.PlaybackServiceInterface; import de.danoeh.antennapod.storage.database.PodDBAdapter; import org.greenrobot.eventbus.EventBus; @@ -206,7 +206,7 @@ public class DBWriter { if (item.getMedia().isDownloaded()) { deleteFeedMediaSynchronous(context, item.getMedia()); } - DownloadService.cancel(context, item.getMedia().getDownload_url()); + DownloadServiceInterface.get().cancel(context, item.getMedia().getDownload_url()); } } 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 0640f7577..c304d67d2 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 @@ -23,6 +23,7 @@ import androidx.work.WorkerParameters; import de.danoeh.antennapod.core.service.download.DownloadRequest; import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.service.download.DownloadRequestCreator; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; import org.apache.commons.lang3.StringUtils; import org.greenrobot.eventbus.EventBus; @@ -152,7 +153,7 @@ public class SyncService extends Worker { if (!URLChecker.containsUrl(localSubscriptions, downloadUrl) && !queuedRemovedFeeds.contains(downloadUrl)) { Feed feed = new Feed(downloadUrl, null); DownloadRequest.Builder builder = DownloadRequestCreator.create(feed); - DownloadService.download(getApplicationContext(), false, builder.build()); + DownloadServiceInterface.get().download(getApplicationContext(), false, builder.build()); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/download/NetworkConnectionChangeHandler.java b/core/src/main/java/de/danoeh/antennapod/core/util/download/NetworkConnectionChangeHandler.java index 38acf7c7c..0eca498c9 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/download/NetworkConnectionChangeHandler.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/download/NetworkConnectionChangeHandler.java @@ -2,7 +2,7 @@ package de.danoeh.antennapod.core.util.download; import android.content.Context; import com.google.android.exoplayer2.util.Log; -import de.danoeh.antennapod.core.service.download.DownloadService; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.util.NetworkUtils; @@ -22,7 +22,7 @@ public abstract class NetworkConnectionChangeHandler { // otherwise cancel all downloads if (NetworkUtils.isNetworkRestricted()) { Log.i(TAG, "Device is no longer connected to Wi-Fi. Cancelling ongoing downloads"); - DownloadService.cancelAll(context); + DownloadServiceInterface.get().cancelAll(context); } } } diff --git a/core/src/test/java/de/danoeh/antennapod/core/feed/LocalFeedUpdaterTest.java b/core/src/test/java/de/danoeh/antennapod/core/feed/LocalFeedUpdaterTest.java index 4cf746ba4..095bed687 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/feed/LocalFeedUpdaterTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/feed/LocalFeedUpdaterTest.java @@ -10,6 +10,8 @@ import androidx.annotation.NonNull; import androidx.test.platform.app.InstrumentationRegistry; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterfaceStub; import de.danoeh.antennapod.core.util.FastDocumentFile; import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.model.feed.FeedItem; @@ -75,6 +77,7 @@ public class LocalFeedUpdaterTest { Application app = (Application) context; ClientConfig.applicationCallbacks = mock(ApplicationCallbacks.class); when(ClientConfig.applicationCallbacks.getApplicationInstance()).thenReturn(app); + DownloadServiceInterface.setImpl(new DownloadServiceInterfaceStub()); // Initialize database PodDBAdapter.init(context); diff --git a/core/src/test/java/de/danoeh/antennapod/core/service/download/DownloadServiceInterfaceStub.java b/core/src/test/java/de/danoeh/antennapod/core/service/download/DownloadServiceInterfaceStub.java new file mode 100644 index 000000000..952936f70 --- /dev/null +++ b/core/src/test/java/de/danoeh/antennapod/core/service/download/DownloadServiceInterfaceStub.java @@ -0,0 +1,18 @@ +package de.danoeh.antennapod.core.service.download; + +import android.content.Context; + +public class DownloadServiceInterfaceStub extends DownloadServiceInterface { + + public void download(Context context, boolean cleanupMedia, DownloadRequest... requests) { + } + + public void refreshAllFeeds(Context context, boolean initiatedByUser) { + } + + public void cancel(Context context, String url) { + } + + public void cancelAll(Context context) { + } +} diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java b/core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java index 533b517d5..ba8877da6 100644 --- a/core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java +++ b/core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java @@ -10,6 +10,8 @@ import androidx.core.util.Consumer; import androidx.preference.PreferenceManager; import androidx.test.platform.app.InstrumentationRegistry; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterface; +import de.danoeh.antennapod.core.service.download.DownloadServiceInterfaceStub; import de.danoeh.antennapod.storage.database.PodDBAdapter; import org.awaitility.Awaitility; import org.junit.After; @@ -65,6 +67,7 @@ public class DbWriterTest { Application app = (Application) context; ClientConfig.applicationCallbacks = mock(ApplicationCallbacks.class); when(ClientConfig.applicationCallbacks.getApplicationInstance()).thenReturn(app); + DownloadServiceInterface.setImpl(new DownloadServiceInterfaceStub()); // create new database PodDBAdapter.init(context); |