summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.md2
-rw-r--r--.github/workflows/gradle-wrapper-validation.yml10
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java3
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/FeedPreferenceSkipDialog.java48
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java24
-rw-r--r--app/src/main/res/layout/external_player_fragment.xml3
-rw-r--r--app/src/main/res/layout/feed_item_list_fragment.xml3
-rw-r--r--app/src/main/res/layout/feed_pref_skip_dialog.xml78
-rw-r--r--app/src/main/res/layout/feedinfo.xml3
-rw-r--r--app/src/main/res/layout/nav_listitem.xml2
-rw-r--r--app/src/main/res/xml/feed_settings.xml9
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/event/settings/SkipIntroEndingChangedEvent.java25
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java41
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java84
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java6
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java14
-rw-r--r--core/src/main/res/values/strings.xml10
18 files changed, 352 insertions, 15 deletions
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 2c2e0cfa2..9f0531c01 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -32,7 +32,7 @@ If you are experiencing a crash, including the stacktrace will likely get it fix
1. Than that
1. Then
-**Environment**: [Settings you have changed, e.g. Auto Download. "Unusual" devices you use, e.g. Bluetooth headphones. Do you still use Prestissimo? Did you select another media player?]
+**Environment**: [Settings you have changed, e.g. Auto Download. "Unusual" devices you use, e.g. Bluetooth headphones. Did you select another media player?]
**Stacktrace/Logcat**:
```
diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml
new file mode 100644
index 000000000..f365456a1
--- /dev/null
+++ b/.github/workflows/gradle-wrapper-validation.yml
@@ -0,0 +1,10 @@
+name: "Validate Gradle Wrapper"
+on: [pull_request]
+
+jobs:
+ validation:
+ name: "Validation"
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: gradle/wrapper-validation-action@v1
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
index 7e052b445..9198c7a3e 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
@@ -410,7 +410,8 @@ public class EpisodesApplyActionFragment extends Fragment {
}
ActivityCompat.invalidateOptionsMenu(EpisodesApplyActionFragment.this.getActivity());
showSpeedDialIfAnyChecked();
- toolbar.setTitle(getString(R.string.num_selected_label, checkedIds.size()));
+ toolbar.setTitle(getResources().getQuantityString(R.plurals.num_selected_label,
+ checkedIds.size(), checkedIds.size()));
}
private void queueChecked() {
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/FeedPreferenceSkipDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/FeedPreferenceSkipDialog.java
new file mode 100644
index 000000000..0e5a064eb
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/FeedPreferenceSkipDialog.java
@@ -0,0 +1,48 @@
+package de.danoeh.antennapod.dialog;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.EditText;
+import androidx.appcompat.app.AlertDialog;
+import de.danoeh.antennapod.R;
+
+/**
+ * Displays a dialog with a username and password text field and an optional checkbox to save username and preferences.
+ */
+public abstract class FeedPreferenceSkipDialog extends AlertDialog.Builder {
+
+ public FeedPreferenceSkipDialog(Context context, int skipIntroInitialValue,
+ int skipEndInitialValue) {
+ super(context);
+ setTitle(R.string.pref_feed_skip);
+ View rootView = View.inflate(context, R.layout.feed_pref_skip_dialog, null);
+ setView(rootView);
+
+ final EditText etxtSkipIntro = rootView.findViewById(R.id.etxtSkipIntro);
+ final EditText etxtSkipEnd = rootView.findViewById(R.id.etxtSkipEnd);
+
+ etxtSkipIntro.setText(String.valueOf(skipIntroInitialValue));
+ etxtSkipEnd.setText(String.valueOf(skipEndInitialValue));
+
+ setNegativeButton(R.string.cancel_label, null);
+ setPositiveButton(R.string.confirm_label, (dialog, which)
+ -> {
+ int skipIntro;
+ int skipEnding;
+ try {
+ skipIntro = Integer.parseInt(etxtSkipIntro.getText().toString());
+ } catch (NumberFormatException e) {
+ skipIntro = 0;
+ }
+
+ try {
+ skipEnding = Integer.parseInt(etxtSkipEnd.getText().toString());
+ } catch (NumberFormatException e) {
+ skipEnding = 0;
+ }
+ onConfirmed(skipIntro, skipEnding);
+ });
+ }
+
+ protected abstract void onConfirmed(int skipIntro, int skipEndig);
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java
index 23b8b7f19..8251e8716 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedSettingsFragment.java
@@ -17,6 +17,7 @@ import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.SwitchPreference;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
+import de.danoeh.antennapod.core.event.settings.SkipIntroEndingChangedEvent;
import de.danoeh.antennapod.core.event.settings.SpeedPresetChangedEvent;
import de.danoeh.antennapod.core.event.settings.VolumeAdaptionChangedEvent;
import de.danoeh.antennapod.core.feed.Feed;
@@ -28,6 +29,7 @@ import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.dialog.AuthenticationDialog;
import de.danoeh.antennapod.dialog.EpisodeFilterDialog;
+import de.danoeh.antennapod.dialog.FeedPreferenceSkipDialog;
import io.reactivex.Maybe;
import io.reactivex.MaybeOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
@@ -99,6 +101,7 @@ public class FeedSettingsFragment extends Fragment {
private static final CharSequence PREF_EPISODE_FILTER = "episodeFilter";
private static final CharSequence PREF_SCREEN = "feedSettingsScreen";
private static final String PREF_FEED_PLAYBACK_SPEED = "feedPlaybackSpeed";
+ private static final String PREF_AUTO_SKIP = "feedAutoSkip";
private static final DecimalFormat SPEED_FORMAT =
new DecimalFormat("0.00", DecimalFormatSymbols.getInstance(Locale.US));
@@ -142,6 +145,7 @@ public class FeedSettingsFragment extends Fragment {
setupAuthentificationPreference();
setupEpisodeFilterPreference();
setupPlaybackSpeedPreference();
+ setupFeedAutoSkipPreference();
updateAutoDeleteSummary();
updateVolumeReductionValue();
@@ -159,6 +163,26 @@ public class FeedSettingsFragment extends Fragment {
}
}
+ private void setupFeedAutoSkipPreference() {
+ findPreference(PREF_AUTO_SKIP).setOnPreferenceClickListener(preference -> {
+ new FeedPreferenceSkipDialog(getContext(),
+ feedPreferences.getFeedSkipIntro(),
+ feedPreferences.getFeedSkipEnding()) {
+ @Override
+ protected void onConfirmed(int skipIntro, int skipEnding) {
+ feedPreferences.setFeedSkipIntro(skipIntro);
+ feedPreferences.setFeedSkipEnding(skipEnding);
+ feed.savePreferences();
+ EventBus.getDefault().post(
+ new SkipIntroEndingChangedEvent(feedPreferences.getFeedSkipIntro(),
+ feedPreferences.getFeedSkipEnding(),
+ feed.getId()));
+ }
+ }.show();
+ return false;
+ });
+ }
+
private void setupPlaybackSpeedPreference() {
ListPreference feedPlaybackSpeedPreference = findPreference(PREF_FEED_PLAYBACK_SPEED);
diff --git a/app/src/main/res/layout/external_player_fragment.xml b/app/src/main/res/layout/external_player_fragment.xml
index 7fb1296a9..dd8f7fe40 100644
--- a/app/src/main/res/layout/external_player_fragment.xml
+++ b/app/src/main/res/layout/external_player_fragment.xml
@@ -27,7 +27,8 @@
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:cropToPadding="true"
- android:scaleType="centerCrop"
+ android:maxWidth="96dp"
+ android:scaleType="fitCenter"
tools:src="@tools:sample/avatars"/>
diff --git a/app/src/main/res/layout/feed_item_list_fragment.xml b/app/src/main/res/layout/feed_item_list_fragment.xml
index e607ac216..38496dd4f 100644
--- a/app/src/main/res/layout/feed_item_list_fragment.xml
+++ b/app/src/main/res/layout/feed_item_list_fragment.xml
@@ -15,6 +15,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="?attr/colorPrimary"
+ app:scrimAnimationDuration="200"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
@@ -22,7 +23,7 @@
style="@style/BigBlurryBackground"
android:background="@color/image_readability_tint"
android:layout_width="match_parent"
- android:layout_height="256dp"
+ android:layout_height="232dp"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.6"/>
diff --git a/app/src/main/res/layout/feed_pref_skip_dialog.xml b/app/src/main/res/layout/feed_pref_skip_dialog.xml
new file mode 100644
index 000000000..db76a3426
--- /dev/null
+++ b/app/src/main/res/layout/feed_pref_skip_dialog.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/labelSkipIntro"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="24dp"
+ android:layout_marginRight="24dp"
+ android:text="@string/pref_feed_skip_intro" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <EditText
+ android:id="@+id/etxtSkipIntro"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="24dp"
+ android:autofillHints="@string/pref_feed_skip_intro"
+ android:cursorVisible="true"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:inputType="number"
+ android:maxLength="5"
+ android:minWidth="150dp"
+ android:text="30" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="24dp"
+ android:text="@string/time_seconds" />
+
+ </LinearLayout>
+
+ <TextView
+ android:id="@+id/labelSkipEnd"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="24dp"
+ android:layout_marginRight="24dp"
+ android:text="@string/pref_feed_skip_ending" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <EditText
+ android:id="@+id/etxtSkipEnd"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="24dp"
+ android:cursorVisible="true"
+ android:focusable="true"
+ android:autofillHints="@string/pref_feed_skip_ending"
+ android:focusableInTouchMode="true"
+ android:inputType="number"
+ android:maxLength="5"
+ android:minWidth="150dp"
+ android:text="30" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="8dp"
+ android:layout_marginRight="24dp"
+ android:text="@string/time_seconds" />
+ </LinearLayout>
+
+</LinearLayout>
diff --git a/app/src/main/res/layout/feedinfo.xml b/app/src/main/res/layout/feedinfo.xml
index e3efa72ce..d2e077be1 100644
--- a/app/src/main/res/layout/feedinfo.xml
+++ b/app/src/main/res/layout/feedinfo.xml
@@ -15,6 +15,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="?attr/colorPrimary"
+ app:scrimAnimationDuration="200"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
@@ -22,7 +23,7 @@
style="@style/BigBlurryBackground"
android:background="@color/image_readability_tint"
android:layout_width="match_parent"
- android:layout_height="256dp"
+ android:layout_height="232dp"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.6"/>
diff --git a/app/src/main/res/layout/nav_listitem.xml b/app/src/main/res/layout/nav_listitem.xml
index f03ebc09f..2b7bc5715 100644
--- a/app/src/main/res/layout/nav_listitem.xml
+++ b/app/src/main/res/layout/nav_listitem.xml
@@ -51,6 +51,8 @@
android:layout_toStartOf="@id/txtvCount"
android:layout_marginLeft="@dimen/list_vertical_padding"
android:layout_marginStart="@dimen/list_vertical_padding"
+ android:layout_marginRight="@dimen/list_vertical_padding"
+ android:layout_marginEnd="@dimen/list_vertical_padding"
android:layout_alignWithParentIfMissing="true"
android:lines="1"
android:text="{fa-exclamation-circle}"
diff --git a/app/src/main/res/xml/feed_settings.xml b/app/src/main/res/xml/feed_settings.xml
index a9effdeeb..9a3a4f438 100644
--- a/app/src/main/res/xml/feed_settings.xml
+++ b/app/src/main/res/xml/feed_settings.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:key="feedSettingsScreen">
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:key="feedSettingsScreen">
<SwitchPreference
android:key="keepUpdated"
@@ -21,6 +21,11 @@
android:title="@string/playback_speed"
android:summary="@string/pref_feed_playback_speed_sum"/>
+ <Preference
+ android:key="skipping"
+ android:summary="@string/pref_feed_skip_sum"
+ android:title="@string/pref_feed_skip" />
+
<ListPreference
android:entries="@array/spnAutoDeleteItems"
android:entryValues="@array/spnAutoDeleteValues"
diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/settings/SkipIntroEndingChangedEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/settings/SkipIntroEndingChangedEvent.java
new file mode 100644
index 000000000..583f7b13f
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/event/settings/SkipIntroEndingChangedEvent.java
@@ -0,0 +1,25 @@
+package de.danoeh.antennapod.core.event.settings;
+
+public class SkipIntroEndingChangedEvent {
+ private final int skipIntro;
+ private final int skipEnding;
+ private final long feedId;
+
+ public SkipIntroEndingChangedEvent(int skipIntro, int skipEnding, long feedId) {
+ this.skipIntro= skipIntro;
+ this.skipEnding = skipEnding;
+ this.feedId = feedId;
+ }
+
+ public int getSkipIntro() {
+ return skipIntro;
+ }
+
+ public int getSkipEnding() {
+ return skipEnding;
+ }
+
+ public long getFeedId() {
+ return feedId;
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java
index b24c52266..2a2568f28 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java
@@ -34,12 +34,18 @@ public class FeedPreferences {
private String username;
private String password;
private float feedPlaybackSpeed;
+ private int feedSkipIntro;
+ private int feedSkipEnding;
public FeedPreferences(long feedID, boolean autoDownload, AutoDeleteAction auto_delete_action, VolumeAdaptionSetting volumeAdaptionSetting, String username, String password) {
this(feedID, autoDownload, true, auto_delete_action, volumeAdaptionSetting, username, password, new FeedFilter(), SPEED_USE_GLOBAL);
}
private FeedPreferences(long feedID, boolean autoDownload, boolean keepUpdated, AutoDeleteAction auto_delete_action, VolumeAdaptionSetting volumeAdaptionSetting, String username, String password, @NonNull FeedFilter filter, float feedPlaybackSpeed) {
+ this(feedID, autoDownload, true, auto_delete_action, volumeAdaptionSetting, username, password, new FeedFilter(), feedPlaybackSpeed, 0, 0);
+ }
+
+ private FeedPreferences(long feedID, boolean autoDownload, boolean keepUpdated, AutoDeleteAction auto_delete_action, VolumeAdaptionSetting volumeAdaptionSetting, String username, String password, @NonNull FeedFilter filter, float feedPlaybackSpeed, int feedSkipIntro, int feedSkipEnding) {
this.feedID = feedID;
this.autoDownload = autoDownload;
this.keepUpdated = keepUpdated;
@@ -49,6 +55,8 @@ public class FeedPreferences {
this.password = password;
this.filter = filter;
this.feedPlaybackSpeed = feedPlaybackSpeed;
+ this.feedSkipIntro = feedSkipIntro;
+ this.feedSkipEnding = feedSkipEnding;
}
public static FeedPreferences fromCursor(Cursor cursor) {
@@ -62,6 +70,8 @@ public class FeedPreferences {
int indexIncludeFilter = cursor.getColumnIndex(PodDBAdapter.KEY_INCLUDE_FILTER);
int indexExcludeFilter = cursor.getColumnIndex(PodDBAdapter.KEY_EXCLUDE_FILTER);
int indexFeedPlaybackSpeed = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_PLAYBACK_SPEED);
+ int indexAutoSkipIntro = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_SKIP_INTRO);
+ int indexAutoSkipEnding = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_SKIP_ENDING);
long feedId = cursor.getLong(indexId);
boolean autoDownload = cursor.getInt(indexAutoDownload) > 0;
@@ -75,7 +85,20 @@ public class FeedPreferences {
String includeFilter = cursor.getString(indexIncludeFilter);
String excludeFilter = cursor.getString(indexExcludeFilter);
float feedPlaybackSpeed = cursor.getFloat(indexFeedPlaybackSpeed);
- return new FeedPreferences(feedId, autoDownload, autoRefresh, autoDeleteAction, volumeAdaptionSetting, username, password, new FeedFilter(includeFilter, excludeFilter), feedPlaybackSpeed);
+ int feedAutoSkipIntro = cursor.getInt(indexAutoSkipIntro);
+ int feedAutoSkipEnding = cursor.getInt(indexAutoSkipEnding);
+ return new FeedPreferences(feedId,
+ autoDownload,
+ autoRefresh,
+ autoDeleteAction,
+ volumeAdaptionSetting,
+ username,
+ password,
+ new FeedFilter(includeFilter, excludeFilter),
+ feedPlaybackSpeed,
+ feedAutoSkipIntro,
+ feedAutoSkipEnding
+ );
}
/**
@@ -204,4 +227,20 @@ public class FeedPreferences {
public void setFeedPlaybackSpeed(float playbackSpeed) {
feedPlaybackSpeed = playbackSpeed;
}
+
+ public void setFeedSkipIntro(int skipIntro) {
+ feedSkipIntro = skipIntro;
+ }
+
+ public int getFeedSkipIntro() {
+ return feedSkipIntro;
+ }
+
+ public void setFeedSkipEnding(int skipEnding) {
+ feedSkipEnding = skipEnding;
+ }
+
+ public int getFeedSkipEnding() {
+ return feedSkipEnding;
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java
index 246ab4e30..d0301db2f 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java
@@ -14,7 +14,7 @@ public class FastBlurTransformation extends BitmapTransformation {
private static final String TAG = FastBlurTransformation.class.getSimpleName();
- private static final int STACK_BLUR_RADIUS = 5;
+ private static final int STACK_BLUR_RADIUS = 10;
public FastBlurTransformation() {
super();
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
index 2679a93d4..a83e50506 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
@@ -51,12 +51,14 @@ import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.event.MessageEvent;
import de.danoeh.antennapod.core.event.PlaybackPositionEvent;
import de.danoeh.antennapod.core.event.ServiceEvent;
+import de.danoeh.antennapod.core.event.settings.SkipIntroEndingChangedEvent;
import de.danoeh.antennapod.core.event.settings.SpeedPresetChangedEvent;
import de.danoeh.antennapod.core.event.settings.VolumeAdaptionChangedEvent;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
+import de.danoeh.antennapod.core.feed.FeedPreferences;
import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
@@ -211,6 +213,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
private Disposable positionEventTimer;
private PlaybackServiceNotificationBuilder notificationBuilder;
+ private long autoSkippedFeedMediaId = -1;
+
/**
* Used for Lollipop notifications, Android Wear, and Android Auto.
*/
@@ -507,6 +511,30 @@ public class PlaybackService extends MediaBrowserServiceCompat {
return Service.START_NOT_STICKY;
}
+ private void skipIntro(Playable playable) {
+ if (! (playable instanceof FeedMedia)) {
+ return;
+ }
+
+ FeedMedia feedMedia = (FeedMedia) playable;
+ FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences();
+ int skipIntro = preferences.getFeedSkipIntro();
+
+ Context context = getApplicationContext();
+ if (skipIntro > 0 && playable.getPosition() < skipIntro * 1000) {
+ int duration = getDuration();
+ if (skipIntro * 1000 < duration) {
+ Log.d(TAG, "skipIntro " + playable.getEpisodeTitle());
+ mediaPlayer.seekTo(skipIntro * 1000);
+ String skipIntroMesg = context.getString(R.string.pref_feed_skip_intro_toast,
+ skipIntro);
+ Toast toast = Toast.makeText(context, skipIntroMesg,
+ Toast.LENGTH_LONG);
+ toast.show();
+ }
+ }
+ }
+
private void displayStreamingNotAllowedNotification(Intent originalIntent) {
Intent intentAllowThisTime = new Intent(originalIntent);
intentAllowThisTime.setAction(EXTRA_ALLOW_STREAM_THIS_TIME);
@@ -758,7 +786,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
case PLAYING:
PlaybackPreferences.writePlayerStatus(mediaPlayer.getPlayerStatus());
setupNotification(newInfo);
- setupPositionUpdater();
+ setupPositionObserver();
stateManager.validStartCommandWasReceived();
// set sleep timer if auto-enabled
if (newInfo.oldPlayerStatus != null && newInfo.oldPlayerStatus != PlayerStatus.SEEKING
@@ -849,6 +877,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
taskManager.startWidgetUpdater();
if (position != PlaybackServiceMediaPlayer.INVALID_TIME) {
playable.setPosition(position);
+ } else {
+ skipIntro(playable);
}
playable.onPlaybackStart();
taskManager.startPositionSaver();
@@ -1000,6 +1030,10 @@ public class PlaybackService extends MediaBrowserServiceCompat {
media.onPlaybackPause(getApplicationContext());
}
+ if (autoSkippedFeedMediaId >= 0 && autoSkippedFeedMediaId == media.getId()) {
+ ended = true;
+ }
+
if (item != null) {
if (ended || smartMarkAsPlayed
|| (skipped && !UserPreferences.shouldSkipKeepEpisode())) {
@@ -1040,6 +1074,33 @@ public class PlaybackService extends MediaBrowserServiceCompat {
sendBroadcast(intent);
}
+ private void skipEndingIfNecessary() {
+ Playable playable = mediaPlayer.getPlayable();
+ if (! (playable instanceof FeedMedia)) {
+ return;
+ }
+
+ int duration = getDuration();
+ int remainingTime = duration - getCurrentPosition();
+
+ FeedMedia feedMedia = (FeedMedia) playable;
+ FeedPreferences preferences = feedMedia.getItem().getFeed().getPreferences();
+ int skipEnd = preferences.getFeedSkipEnding();
+ if (skipEnd > 0
+ && skipEnd < playable.getDuration()
+ && (remainingTime - (skipEnd * 1000) > 0)
+ && ((remainingTime - skipEnd * 1000) < (getCurrentPlaybackSpeed() * 1000))) {
+ Log.d(TAG, "skipEndingIfNecessary: Skipping the remaining " + remainingTime + " " + skipEnd * 1000 + " speed " + getCurrentPlaybackSpeed());
+ Context context = getApplicationContext();
+ String skipMesg = context.getString(R.string.pref_feed_skip_ending_toast, skipEnd);
+ Toast toast = Toast.makeText(context, skipMesg, Toast.LENGTH_LONG);
+ toast.show();
+
+ this.autoSkippedFeedMediaId = feedMedia.getItem().getId();
+ mediaPlayer.skip();
+ }
+ }
+
/**
* Updates the Media Session for the corresponding status.
*
@@ -1451,12 +1512,14 @@ public class PlaybackService extends MediaBrowserServiceCompat {
};
@Subscribe(threadMode = ThreadMode.MAIN)
+ @SuppressWarnings("unused")
public void volumeAdaptionChanged(VolumeAdaptionChangedEvent event) {
PlaybackVolumeUpdater playbackVolumeUpdater = new PlaybackVolumeUpdater();
playbackVolumeUpdater.updateVolumeIfNecessary(mediaPlayer, event.getFeedId(), event.getVolumeAdaptionSetting());
}
@Subscribe(threadMode = ThreadMode.MAIN)
+ @SuppressWarnings("unused")
public void speedPresetChanged(SpeedPresetChangedEvent event) {
if (getPlayable() instanceof FeedMedia) {
if (((FeedMedia) getPlayable()).getItem().getFeed().getId() == event.getFeedId()) {
@@ -1469,6 +1532,22 @@ public class PlaybackService extends MediaBrowserServiceCompat {
}
}
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ @SuppressWarnings("unused")
+ public void skipIntroEndingPresetChanged(SkipIntroEndingChangedEvent event) {
+ if (getPlayable() instanceof FeedMedia) {
+ if (((FeedMedia) getPlayable()).getItem().getFeed().getId() == event.getFeedId()) {
+ if (event.getSkipEnding() != 0) {
+ FeedPreferences feedPreferences
+ = ((FeedMedia) getPlayable()).getItem().getFeed().getPreferences();
+ feedPreferences.setFeedSkipIntro(event.getSkipIntro());
+ feedPreferences.setFeedSkipEnding(event.getSkipEnding());
+
+ }
+ }
+ }
+ }
+
public static MediaType getCurrentMediaType() {
return currentMediaType;
}
@@ -1613,7 +1692,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
return mediaPlayer.getVideoSize();
}
- private void setupPositionUpdater() {
+ private void setupPositionObserver() {
if (positionEventTimer != null) {
positionEventTimer.dispose();
}
@@ -1629,6 +1708,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
}
+ skipEndingIfNecessary();
});
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java
index ee31c8cc4..8574ff33b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBUpgrader.java
@@ -304,6 +304,12 @@ class DBUpgrader {
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS
+ " ADD COLUMN " + PodDBAdapter.KEY_IMAGE_URL + " TEXT DEFAULT NULL");
}
+ if (oldVersion < 1090001) {
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS +
+ " ADD COLUMN " + PodDBAdapter.KEY_FEED_SKIP_INTRO + " INTEGER DEFAULT 0;");
+ db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS +
+ " ADD COLUMN " + PodDBAdapter.KEY_FEED_SKIP_ENDING + " INTEGER DEFAULT 0;");
+ }
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
index 6ca3419cf..e6d47b32a 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
@@ -47,7 +47,7 @@ public class PodDBAdapter {
private static final String TAG = "PodDBAdapter";
public static final String DATABASE_NAME = "Antennapod.db";
- public static final int VERSION = 1090000;
+ public static final int VERSION = 1090001;
/**
* Maximum number of arguments for IN-operator.
@@ -109,6 +109,8 @@ public class PodDBAdapter {
public static final String KEY_INCLUDE_FILTER = "include_filter";
public static final String KEY_EXCLUDE_FILTER = "exclude_filter";
public static final String KEY_FEED_PLAYBACK_SPEED = "feed_playback_speed";
+ public static final String KEY_FEED_SKIP_INTRO = "feed_skip_intro";
+ public static final String KEY_FEED_SKIP_ENDING = "feed_skip_ending";
// Table names
static final String TABLE_NAME_FEEDS = "Feeds";
@@ -144,7 +146,9 @@ public class PodDBAdapter {
+ KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0,"
+ KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0,"
+ KEY_FEED_PLAYBACK_SPEED + " REAL DEFAULT " + SPEED_USE_GLOBAL + ","
- + KEY_FEED_VOLUME_ADAPTION + " INTEGER DEFAULT 0)";
+ + KEY_FEED_VOLUME_ADAPTION + " INTEGER DEFAULT 0,"
+ + KEY_FEED_SKIP_INTRO + " INTEGER DEFAULT 0,"
+ + KEY_FEED_SKIP_ENDING + " INTEGER DEFAULT 0)";
private static final String CREATE_TABLE_FEED_ITEMS = "CREATE TABLE "
+ TABLE_NAME_FEED_ITEMS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE
@@ -244,7 +248,9 @@ public class PodDBAdapter {
TABLE_NAME_FEEDS + "." + KEY_FEED_VOLUME_ADAPTION,
TABLE_NAME_FEEDS + "." + KEY_INCLUDE_FILTER,
TABLE_NAME_FEEDS + "." + KEY_EXCLUDE_FILTER,
- TABLE_NAME_FEEDS + "." + KEY_FEED_PLAYBACK_SPEED
+ TABLE_NAME_FEEDS + "." + KEY_FEED_PLAYBACK_SPEED,
+ TABLE_NAME_FEEDS + "." + KEY_FEED_SKIP_INTRO,
+ TABLE_NAME_FEEDS + "." + KEY_FEED_SKIP_ENDING
};
/**
@@ -421,6 +427,8 @@ public class PodDBAdapter {
values.put(KEY_INCLUDE_FILTER, prefs.getFilter().getIncludeFilter());
values.put(KEY_EXCLUDE_FILTER, prefs.getFilter().getExcludeFilter());
values.put(KEY_FEED_PLAYBACK_SPEED, prefs.getFeedPlaybackSpeed());
+ values.put(KEY_FEED_SKIP_INTRO, prefs.getFeedSkipIntro());
+ values.put(KEY_FEED_SKIP_ENDING, prefs.getFeedSkipEnding());
db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(prefs.getFeedID())});
}
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index efd7d698a..7b011159b 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -116,7 +116,9 @@
<item quantity="one">1 day after finishing</item>
<item quantity="other">%d days after finishing</item>
</plurals>
- <string name="num_selected_label">%d selected</string>
+ <plurals name="num_selected_label">
+ <item quantity="other">%d selected</item>
+ </plurals>
<string name="loading_more">Loading moreā€¦</string>
<!-- Actions on feeds -->
@@ -444,6 +446,12 @@
<string name="pref_playback_speed_title">Playback Speeds</string>
<string name="pref_playback_speed_sum">Customize the speeds available for variable speed audio playback</string>
<string name="pref_feed_playback_speed_sum">The speed to use when starting audio playback for episodes in this podcast</string>
+ <string name="pref_feed_skip">Auto Skip</string>
+ <string name="pref_feed_skip_sum">Skip introductions and ending credits.</string>
+ <string name="pref_feed_skip_ending">Skip last</string>
+ <string name="pref_feed_skip_intro">Skip first</string>
+ <string name="pref_feed_skip_ending_toast">Skipped last %d seconds</string>
+ <string name="pref_feed_skip_intro_toast">Skipped first %d seconds</string>
<string name="pref_playback_time_respects_speed_title">Adjust media info to playback speed</string>
<string name="pref_playback_time_respects_speed_sum">Displayed position and duration are adapted to playback speed</string>
<string name="pref_fast_forward">Fast Forward Skip Time</string>