Move playback service to module (#7042)

This commit is contained in:
ByteHamster 2024-03-29 21:05:02 +01:00 committed by GitHub
parent 2fd73b148d
commit 8accb54685
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
57 changed files with 220 additions and 162 deletions

View File

@ -91,6 +91,7 @@ dependencies {
implementation project(':ui:preferences')
implementation project(':ui:statistics')
implementation project(':net:sync:service-interface')
implementation project(':playback:service')
annotationProcessor "androidx.annotation:annotation:$annotationVersion"
implementation "androidx.appcompat:appcompat:$appcompatVersion"

View File

@ -18,13 +18,13 @@ import androidx.test.espresso.util.HumanReadables;
import androidx.test.espresso.util.TreeIterables;
import android.view.View;
import de.danoeh.antennapod.playback.service.PlaybackService;
import de.danoeh.antennapod.storage.database.PodDBAdapter;
import junit.framework.AssertionFailedError;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.fragment.NavDrawerFragment;
import org.awaitility.Awaitility;
import org.awaitility.core.ConditionTimeoutException;

View File

@ -11,11 +11,11 @@ import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.playback.service.PlaybackController;
import de.danoeh.antennapod.storage.preferences.PlaybackPreferences;
import de.danoeh.antennapod.storage.database.DBReader;
import de.danoeh.antennapod.storage.database.DBWriter;
import de.danoeh.antennapod.storage.database.LongList;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedItemFilter;
import de.danoeh.antennapod.model.feed.FeedMedia;

View File

@ -8,6 +8,7 @@ import androidx.test.filters.MediumTest;
import de.danoeh.antennapod.model.feed.VolumeAdaptionSetting;
import de.danoeh.antennapod.playback.base.PlaybackServiceMediaPlayer;
import de.danoeh.antennapod.playback.base.PlayerStatus;
import de.danoeh.antennapod.playback.service.internal.LocalPSMP;
import de.danoeh.antennapod.storage.database.PodDBAdapter;
import de.test.antennapod.EspressoTestUtils;
import junit.framework.AssertionFailedError;
@ -27,7 +28,6 @@ import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.model.feed.FeedPreferences;
import de.danoeh.antennapod.core.service.playback.LocalPSMP;
import de.danoeh.antennapod.model.playback.Playable;
import de.test.antennapod.util.service.download.HTTPBin;
import org.junit.After;

View File

@ -6,6 +6,7 @@ import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.LargeTest;
import de.danoeh.antennapod.event.playback.SleepTimerUpdatedEvent;
import de.danoeh.antennapod.playback.service.internal.PlaybackServiceTaskManager;
import de.danoeh.antennapod.storage.preferences.SleepTimerPreferences;
import de.danoeh.antennapod.storage.database.PodDBAdapter;
import de.danoeh.antennapod.ui.widget.WidgetUpdater;
@ -23,7 +24,6 @@ import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.core.service.playback.PlaybackServiceTaskManager;
import de.danoeh.antennapod.model.playback.Playable;
import static org.junit.Assert.assertFalse;

View File

@ -5,7 +5,6 @@ import android.os.StrictMode;
import com.google.android.material.color.DynamicColors;
import de.danoeh.antennapod.core.ApCoreEventBusIndex;
import de.danoeh.antennapod.error.CrashReportWriter;
import de.danoeh.antennapod.error.RxJavaErrorHandlerSetup;
import de.danoeh.antennapod.preferences.PreferenceUpgrader;
@ -37,7 +36,6 @@ public class PodcastApp extends Application {
SPAUtil.sendSPAppsQueryFeedsIntent(this);
EventBus.builder()
.addIndex(new ApEventBusIndex())
.addIndex(new ApCoreEventBusIndex())
.logNoSubscriberMessages(false)
.sendNoSubscriberEvent(false)
.installDefaultEventBus();

View File

@ -35,7 +35,7 @@ import de.danoeh.antennapod.ui.common.ThemeSwitcher;
import de.danoeh.antennapod.net.download.serviceinterface.DownloadRequestCreator;
import de.danoeh.antennapod.net.discovery.FeedUrlNotFoundException;
import de.danoeh.antennapod.storage.database.FeedDatabaseWriter;
import de.danoeh.antennapod.core.service.playback.PlaybackServiceInterface;
import de.danoeh.antennapod.playback.service.PlaybackServiceInterface;
import de.danoeh.antennapod.core.util.DownloadErrorLabel;
import de.danoeh.antennapod.databinding.EditTextDialogBinding;
import de.danoeh.antennapod.databinding.OnlinefeedviewHeaderBinding;

View File

@ -43,8 +43,9 @@ import de.danoeh.antennapod.event.PlayerErrorEvent;
import de.danoeh.antennapod.event.playback.PlaybackServiceEvent;
import de.danoeh.antennapod.event.playback.SleepTimerUpdatedEvent;
import de.danoeh.antennapod.fragment.ChaptersFragment;
import de.danoeh.antennapod.playback.service.PlaybackController;
import de.danoeh.antennapod.playback.service.PlaybackService;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.storage.database.DBReader;
import de.danoeh.antennapod.storage.database.DBWriter;
import de.danoeh.antennapod.ui.common.Converter;
@ -52,7 +53,6 @@ import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.ShareUtils;
import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.databinding.VideoplayerActivityBinding;
import de.danoeh.antennapod.dialog.PlaybackControlsDialog;
import de.danoeh.antennapod.dialog.ShareDialog;

View File

@ -16,10 +16,10 @@ import de.danoeh.antennapod.model.playback.MediaType;
import de.danoeh.antennapod.net.common.NetworkUtils;
import de.danoeh.antennapod.model.playback.RemoteMedia;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.playback.service.PlaybackService;
import de.danoeh.antennapod.playback.service.PlaybackServiceStarter;
import de.danoeh.antennapod.ui.common.DateFormatter;
import de.danoeh.antennapod.model.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText;
import de.danoeh.antennapod.dialog.StreamingConfirmationDialog;

View File

@ -7,7 +7,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import android.view.View;
import de.danoeh.antennapod.core.util.PlaybackStatus;
import de.danoeh.antennapod.playback.service.PlaybackStatus;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface;

View File

@ -5,7 +5,7 @@ import android.view.KeyEvent;
import androidx.annotation.DrawableRes;
import androidx.annotation.StringRes;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.util.PlaybackStatus;
import de.danoeh.antennapod.playback.service.PlaybackStatus;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.ui.appstartintent.MediaButtonStarter;

View File

@ -5,14 +5,14 @@ import android.util.Log;
import androidx.annotation.DrawableRes;
import androidx.annotation.StringRes;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.playback.service.PlaybackService;
import de.danoeh.antennapod.playback.service.PlaybackServiceStarter;
import de.danoeh.antennapod.storage.database.DBWriter;
import de.danoeh.antennapod.event.FeedItemEvent;
import de.danoeh.antennapod.event.MessageEvent;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.model.playback.MediaType;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
import org.greenrobot.eventbus.EventBus;
public class PlayActionButton extends ItemActionButton {

View File

@ -7,8 +7,8 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.model.playback.MediaType;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
import de.danoeh.antennapod.playback.service.PlaybackService;
import de.danoeh.antennapod.playback.service.PlaybackServiceStarter;
public class PlayLocalActionButton extends ItemActionButton {

View File

@ -9,10 +9,10 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.model.playback.MediaType;
import de.danoeh.antennapod.playback.service.PlaybackService;
import de.danoeh.antennapod.playback.service.PlaybackServiceStarter;
import de.danoeh.antennapod.storage.preferences.UsageStatistics;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.net.common.NetworkUtils;
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
import de.danoeh.antennapod.dialog.StreamingConfirmationDialog;
public class StreamActionButton extends ItemActionButton {

View File

@ -11,7 +11,8 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import androidx.fragment.app.DialogFragment;
import android.widget.Button;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.playback.service.PlaybackController;
import java.util.List;
public class PlaybackControlsDialog extends DialogFragment {

View File

@ -20,6 +20,8 @@ import androidx.fragment.app.DialogFragment;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.snackbar.Snackbar;
import de.danoeh.antennapod.playback.service.PlaybackController;
import de.danoeh.antennapod.playback.service.PlaybackService;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
@ -28,9 +30,7 @@ import java.util.Locale;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.storage.preferences.SleepTimerPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.ui.common.Converter;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.event.playback.SleepTimerUpdatedEvent;
public class SleepTimerDialog extends DialogFragment {

View File

@ -3,9 +3,9 @@ package de.danoeh.antennapod.dialog;
import android.content.Context;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.playback.service.PlaybackServiceStarter;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.model.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
public class StreamingConfirmationDialog {
private final Context context;

View File

@ -17,8 +17,8 @@ import com.google.android.material.chip.Chip;
import com.google.android.material.snackbar.Snackbar;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.event.playback.SpeedChangedEvent;
import de.danoeh.antennapod.playback.service.PlaybackController;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.view.ItemOffsetDecoration;
import de.danoeh.antennapod.view.PlaybackSpeedSeekBar;
import org.greenrobot.eventbus.EventBus;

View File

@ -25,6 +25,7 @@ import com.google.android.material.appbar.MaterialToolbar;
import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.elevation.SurfaceColors;
import de.danoeh.antennapod.playback.service.PlaybackController;
import de.danoeh.antennapod.ui.appstartintent.MediaButtonStarter;
import de.danoeh.antennapod.ui.episodes.PlaybackSpeedUtils;
import de.danoeh.antennapod.ui.episodes.TimeSpeedConverter;
@ -40,7 +41,6 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.util.ChapterUtils;
import de.danoeh.antennapod.ui.common.Converter;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.dialog.MediaPlayerErrorDialog;
import de.danoeh.antennapod.dialog.SkipPreferenceDialog;
import de.danoeh.antennapod.dialog.SleepTimerDialog;

View File

@ -21,12 +21,12 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.ChaptersListAdapter;
import de.danoeh.antennapod.core.util.ChapterUtils;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.event.playback.PlaybackPositionEvent;
import de.danoeh.antennapod.model.feed.Chapter;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.model.playback.Playable;
import de.danoeh.antennapod.playback.base.PlayerStatus;
import de.danoeh.antennapod.playback.service.PlaybackController;
import io.reactivex.Maybe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;

View File

@ -33,8 +33,8 @@ import com.google.android.material.snackbar.Snackbar;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.util.ChapterUtils;
import de.danoeh.antennapod.playback.service.PlaybackController;
import de.danoeh.antennapod.ui.common.DateFormatter;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.databinding.CoverFragmentBinding;
import de.danoeh.antennapod.event.playback.PlaybackPositionEvent;
import de.danoeh.antennapod.model.feed.Chapter;

View File

@ -20,10 +20,10 @@ import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.event.playback.PlaybackPositionEvent;
import de.danoeh.antennapod.event.playback.PlaybackServiceEvent;
import de.danoeh.antennapod.model.playback.MediaType;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.model.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.playback.base.PlayerStatus;
import de.danoeh.antennapod.playback.service.PlaybackController;
import de.danoeh.antennapod.playback.service.PlaybackService;
import de.danoeh.antennapod.ui.episodes.ImageResourceUtils;
import de.danoeh.antennapod.view.PlayButton;
import io.reactivex.Maybe;

View File

@ -13,8 +13,8 @@ import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.playback.service.PlaybackController;
import de.danoeh.antennapod.storage.database.DBReader;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.core.util.gui.ShownotesCleaner;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.model.playback.Playable;

View File

@ -38,12 +38,13 @@ import de.danoeh.antennapod.adapter.actionbutton.PlayLocalActionButton;
import de.danoeh.antennapod.adapter.actionbutton.StreamActionButton;
import de.danoeh.antennapod.adapter.actionbutton.VisitWebsiteActionButton;
import de.danoeh.antennapod.event.EpisodeDownloadEvent;
import de.danoeh.antennapod.core.util.PlaybackStatus;
import de.danoeh.antennapod.playback.service.PlaybackStatus;
import de.danoeh.antennapod.event.FeedItemEvent;
import de.danoeh.antennapod.event.PlayerStatusEvent;
import de.danoeh.antennapod.event.UnreadItemsUpdateEvent;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.playback.service.PlaybackController;
import de.danoeh.antennapod.storage.preferences.UsageStatistics;
import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
@ -52,7 +53,6 @@ import de.danoeh.antennapod.ui.common.Converter;
import de.danoeh.antennapod.ui.common.DateFormatter;
import de.danoeh.antennapod.ui.common.CircularProgressBar;
import de.danoeh.antennapod.ui.common.ThemeUtils;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.core.util.gui.ShownotesCleaner;
import de.danoeh.antennapod.ui.episodes.ImageResourceUtils;
import de.danoeh.antennapod.view.ShownotesWebView;

View File

@ -19,12 +19,12 @@ import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.net.sync.serviceinterface.SynchronizationQueueSink;
import de.danoeh.antennapod.storage.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.util.FeedUtil;
import de.danoeh.antennapod.core.service.playback.PlaybackServiceInterface;
import de.danoeh.antennapod.playback.service.PlaybackServiceInterface;
import de.danoeh.antennapod.storage.database.DBWriter;
import de.danoeh.antennapod.storage.preferences.SynchronizationSettings;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.PlaybackStatus;
import de.danoeh.antennapod.playback.service.PlaybackStatus;
import de.danoeh.antennapod.core.util.ShareUtils;
import de.danoeh.antennapod.dialog.ShareDialog;
import de.danoeh.antennapod.model.feed.FeedItem;

View File

@ -20,7 +20,7 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.CoverLoader;
import de.danoeh.antennapod.adapter.actionbutton.ItemActionButton;
import de.danoeh.antennapod.core.util.PlaybackStatus;
import de.danoeh.antennapod.playback.service.PlaybackStatus;
import de.danoeh.antennapod.core.util.download.MediaSizeLoader;
import de.danoeh.antennapod.event.playback.PlaybackPositionEvent;
import de.danoeh.antennapod.ui.common.DateFormatter;

View File

@ -14,7 +14,7 @@ import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.CoverLoader;
import de.danoeh.antennapod.adapter.actionbutton.ItemActionButton;
import de.danoeh.antennapod.ui.common.DateFormatter;
import de.danoeh.antennapod.core.util.PlaybackStatus;
import de.danoeh.antennapod.playback.service.PlaybackStatus;
import de.danoeh.antennapod.event.playback.PlaybackPositionEvent;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;

View File

@ -30,7 +30,7 @@
</Match>
<Match>
<Bug pattern="MS_CANNOT_BE_FINAL"/>
<Class name="de.danoeh.antennapod.core.service.playback.PlaybackService"/>
<Class name="de.danoeh.antennapod.playback.service.PlaybackService"/>
</Match>
<Match>
<Bug pattern="MS_MUTABLE_ARRAY"/>
@ -62,7 +62,7 @@
</Match>
<Match>
<Bug pattern="ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD"/>
<Class name="de.danoeh.antennapod.core.service.playback.PlaybackService"/>
<Class name="de.danoeh.antennapod.playback.service.PlaybackService"/>
</Match>
<Match>
<Bug pattern="ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD"/>

View File

@ -23,32 +23,20 @@ android {
}
dependencies {
implementation project(':event')
implementation project(':model')
implementation project(':net:common')
implementation project(':net:download:service-interface')
implementation project(':net:sync:service-interface')
implementation project(':parser:feed')
implementation project(':parser:media')
implementation project(':playback:base')
implementation project(':playback:cast')
implementation project(':storage:database')
implementation project(':storage:preferences')
implementation project(':ui:app-start-intent')
implementation project(':storage:database')
implementation project(':ui:common')
implementation project(':ui:episodes')
implementation project(':ui:notifications')
implementation project(':ui:widget')
annotationProcessor "androidx.annotation:annotation:$annotationVersion"
implementation "androidx.appcompat:appcompat:$appcompatVersion"
implementation "androidx.core:core:$coreVersion"
implementation 'androidx.documentfile:documentfile:1.0.1'
implementation "androidx.fragment:fragment:$fragmentVersion"
implementation "androidx.media:media:$mediaVersion"
implementation "androidx.media3:media3-datasource-okhttp:$media3Version"
implementation "androidx.media3:media3-exoplayer:$media3Version"
implementation "androidx.media3:media3-ui:$media3Version"
implementation "androidx.preference:preference:$preferenceVersion"
implementation "androidx.work:work-runtime:$workManagerVersion"
implementation "com.google.android.material:material:$googleMaterialVersion"

View File

@ -12,60 +12,4 @@
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:supportsRtl="true">
<service android:name=".service.playback.PlaybackService"
android:label="@string/app_name"
android:enabled="true"
android:exported="true"
android:foregroundServiceType="mediaPlayback"
tools:ignore="ExportedService">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService"/>
<action android:name="de.danoeh.antennapod.intents.PLAYBACK_SERVICE" />
</intent-filter>
</service>
<receiver
android:name=".receiver.MediaButtonReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
<intent-filter>
<action android:name="de.danoeh.antennapod.NOTIFY_BUTTON_RECEIVER" />
</intent-filter>
</receiver>
<receiver android:name=".receiver.FeedUpdateReceiver"
android:label="@string/feed_update_receiver_name"
android:exported="true"
tools:ignore="ExportedReceiver" /> <!-- allow feeds update to be triggered by external apps -->
<service
android:name=".service.QuickSettingsTileService"
android:enabled="true"
android:exported="true"
android:label="@string/app_name"
android:icon="@drawable/ic_notification"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
<meta-data android:name="android.service.quicksettings.ACTIVE_TILE" android:value="true" />
<meta-data android:name="android.service.quicksettings.TOGGLEABLE_TILE" android:value="true" />
</service>
</application>
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
</queries>
</manifest>

View File

@ -9,7 +9,6 @@ import java.util.List;
import de.danoeh.antennapod.model.feed.FeedItemFilter;
import de.danoeh.antennapod.model.feed.SortOrder;
import de.danoeh.antennapod.core.util.PlaybackStatus;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedPreferences;
import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface;
@ -73,7 +72,6 @@ public class AutomaticDownloadAlgorithm {
if (!item.isAutoDownloadEnabled()
|| item.isDownloaded()
|| !item.hasMedia()
|| PlaybackStatus.isPlaying(item.getMedia())
|| item.getFeed().isLocalFeed()) {
it.remove();
}

View File

@ -14,8 +14,4 @@
<!-- View types -->
<item name="view_type_episode_item" type="id"/>
<!-- Notifications need unique IDs to update/cancel them -->
<item name="notification_playing" type="id"/>
<item name="notification_streaming_confirmation" type="id"/>
</resources>
</resources>

View File

@ -1,7 +1,19 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:supportsRtl="true">
<receiver android:name=".feed.FeedUpdateReceiver"
android:label="@string/feed_update_receiver_name"
android:exported="true"
tools:ignore="ExportedReceiver" /> <!-- allow feeds update to be triggered by external apps -->
</application>
</manifest>

View File

@ -1,4 +1,4 @@
package de.danoeh.antennapod.core.receiver;
package de.danoeh.antennapod.net.download.service.feed;
import android.content.BroadcastReceiver;
import android.content.Context;

View File

@ -18,10 +18,10 @@ import androidx.core.content.ContextCompat;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedCounter;
import de.danoeh.antennapod.model.feed.FeedPreferences;
import de.danoeh.antennapod.net.download.service.R;
import de.danoeh.antennapod.storage.database.PodDBAdapter;
import de.danoeh.antennapod.ui.notifications.NotificationUtils;

View File

@ -0,0 +1,3 @@
# :playback:service
The main service doing media playback.

View File

@ -0,0 +1,44 @@
plugins {
id("com.android.library")
}
apply from: "../../common.gradle"
apply from: "../../playFlavor.gradle"
android {
namespace "de.danoeh.antennapod.playback.service"
}
dependencies {
implementation project(':core')
implementation project(':event')
implementation project(':model')
implementation project(':net:common')
implementation project(':net:sync:service-interface')
implementation project(':playback:base')
implementation project(':playback:cast')
implementation project(':storage:database')
implementation project(':storage:preferences')
implementation project(':ui:app-start-intent')
implementation project(':ui:common')
implementation project(':ui:episodes')
implementation project(':ui:i18n')
implementation project(':ui:notifications')
implementation project(':ui:widget')
annotationProcessor "androidx.annotation:annotation:$annotationVersion"
implementation "androidx.core:core:$coreVersion"
implementation "androidx.appcompat:appcompat:$appcompatVersion"
implementation "androidx.media:media:$mediaVersion"
implementation "androidx.media3:media3-datasource-okhttp:$media3Version"
implementation "androidx.media3:media3-exoplayer:$media3Version"
implementation "androidx.media3:media3-ui:$media3Version"
implementation "io.reactivex.rxjava2:rxandroid:$rxAndroidVersion"
implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion"
implementation "org.greenrobot:eventbus:$eventbusVersion"
implementation "com.github.bumptech.glide:glide:$glideVersion"
implementation "org.apache.commons:commons-lang3:$commonslangVersion"
testImplementation "junit:junit:$junitVersion"
testImplementation 'org.mockito:mockito-core:5.11.0'
}

View File

@ -0,0 +1,66 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:supportsRtl="true">
<service android:name="de.danoeh.antennapod.playback.service.PlaybackService"
android:label="@string/app_name"
android:enabled="true"
android:exported="true"
android:foregroundServiceType="mediaPlayback"
tools:ignore="ExportedService">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService"/>
<action android:name="de.danoeh.antennapod.intents.PLAYBACK_SERVICE" />
</intent-filter>
</service>
<receiver
android:name="de.danoeh.antennapod.playback.service.MediaButtonReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
<intent-filter>
<action android:name="de.danoeh.antennapod.NOTIFY_BUTTON_RECEIVER" />
</intent-filter>
</receiver>
<service
android:name="de.danoeh.antennapod.playback.service.QuickSettingsTileService"
android:enabled="true"
android:exported="true"
android:label="@string/app_name"
android:icon="@drawable/ic_notification"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
<meta-data android:name="android.service.quicksettings.ACTIVE_TILE" android:value="true" />
<meta-data android:name="android.service.quicksettings.TOGGLEABLE_TILE" android:value="true" />
</service>
</application>
<queries>
<intent>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="https" />
</intent>
</queries>
</manifest>

View File

@ -1,4 +1,4 @@
package de.danoeh.antennapod.core.receiver;
package de.danoeh.antennapod.playback.service;
import android.content.BroadcastReceiver;
import android.content.Context;

View File

@ -1,4 +1,4 @@
package de.danoeh.antennapod.core.util.playback;
package de.danoeh.antennapod.playback.service;
import android.app.Activity;
import android.content.BroadcastReceiver;
@ -12,7 +12,6 @@ import android.util.Log;
import android.util.Pair;
import android.view.SurfaceHolder;
import androidx.annotation.NonNull;
import de.danoeh.antennapod.core.service.playback.PlaybackServiceInterface;
import de.danoeh.antennapod.storage.database.DBReader;
import de.danoeh.antennapod.storage.database.DBWriter;
import de.danoeh.antennapod.event.playback.PlaybackPositionEvent;
@ -22,7 +21,6 @@ import de.danoeh.antennapod.event.playback.SpeedChangedEvent;
import de.danoeh.antennapod.model.feed.FeedPreferences;
import de.danoeh.antennapod.model.playback.MediaType;
import de.danoeh.antennapod.storage.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.model.playback.Playable;
import de.danoeh.antennapod.playback.base.PlaybackServiceMediaPlayer;
import de.danoeh.antennapod.playback.base.PlayerStatus;

View File

@ -1,4 +1,4 @@
package de.danoeh.antennapod.core.service.playback;
package de.danoeh.antennapod.playback.service;
import static de.danoeh.antennapod.model.feed.FeedPreferences.SPEED_USE_GLOBAL;
@ -52,6 +52,13 @@ import androidx.media.MediaBrowserServiceCompat;
import de.danoeh.antennapod.event.PlayerStatusEvent;
import de.danoeh.antennapod.net.sync.serviceinterface.SynchronizationQueueSink;
import de.danoeh.antennapod.playback.service.internal.LocalPSMP;
import de.danoeh.antennapod.playback.service.internal.PlayableUtils;
import de.danoeh.antennapod.playback.service.internal.PlaybackServiceNotificationBuilder;
import de.danoeh.antennapod.playback.service.internal.PlaybackServiceStateManager;
import de.danoeh.antennapod.playback.service.internal.PlaybackServiceTaskManager;
import de.danoeh.antennapod.playback.service.internal.PlaybackVolumeUpdater;
import de.danoeh.antennapod.playback.service.internal.WearMediaSession;
import de.danoeh.antennapod.ui.notifications.NotificationUtils;
import de.danoeh.antennapod.ui.widget.WidgetUpdater;
import org.greenrobot.eventbus.EventBus;
@ -65,20 +72,15 @@ import java.util.GregorianCalendar;
import java.util.List;
import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.storage.preferences.PlaybackPreferences;
import de.danoeh.antennapod.storage.preferences.SleepTimerPreferences;
import de.danoeh.antennapod.core.receiver.MediaButtonReceiver;
import de.danoeh.antennapod.core.service.QuickSettingsTileService;
import de.danoeh.antennapod.core.service.playback.PlaybackServiceTaskManager.SleepTimer;
import de.danoeh.antennapod.storage.database.DBReader;
import de.danoeh.antennapod.storage.database.DBWriter;
import de.danoeh.antennapod.playback.service.internal.PlaybackServiceTaskManager.SleepTimer;
import de.danoeh.antennapod.core.util.ChapterUtils;
import de.danoeh.antennapod.core.util.FeedUtil;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.net.common.NetworkUtils;
import de.danoeh.antennapod.core.util.playback.PlayableUtils;
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
import de.danoeh.antennapod.event.MessageEvent;
import de.danoeh.antennapod.event.PlayerErrorEvent;
import de.danoeh.antennapod.event.playback.BufferUpdateEvent;

View File

@ -1,4 +1,4 @@
package de.danoeh.antennapod.core.service.playback;
package de.danoeh.antennapod.playback.service;
public abstract class PlaybackServiceInterface {
public static final String EXTRA_PLAYABLE = "PlaybackService.PlayableExtra";

View File

@ -1,12 +1,10 @@
package de.danoeh.antennapod.core.util.playback;
package de.danoeh.antennapod.playback.service;
import android.content.Context;
import android.content.Intent;
import android.os.Parcelable;
import androidx.core.content.ContextCompat;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.service.playback.PlaybackServiceInterface;
import de.danoeh.antennapod.model.playback.Playable;
public class PlaybackServiceStarter {

View File

@ -1,7 +1,6 @@
package de.danoeh.antennapod.core.util;
package de.danoeh.antennapod.playback.service;
import de.danoeh.antennapod.storage.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.model.feed.FeedMedia;
public abstract class PlaybackStatus {

View File

@ -1,4 +1,4 @@
package de.danoeh.antennapod.core.service;
package de.danoeh.antennapod.playback.service;
import android.content.ComponentName;
import android.content.Intent;
@ -12,7 +12,6 @@ import android.view.KeyEvent;
import androidx.annotation.RequiresApi;
import de.danoeh.antennapod.storage.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.ui.appstartintent.MediaButtonStarter;
@RequiresApi(api = Build.VERSION_CODES.N)

View File

@ -1,4 +1,4 @@
package de.danoeh.antennapod.core.service.playback;
package de.danoeh.antennapod.playback.service.internal;
import android.content.Context;
import android.media.audiofx.LoudnessEnhancer;
@ -9,10 +9,12 @@ import android.view.SurfaceHolder;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.OptIn;
import androidx.core.util.Consumer;
import androidx.media3.common.C;
import androidx.media3.common.PlaybackException;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.database.StandaloneDatabaseProvider;
import androidx.media3.datasource.DataSource;
import androidx.media3.datasource.DefaultDataSource;
@ -42,9 +44,9 @@ import androidx.media3.extractor.DefaultExtractorsFactory;
import androidx.media3.extractor.mp3.Mp3Extractor;
import androidx.media3.ui.DefaultTrackNameProvider;
import androidx.media3.ui.TrackNameProvider;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.net.common.UserAgentInterceptor;
import de.danoeh.antennapod.model.feed.VolumeAdaptionSetting;
import de.danoeh.antennapod.playback.service.R;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.net.common.AntennapodHttpClient;
import de.danoeh.antennapod.net.common.HttpCredentialEncoder;
@ -62,6 +64,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
@OptIn(markerClass = UnstableApi.class)
public class ExoPlayerWrapper {
public static final int BUFFERING_STARTED = -1;
public static final int BUFFERING_ENDED = -2;

View File

@ -1,4 +1,4 @@
package de.danoeh.antennapod.core.service.playback;
package de.danoeh.antennapod.playback.service.internal;
import android.app.UiModeManager;
import android.content.Context;
@ -24,6 +24,7 @@ import de.danoeh.antennapod.model.playback.Playable;
import de.danoeh.antennapod.playback.base.PlaybackServiceMediaPlayer;
import de.danoeh.antennapod.playback.base.PlayerStatus;
import de.danoeh.antennapod.playback.base.RewindAfterPauseUtils;
import de.danoeh.antennapod.playback.service.PlaybackService;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.ui.episodes.PlaybackSpeedUtils;
import org.greenrobot.eventbus.EventBus;

View File

@ -1,4 +1,4 @@
package de.danoeh.antennapod.core.util.playback;
package de.danoeh.antennapod.playback.service.internal;
import de.danoeh.antennapod.storage.database.DBWriter;
import de.danoeh.antennapod.model.feed.FeedItem;

View File

@ -1,4 +1,4 @@
package de.danoeh.antennapod.core.service.playback;
package de.danoeh.antennapod.playback.service.internal;
import android.app.Notification;
import android.app.PendingIntent;
@ -18,9 +18,10 @@ import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.app.NotificationCompat;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.playback.service.MediaButtonReceiver;
import de.danoeh.antennapod.playback.service.PlaybackService;
import de.danoeh.antennapod.playback.service.R;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.core.receiver.MediaButtonReceiver;
import de.danoeh.antennapod.ui.common.Converter;
import de.danoeh.antennapod.model.playback.Playable;
import de.danoeh.antennapod.ui.episodes.ImageResourceUtils;

View File

@ -1,35 +1,36 @@
package de.danoeh.antennapod.core.service.playback;
package de.danoeh.antennapod.playback.service.internal;
import android.app.Notification;
import android.util.Log;
import androidx.core.app.ServiceCompat;
import de.danoeh.antennapod.playback.service.PlaybackService;
class PlaybackServiceStateManager {
public class PlaybackServiceStateManager {
private static final String TAG = "PlaybackSrvState";
private final PlaybackService playbackService;
private volatile boolean isInForeground = false;
private volatile boolean hasReceivedValidStartCommand = false;
PlaybackServiceStateManager(PlaybackService playbackService) {
public PlaybackServiceStateManager(PlaybackService playbackService) {
this.playbackService = playbackService;
}
void startForeground(int notificationId, Notification notification) {
public void startForeground(int notificationId, Notification notification) {
Log.d(TAG, "startForeground");
playbackService.startForeground(notificationId, notification);
isInForeground = true;
}
void stopService() {
public void stopService() {
Log.d(TAG, "stopService");
stopForeground(true);
playbackService.stopSelf();
hasReceivedValidStartCommand = false;
}
void stopForeground(boolean removeNotification) {
public void stopForeground(boolean removeNotification) {
Log.d(TAG, "stopForeground");
if (isInForeground) {
if (removeNotification) {
@ -41,11 +42,11 @@ class PlaybackServiceStateManager {
isInForeground = false;
}
boolean hasReceivedValidStartCommand() {
public boolean hasReceivedValidStartCommand() {
return hasReceivedValidStartCommand;
}
void validStartCommandWasReceived() {
public void validStartCommandWasReceived() {
this.hasReceivedValidStartCommand = true;
}
}

View File

@ -1,4 +1,4 @@
package de.danoeh.antennapod.core.service.playback;
package de.danoeh.antennapod.playback.service.internal;
import android.content.Context;
import android.os.Handler;
@ -275,7 +275,7 @@ public class PlaybackServiceTaskManager {
/**
* Sleeps for a given time and then pauses playback.
*/
class SleepTimer implements Runnable {
public class SleepTimer implements Runnable {
private static final String TAG = "SleepTimer";
private static final long UPDATE_INTERVAL = 1000L;
public static final long NOTIFICATION_THRESHOLD = 10000;

View File

@ -1,4 +1,4 @@
package de.danoeh.antennapod.core.service.playback;
package de.danoeh.antennapod.playback.service.internal;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.model.feed.FeedPreferences;
@ -7,7 +7,7 @@ import de.danoeh.antennapod.model.playback.Playable;
import de.danoeh.antennapod.playback.base.PlaybackServiceMediaPlayer;
import de.danoeh.antennapod.playback.base.PlayerStatus;
class PlaybackVolumeUpdater {
public class PlaybackVolumeUpdater {
public void updateVolumeIfNecessary(PlaybackServiceMediaPlayer mediaPlayer, long feedId,
VolumeAdaptionSetting volumeAdaptionSetting) {

View File

@ -1,4 +1,4 @@
package de.danoeh.antennapod.core.service.playback;
package de.danoeh.antennapod.playback.service.internal;
import android.content.Context;
import android.hardware.Sensor;
@ -7,8 +7,7 @@ import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
class ShakeListener implements SensorEventListener
{
public class ShakeListener implements SensorEventListener {
private static final String TAG = ShakeListener.class.getSimpleName();
private Sensor mAccelerometer;

View File

@ -1,4 +1,4 @@
package de.danoeh.antennapod.core.service.playback;
package de.danoeh.antennapod.playback.service.internal;
import android.os.Bundle;
import android.support.v4.media.session.MediaSessionCompat;
@ -9,13 +9,13 @@ public class WearMediaSession {
* Take a custom action builder and make sure the custom action shows on Wear OS because this is the Play version
* of the app.
*/
static void addWearExtrasToAction(PlaybackStateCompat.CustomAction.Builder actionBuilder) {
public static void addWearExtrasToAction(PlaybackStateCompat.CustomAction.Builder actionBuilder) {
Bundle actionExtras = new Bundle();
actionExtras.putBoolean("android.support.wearable.media.extra.CUSTOM_ACTION_SHOW_ON_WEAR", true);
actionBuilder.setExtras(actionExtras);
}
static void mediaSessionSetExtraForWear(MediaSessionCompat mediaSession) {
public static void mediaSessionSetExtraForWear(MediaSessionCompat mediaSession) {
Bundle sessionExtras = new Bundle();
sessionExtras.putBoolean("android.support.wearable.media.extra.RESERVE_SLOT_SKIP_TO_PREVIOUS", false);
sessionExtras.putBoolean("android.support.wearable.media.extra.RESERVE_SLOT_SKIP_TO_NEXT", false);

View File

@ -0,0 +1,4 @@
<resources>
<item name="notification_playing" type="id" />
<item name="notification_streaming_confirmation" type="id" />
</resources>

View File

@ -1,4 +1,4 @@
package de.danoeh.antennapod.core.service.playback;
package de.danoeh.antennapod.playback.service;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedItem;
@ -8,6 +8,7 @@ import de.danoeh.antennapod.model.feed.VolumeAdaptionSetting;
import de.danoeh.antennapod.model.playback.Playable;
import de.danoeh.antennapod.playback.base.PlaybackServiceMediaPlayer;
import de.danoeh.antennapod.playback.base.PlayerStatus;
import de.danoeh.antennapod.playback.service.internal.PlaybackVolumeUpdater;
import org.junit.Before;
import org.junit.Test;

View File

@ -35,6 +35,7 @@ include ':parser:media'
include ':playback:base'
include ':playback:cast'
include ':playback:service'
include ':storage:database'
include ':storage:importexport'