diff options
author | ByteHamster <info@bytehamster.com> | 2020-10-25 19:33:21 +0100 |
---|---|---|
committer | ByteHamster <info@bytehamster.com> | 2020-10-25 19:33:21 +0100 |
commit | 679e4829997d886a07fe3361fd9d917db16061d2 (patch) | |
tree | a6de6275fa337e69651e370135e750bbadf901a1 /core/src | |
parent | caaf2c72db2220c84ce24b60853c5fe6a5874b18 (diff) | |
parent | 71b6c57773d1af6e6df967bba968e08cb0268335 (diff) | |
download | AntennaPod-679e4829997d886a07fe3361fd9d917db16061d2.zip |
Merge branch 'develop' into add-local-feeds
Diffstat (limited to 'core/src')
11 files changed, 205 insertions, 108 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/ChapterMerger.java b/core/src/main/java/de/danoeh/antennapod/core/feed/ChapterMerger.java new file mode 100644 index 000000000..f33fa7511 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/ChapterMerger.java @@ -0,0 +1,55 @@ +package de.danoeh.antennapod.core.feed; + +import android.text.TextUtils; +import android.util.Log; +import androidx.annotation.Nullable; + +import java.util.List; + +public class ChapterMerger { + private static final String TAG = "ChapterMerger"; + + private ChapterMerger() { + + } + + /** + * This method might modify the input data. + */ + @Nullable + public static List<Chapter> merge(@Nullable List<Chapter> chapters1, @Nullable List<Chapter> chapters2) { + Log.d(TAG, "Merging chapters"); + if (chapters1 == null) { + return chapters2; + } else if (chapters2 == null) { + return chapters1; + } else if (chapters2.size() > chapters1.size()) { + return chapters2; + } else if (chapters2.size() < chapters1.size()) { + return chapters1; + } else { + // Merge chapter lists of same length. Store in chapters2 array. + // In case the lists can not be merged, return chapters1 array. + for (int i = 0; i < chapters2.size(); i++) { + Chapter chapterTarget = chapters2.get(i); + Chapter chapterOther = chapters1.get(i); + + if (Math.abs(chapterTarget.start - chapterOther.start) > 1000) { + Log.e(TAG, "Chapter lists are too different. Cancelling merge."); + return chapters1; + } + + if (TextUtils.isEmpty(chapterTarget.imageUrl)) { + chapterTarget.imageUrl = chapterOther.imageUrl; + } + if (TextUtils.isEmpty(chapterTarget.link)) { + chapterTarget.link = chapterOther.link; + } + if (TextUtils.isEmpty(chapterTarget.title)) { + chapterTarget.title = chapterOther.title; + } + } + return chapters2; + } + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index 92e45376a..88945b930 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -11,6 +11,7 @@ import androidx.annotation.Nullable; import android.support.v4.media.MediaBrowserCompat; import android.support.v4.media.MediaDescriptionCompat; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.concurrent.Callable; @@ -383,19 +384,30 @@ public class FeedMedia extends FeedFile implements Playable { if (item == null || item.getChapters() != null) { return; } - // check if chapters are stored in db and not loaded yet. + + List<Chapter> chapters = loadChapters(context); + if (chapters == null) { + // Do not try loading again. There are no chapters. + item.setChapters(Collections.emptyList()); + } else { + item.setChapters(chapters); + } + } + + private List<Chapter> loadChapters(Context context) { + List<Chapter> chaptersFromDatabase = null; if (item.hasChapters()) { - DBReader.loadChaptersOfFeedItem(item); + chaptersFromDatabase = DBReader.loadChaptersOfFeedItem(item); + } + + List<Chapter> chaptersFromMediaFile; + if (localFileAvailable()) { + chaptersFromMediaFile = ChapterUtils.loadChaptersFromFileUrl(this); } else { - if (localFileAvailable()) { - ChapterUtils.loadChaptersFromFileUrl(this); - } else { - ChapterUtils.loadChaptersFromStreamUrl(this, context); - } - if (item.getChapters() != null) { - DBWriter.setFeedItem(item); - } + chaptersFromMediaFile = ChapterUtils.loadChaptersFromStreamUrl(this, context); } + + return ChapterMerger.merge(chaptersFromDatabase, chaptersFromMediaFile); } @Override diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index 1dc4b6093..56dd95fe6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -4,7 +4,6 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.res.Configuration; import android.os.Build; -import androidx.preference.PreferenceManager; import android.text.TextUtils; import android.util.Log; @@ -12,6 +11,7 @@ import androidx.annotation.IntRange; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.core.app.NotificationCompat; +import androidx.preference.PreferenceManager; import org.json.JSONArray; import org.json.JSONException; @@ -23,7 +23,7 @@ import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; +import java.util.Calendar; import java.util.HashSet; import java.util.List; import java.util.Locale; @@ -115,6 +115,7 @@ public class UserPreferences { private static final String PREF_DATA_FOLDER = "prefDataFolder"; public static final String PREF_IMAGE_CACHE_SIZE = "prefImageCacheSize"; public static final String PREF_DELETE_REMOVES_FROM_QUEUE = "prefDeleteRemovesFromQueue"; + public static final String PREF_USAGE_COUNTING_DATE = "prefUsageCounting"; // Mediaplayer public static final String PREF_MEDIA_PLAYER = "prefMediaPlayer"; @@ -1056,4 +1057,19 @@ public class UserPreferences { .apply(); } + public static long getUsageCountingDateMillis() { + return prefs.getLong(PREF_USAGE_COUNTING_DATE, -1); + } + + private static void setUsageCountingDateMillis(long value) { + prefs.edit().putLong(PREF_USAGE_COUNTING_DATE, value).apply(); + } + + public static void resetUsageCountingDate() { + setUsageCountingDateMillis(Calendar.getInstance().getTimeInMillis()); + } + + public static void unsetUsageCountingDate() { + setUsageCountingDateMillis(-1); + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java index 9e2b69810..501214399 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/handler/MediaDownloadedHandler.java @@ -56,7 +56,7 @@ public class MediaDownloadedHandler implements Runnable { // check if file has chapters if (media.getItem() != null && !media.getItem().hasChapters()) { - ChapterUtils.loadChaptersFromFileUrl(media); + media.setChapters(ChapterUtils.loadChaptersFromFileUrl(media)); } // Get duration diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java index fbdc9a52b..ae5d62872 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java @@ -2,9 +2,7 @@ package de.danoeh.antennapod.core.service.playback; import android.content.Context; import android.media.AudioAttributes; -import android.media.AudioFocusRequest; import android.media.AudioManager; -import android.os.Build; import android.os.PowerManager; import androidx.annotation.NonNull; import android.telephony.TelephonyManager; @@ -12,11 +10,13 @@ import android.util.Log; import android.util.Pair; import android.view.SurfaceHolder; +import androidx.media.AudioAttributesCompat; +import androidx.media.AudioFocusRequestCompat; +import androidx.media.AudioManagerCompat; import org.antennapod.audio.MediaPlayer; import java.io.File; import java.io.IOException; -import java.util.EnumSet; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Future; @@ -57,6 +57,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { private final AtomicBoolean startWhenPrepared; private volatile boolean pausedBecauseOfTransientAudiofocusLoss; private volatile Pair<Integer, Integer> videoSize; + private final AudioFocusRequestCompat audioFocusRequest; /** * Some asynchronous calls might change the state of the MediaPlayer object. Therefore calls in other threads @@ -154,6 +155,16 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { pausedBecauseOfTransientAudiofocusLoss = false; mediaType = MediaType.UNKNOWN; videoSize = null; + + AudioAttributesCompat audioAttributes = new AudioAttributesCompat.Builder() + .setUsage(AudioAttributesCompat.USAGE_MEDIA) + .setContentType(AudioAttributesCompat.CONTENT_TYPE_SPEECH) + .build(); + audioFocusRequest = new AudioFocusRequestCompat.Builder(AudioManagerCompat.AUDIOFOCUS_GAIN) + .setAudioAttributes(audioAttributes) + .setOnAudioFocusChangeListener(audioFocusChangeListener) + .setWillPauseWhenDucked(true) + .build(); } /** @@ -287,25 +298,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { private void resumeSync() { if (playerStatus == PlayerStatus.PAUSED || playerStatus == PlayerStatus.PREPARED) { - int focusGained; - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - AudioAttributes audioAttributes = new AudioAttributes.Builder() - .setUsage(AudioAttributes.USAGE_MEDIA) - .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) - .build(); - AudioFocusRequest audioFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) - .setAudioAttributes(audioAttributes) - .setOnAudioFocusChangeListener(audioFocusChangeListener) - .setAcceptsDelayedFocusGain(true) - .setWillPauseWhenDucked(true) - .build(); - focusGained = audioManager.requestAudioFocus(audioFocusRequest); - } else { - focusGained = audioManager.requestAudioFocus( - audioFocusChangeListener, AudioManager.STREAM_MUSIC, - AudioManager.AUDIOFOCUS_GAIN); - } + int focusGained = AudioManagerCompat.requestAudioFocus(audioManager, audioFocusRequest); if (focusGained == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { Log.d(TAG, "Audiofocus successfully requested"); @@ -373,13 +366,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { } private void abandonAudioFocus() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - AudioFocusRequest.Builder builder = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN) - .setOnAudioFocusChangeListener(audioFocusChangeListener); - audioManager.abandonAudioFocusRequest(builder.build()); - } else { - audioManager.abandonAudioFocus(audioFocusChangeListener); - } + AudioManagerCompat.abandonAudioFocusRequest(audioManager, audioFocusRequest); } /** 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 9f53c6da0..25c301ccc 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 @@ -504,16 +504,27 @@ public class PlaybackService extends MediaBrowserServiceCompat { stateManager.stopService(); return Service.START_NOT_STICKY; } - if (playable instanceof FeedMedia) { - playable = DBReader.getFeedMedia(((FeedMedia) playable).getId()); - } - if (playable == null) { - Log.d(TAG, "Playable was not found. Stopping service."); - stateManager.stopService(); - return Service.START_NOT_STICKY; - } - mediaPlayer.playMediaObject(playable, stream, startWhenPrepared, prepareImmediately); - addPlayableToQueue(playable); + + Observable.fromCallable( + () -> { + if (playable instanceof FeedMedia) { + return DBReader.getFeedMedia(((FeedMedia) playable).getId()); + } else { + return playable; + } + }) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + playableLoaded -> { + mediaPlayer.playMediaObject(playable, stream, startWhenPrepared, + prepareImmediately); + addPlayableToQueue(playable); + }, error -> { + Log.d(TAG, "Playable was not found. Stopping service."); + stateManager.stopService(); + }); + return Service.START_NOT_STICKY; } else { Log.d(TAG, "Did not handle intent to PlaybackService: " + intent); Log.d(TAG, "Extras: " + intent.getExtras()); @@ -582,7 +593,7 @@ public class PlaybackService extends MediaBrowserServiceCompat { .setPriority(NotificationCompat.PRIORITY_DEFAULT) .setContentIntent(pendingIntentAllowThisTime) .addAction(R.drawable.ic_stream_white, - getString(R.string.stream_label), + getString(R.string.confirm_mobile_streaming_button_once), pendingIntentAllowThisTime) .addAction(R.drawable.ic_stream_white, getString(R.string.confirm_mobile_streaming_button_always), @@ -682,27 +693,33 @@ public class PlaybackService extends MediaBrowserServiceCompat { } private void startPlayingFromPreferences() { - Playable playable = Playable.PlayableUtils.createInstanceFromPreferences(getApplicationContext()); - if (playable != null) { - boolean localFeed = URLUtil.isContentUrl(playable.getStreamUrl()); - if (PlaybackPreferences.getCurrentEpisodeIsStream() && !NetworkUtils.isStreamingAllowed() && !localFeed) { - displayStreamingNotAllowedNotification( - new PlaybackServiceStarter(this, playable) - .prepareImmediately(true) - .startWhenPrepared(true) - .shouldStream(true) - .getIntent()); - PlaybackPreferences.writeNoMediaPlaying(); - stateManager.stopService(); - return; - } - mediaPlayer.playMediaObject(playable, PlaybackPreferences.getCurrentEpisodeIsStream(), true, true); - stateManager.validStartCommandWasReceived(); - PlaybackService.this.updateMediaSessionMetadata(playable); - addPlayableToQueue(playable); - } else { - stateManager.stopService(); - } + Observable.fromCallable(() -> Playable.PlayableUtils.createInstanceFromPreferences(getApplicationContext())) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + playable -> { + boolean localFeed = URLUtil.isContentUrl(playable.getStreamUrl()); + if (PlaybackPreferences.getCurrentEpisodeIsStream() + && !NetworkUtils.isStreamingAllowed() && !localFeed) { + displayStreamingNotAllowedNotification( + new PlaybackServiceStarter(this, playable) + .prepareImmediately(true) + .startWhenPrepared(true) + .shouldStream(true) + .getIntent()); + PlaybackPreferences.writeNoMediaPlaying(); + stateManager.stopService(); + return; + } + mediaPlayer.playMediaObject(playable, PlaybackPreferences.getCurrentEpisodeIsStream(), + true, true); + stateManager.validStartCommandWasReceived(); + PlaybackService.this.updateMediaSessionMetadata(playable); + addPlayableToQueue(playable); + }, error -> { + Log.d(TAG, "Playable was not loaded from preferences. Stopping service."); + stateManager.stopService(); + }); } /** diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 892254507..b218a73f9 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -651,29 +651,30 @@ public final class DBReader { * * @param item The FeedItem */ - public static void loadChaptersOfFeedItem(final FeedItem item) { + public static List<Chapter> loadChaptersOfFeedItem(final FeedItem item) { Log.d(TAG, "loadChaptersOfFeedItem() called with: " + "item = [" + item + "]"); PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); try { - loadChaptersOfFeedItem(adapter, item); + return loadChaptersOfFeedItem(adapter, item); } finally { adapter.close(); } } - private static void loadChaptersOfFeedItem(PodDBAdapter adapter, FeedItem item) { + private static List<Chapter> loadChaptersOfFeedItem(PodDBAdapter adapter, FeedItem item) { try (Cursor cursor = adapter.getSimpleChaptersOfFeedItemCursor(item)) { int chaptersCount = cursor.getCount(); if (chaptersCount == 0) { item.setChapters(null); - return; + return null; } - item.setChapters(new ArrayList<>(chaptersCount)); + ArrayList<Chapter> chapters = new ArrayList<>(); while (cursor.moveToNext()) { - item.getChapters().add(Chapter.fromCursor(cursor)); + chapters.add(Chapter.fromCursor(cursor)); } + return chapters; } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java index 859666464..d4a2cdca6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/ChapterUtils.java @@ -52,32 +52,34 @@ public class ChapterUtils { return chapters.size() - 1; } - public static void loadChaptersFromStreamUrl(Playable media, Context context) { - ChapterUtils.readID3ChaptersFromPlayableStreamUrl(media, context); - if (media.getChapters() == null) { - ChapterUtils.readOggChaptersFromPlayableStreamUrl(media, context); + public static List<Chapter> loadChaptersFromStreamUrl(Playable media, Context context) { + List<Chapter> chapters = ChapterUtils.readID3ChaptersFromPlayableStreamUrl(media, context); + if (chapters == null) { + chapters = ChapterUtils.readOggChaptersFromPlayableStreamUrl(media, context); } + return chapters; } - public static void loadChaptersFromFileUrl(Playable media) { + public static List<Chapter> loadChaptersFromFileUrl(Playable media) { if (!media.localFileAvailable()) { Log.e(TAG, "Could not load chapters from file url: local file not available"); - return; + return null; } - ChapterUtils.readID3ChaptersFromPlayableFileUrl(media); - if (media.getChapters() == null) { - ChapterUtils.readOggChaptersFromPlayableFileUrl(media); + List<Chapter> chapters = ChapterUtils.readID3ChaptersFromPlayableFileUrl(media); + if (chapters == null) { + chapters = ChapterUtils.readOggChaptersFromPlayableFileUrl(media); } + return chapters; } /** * Uses the download URL of a media object of a feeditem to read its ID3 * chapters. */ - private static void readID3ChaptersFromPlayableStreamUrl(Playable p, Context context) { + private static List<Chapter> readID3ChaptersFromPlayableStreamUrl(Playable p, Context context) { if (p == null || p.getStreamUrl() == null) { Log.e(TAG, "Unable to read ID3 chapters: media or download URL was null"); - return; + return null; } Log.d(TAG, "Reading id3 chapters from item " + p.getEpisodeTitle()); CountingInputStream in = null; @@ -93,7 +95,7 @@ public class ChapterUtils { } List<Chapter> chapters = readChaptersFrom(in); if (!chapters.isEmpty()) { - p.setChapters(chapters); + return chapters; } Log.i(TAG, "Chapters loaded"); } catch (IOException | ID3ReaderException | IllegalArgumentException e) { @@ -101,21 +103,22 @@ public class ChapterUtils { } finally { IOUtils.closeQuietly(in); } + return null; } /** * Uses the file URL of a media object of a feeditem to read its ID3 * chapters. */ - private static void readID3ChaptersFromPlayableFileUrl(Playable p) { + private static List<Chapter> readID3ChaptersFromPlayableFileUrl(Playable p) { if (p == null || !p.localFileAvailable() || p.getLocalMediaUrl() == null) { - return; + return null; } Log.d(TAG, "Reading id3 chapters from item " + p.getEpisodeTitle()); File source = new File(p.getLocalMediaUrl()); if (!source.exists()) { Log.e(TAG, "Unable to read id3 chapters: Source doesn't exist"); - return; + return null; } CountingInputStream in = null; @@ -123,7 +126,7 @@ public class ChapterUtils { in = new CountingInputStream(new BufferedInputStream(new FileInputStream(source))); List<Chapter> chapters = readChaptersFrom(in); if (!chapters.isEmpty()) { - p.setChapters(chapters); + return chapters; } Log.i(TAG, "Chapters loaded"); } catch (IOException | ID3ReaderException e) { @@ -131,6 +134,7 @@ public class ChapterUtils { } finally { IOUtils.closeQuietly(in); } + return null; } @NonNull @@ -152,9 +156,9 @@ public class ChapterUtils { return chapters; } - private static void readOggChaptersFromPlayableStreamUrl(Playable media, Context context) { + private static List<Chapter> readOggChaptersFromPlayableStreamUrl(Playable media, Context context) { if (media == null || !media.streamAvailable()) { - return; + return null; } InputStream input = null; try { @@ -168,34 +172,36 @@ public class ChapterUtils { input = urlConnection.getInputStream(); } if (input != null) { - readOggChaptersFromInputStream(media, input); + return readOggChaptersFromInputStream(media, input); } } catch (IOException | IllegalArgumentException e) { Log.e(TAG, Log.getStackTraceString(e)); } finally { IOUtils.closeQuietly(input); } + return null; } - private static void readOggChaptersFromPlayableFileUrl(Playable media) { + private static List<Chapter> readOggChaptersFromPlayableFileUrl(Playable media) { if (media == null || media.getLocalMediaUrl() == null) { - return; + return null; } File source = new File(media.getLocalMediaUrl()); if (source.exists()) { InputStream input = null; try { input = new BufferedInputStream(new FileInputStream(source)); - readOggChaptersFromInputStream(media, input); + return readOggChaptersFromInputStream(media, input); } catch (FileNotFoundException e) { Log.e(TAG, Log.getStackTraceString(e)); } finally { IOUtils.closeQuietly(input); } } + return null; } - private static void readOggChaptersFromInputStream(Playable p, InputStream input) { + private static List<Chapter> readOggChaptersFromInputStream(Playable p, InputStream input) { Log.d(TAG, "Trying to read chapters from item with title " + p.getEpisodeTitle()); try { VorbisCommentChapterReader reader = new VorbisCommentChapterReader(); @@ -203,19 +209,20 @@ public class ChapterUtils { List<Chapter> chapters = reader.getChapters(); if (chapters == null) { Log.i(TAG, "ChapterReader could not find any Ogg vorbis chapters"); - return; + return null; } Collections.sort(chapters, new ChapterStartTimeComparator()); enumerateEmptyChapterTitles(chapters); if (chaptersValid(chapters)) { - p.setChapters(chapters); Log.i(TAG, "Chapters loaded"); + return chapters; } else { Log.e(TAG, "Chapter data was invalid"); } } catch (VorbisCommentReaderException e) { e.printStackTrace(); } + return null; } /** diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java index 81937b62e..6c107996f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java @@ -99,7 +99,7 @@ public class ExternalMedia implements Playable { e.printStackTrace(); throw new PlayableException("NumberFormatException when reading duration of media file"); } - ChapterUtils.loadChaptersFromFileUrl(this); + setChapters(ChapterUtils.loadChaptersFromFileUrl(this)); } @Override diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/RemoteMedia.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/RemoteMedia.java index 669279294..29eb20aca 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/RemoteMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/RemoteMedia.java @@ -130,7 +130,7 @@ public class RemoteMedia implements Playable { @Override public void loadChapterMarks(Context context) { - ChapterUtils.loadChaptersFromStreamUrl(this, context); + setChapters(ChapterUtils.loadChaptersFromStreamUrl(this, context)); } @Override diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 30f64b35f..542b90120 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -41,6 +41,7 @@ <string name="statistics_speed_not_counted">Notice: Playback speed is never taken into account.</string> <string name="statistics_reset_data">Reset statistics data</string> <string name="statistics_reset_data_msg">This will erase the history of duration played for all episodes. Are you sure you want to proceed?</string> + <string name="statistics_counting_since">Since %s,\nyou played</string> <!-- Download Statistics fragment --> <string name="total_size_downloaded_podcasts">Total size of episodes on the device:</string> @@ -269,7 +270,8 @@ <string name="confirm_mobile_download_dialog_message">Downloading over mobile data connection is disabled in the settings.\n\nDo you want to allow downloading temporarily?\n\n<small>Your choice will be remembered for 10 minutes.</small></string> <string name="confirm_mobile_streaming_notification_title">Confirm Mobile streaming</string> <string name="confirm_mobile_streaming_notification_message">Streaming over mobile data connection is disabled in the settings. Tap to stream anyway.</string> - <string name="confirm_mobile_streaming_button_always">Always allow</string> + <string name="confirm_mobile_streaming_button_always">Always</string> + <string name="confirm_mobile_streaming_button_once">Once</string> <string name="confirm_mobile_download_dialog_only_add_to_queue">Enqueue</string> <string name="confirm_mobile_download_dialog_enable_temporarily">Allow temporarily</string> |