summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/ResizingOkHttpStreamFetcher.java132
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java8
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java38
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java8
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java24
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java12
-rw-r--r--core/src/main/res/values/styles.xml2
-rw-r--r--core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java8
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/util/URLCheckerTest.java16
11 files changed, 206 insertions, 49 deletions
diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java
index 8c80e9151..a0ec16578 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java
@@ -4,7 +4,6 @@ import android.content.ContentResolver;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.bumptech.glide.integration.okhttp3.OkHttpStreamFetcher;
import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.load.model.ModelLoader;
@@ -77,7 +76,7 @@ class ApOkHttpUrlLoader implements ModelLoader<String, InputStream> {
@Nullable
@Override
public LoadData<InputStream> buildLoadData(@NonNull String model, int width, int height, @NonNull Options options) {
- return new LoadData<>(new ObjectKey(model), new OkHttpStreamFetcher(client, new GlideUrl(model)));
+ return new LoadData<>(new ObjectKey(model), new ResizingOkHttpStreamFetcher(client, new GlideUrl(model)));
}
@Override
diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ResizingOkHttpStreamFetcher.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ResizingOkHttpStreamFetcher.java
new file mode 100644
index 000000000..7b8eed6e0
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ResizingOkHttpStreamFetcher.java
@@ -0,0 +1,132 @@
+package de.danoeh.antennapod.core.glide;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.os.Build;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import com.bumptech.glide.Priority;
+import com.bumptech.glide.integration.okhttp3.OkHttpStreamFetcher;
+import com.bumptech.glide.load.model.GlideUrl;
+import com.google.android.exoplayer2.util.Log;
+import okhttp3.Call;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class ResizingOkHttpStreamFetcher extends OkHttpStreamFetcher {
+ private static final String TAG = "ResizingOkHttpStreamFetcher";
+ private static final int MAX_DIMENSIONS = 2000;
+ private static final int MAX_FILE_SIZE = 1024 * 1024; // 1 MB
+
+ private FileInputStream stream;
+ private File tempIn;
+ private File tempOut;
+
+ public ResizingOkHttpStreamFetcher(Call.Factory client, GlideUrl url) {
+ super(client, url);
+ }
+
+ @Override
+ public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super InputStream> callback) {
+ super.loadData(priority, new DataCallback<InputStream>() {
+ @Override
+ public void onDataReady(@Nullable InputStream data) {
+ if (data == null) {
+ callback.onDataReady(null);
+ return;
+ }
+ try {
+ tempIn = File.createTempFile("resize_", null);
+ tempOut = File.createTempFile("resize_", null);
+ OutputStream outputStream = new FileOutputStream(tempIn);
+ IOUtils.copy(data, outputStream);
+ outputStream.close();
+ IOUtils.closeQuietly(data);
+
+ if (tempIn.length() <= MAX_FILE_SIZE) {
+ try {
+ stream = new FileInputStream(tempIn);
+ callback.onDataReady(stream); // Just deliver the original, non-scaled image
+ } catch (FileNotFoundException fileNotFoundException) {
+ callback.onLoadFailed(fileNotFoundException);
+ }
+ return;
+ }
+
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ FileInputStream in = new FileInputStream(tempIn);
+ BitmapFactory.decodeStream(in, null, options);
+ IOUtils.closeQuietly(in);
+
+ if (Math.max(options.outHeight, options.outWidth) >= MAX_DIMENSIONS) {
+ double sampleSize = (double) Math.max(options.outHeight, options.outWidth) / MAX_DIMENSIONS;
+ options.inSampleSize = (int) Math.pow(2d, Math.floor(Math.log(sampleSize) / Math.log(2d)));
+ }
+
+ options.inJustDecodeBounds = false;
+ in = new FileInputStream(tempIn);
+ Bitmap bitmap = BitmapFactory.decodeStream(in, null, options);
+ IOUtils.closeQuietly(in);
+
+ Bitmap.CompressFormat format = Build.VERSION.SDK_INT < 30
+ ? Bitmap.CompressFormat.WEBP : Bitmap.CompressFormat.WEBP_LOSSY;
+
+ int quality = 100;
+ while (true) {
+ FileOutputStream out = new FileOutputStream(tempOut);
+ bitmap.compress(format, quality, out);
+ IOUtils.closeQuietly(out);
+
+ if (tempOut.length() > 3 * MAX_FILE_SIZE && quality >= 45) {
+ quality -= 40;
+ } else if (tempOut.length() > 2 * MAX_FILE_SIZE && quality >= 25) {
+ quality -= 20;
+ } else if (tempOut.length() > MAX_FILE_SIZE && quality >= 15) {
+ quality -= 10;
+ } else if (tempOut.length() > MAX_FILE_SIZE && quality >= 10) {
+ quality -= 5;
+ } else {
+ break;
+ }
+ }
+
+ stream = new FileInputStream(tempOut);
+ callback.onDataReady(stream);
+ Log.d(TAG, "Compressed image from " + tempIn.length() / 1024
+ + " to " + tempOut.length() / 1024 + " kB (quality: " + quality + "%)");
+ } catch (Exception e) {
+ e.printStackTrace();
+
+ try {
+ stream = new FileInputStream(tempIn);
+ callback.onDataReady(stream); // Just deliver the original, non-scaled image
+ } catch (FileNotFoundException fileNotFoundException) {
+ e.printStackTrace();
+ callback.onLoadFailed(fileNotFoundException);
+ }
+ }
+ }
+
+ @Override
+ public void onLoadFailed(@NonNull Exception e) {
+ callback.onLoadFailed(e);
+ }
+ });
+ }
+
+ @Override
+ public void cleanup() {
+ IOUtils.closeQuietly(stream);
+ FileUtils.deleteQuietly(tempIn);
+ FileUtils.deleteQuietly(tempOut);
+ super.cleanup();
+ }
+}
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 3016b96d5..f74e3b9ad 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
@@ -947,14 +947,10 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
// is an episode in the queue left.
// Start playback immediately if continuous playback is enabled
nextMedia = callback.getNextInQueue(currentMedia);
-
- boolean playNextEpisode = isPlaying &&
- nextMedia != null &&
- UserPreferences.isFollowQueue();
-
+ boolean playNextEpisode = isPlaying && nextMedia != null;
if (playNextEpisode) {
Log.d(TAG, "Playback of next episode will start immediately.");
- } else if (nextMedia == null){
+ } else if (nextMedia == null) {
Log.d(TAG, "No more episodes available to play");
} else {
Log.d(TAG, "Loading next episode, but not playing automatically.");
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 423fd9bfe..a54f0679d 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
@@ -751,7 +751,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
mediaPlayer.playMediaObject(playable, PlaybackPreferences.getCurrentEpisodeIsStream(),
true, true);
stateManager.validStartCommandWasReceived();
- PlaybackService.this.updateMediaSessionMetadata(playable);
+ updateNotificationAndMediaSession(playable);
addPlayableToQueue(playable);
}, error -> {
Log.d(TAG, "Playable was not loaded from preferences. Stopping service.");
@@ -772,7 +772,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
public void notifyVideoSurfaceAbandoned() {
mediaPlayer.pause(true, false);
mediaPlayer.resetVideoSurface();
- setupNotification(getPlayable());
+ updateNotificationAndMediaSession(getPlayable());
stateManager.stopForeground(!UserPreferences.isPersistNotify());
}
@@ -828,7 +828,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
case INITIALIZED:
PlaybackPreferences.writeMediaPlaying(mediaPlayer.getPSMPInfo().playable,
mediaPlayer.getPSMPInfo().playerStatus, mediaPlayer.isStreaming());
- setupNotification(newInfo);
+ updateNotificationAndMediaSession(newInfo.playable);
break;
case PREPARED:
taskManager.startChapterLoader(newInfo.playable);
@@ -838,7 +838,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
// do not remove notification on pause based on user pref and whether android version supports expanded notifications
// Change [Play] button to [Pause]
- setupNotification(newInfo);
+ updateNotificationAndMediaSession(newInfo.playable);
} else if (!UserPreferences.isPersistNotify() && !isCasting) {
// remove notification on pause
stateManager.stopForeground(true);
@@ -852,7 +852,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
break;
case PLAYING:
PlaybackPreferences.writePlayerStatus(mediaPlayer.getPlayerStatus());
- setupNotification(newInfo);
+ updateNotificationAndMediaSession(newInfo.playable);
setupPositionObserver();
stateManager.validStartCommandWasReceived();
// set sleep timer if auto-enabled
@@ -880,7 +880,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
@Override
public void shouldStop() {
- setupNotification(getPlayable()); // Stops foreground if not playing
+ updateNotificationAndMediaSession(getPlayable()); // Stops foreground if not playing
}
@Override
@@ -899,7 +899,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
if (reloadUI) {
sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, 0);
}
- PlaybackService.this.updateMediaSessionMetadata(getPlayable());
+ updateNotificationAndMediaSession(getPlayable());
}
@Override
@@ -917,8 +917,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
// Playable is being streamed and does not have a duration specified in the feed
playable.setDuration(mediaPlayer.getDuration());
DBWriter.setFeedMedia((FeedMedia) playable);
- updateMediaSessionMetadata(playable);
- setupNotification(playable);
+ updateNotificationAndMediaSession(playable);
}
return true;
@@ -1012,6 +1011,12 @@ public class PlaybackService extends MediaBrowserServiceCompat {
return null;
}
+ if (!UserPreferences.isFollowQueue()) {
+ Log.d(TAG, "getNextInQueue(), but follow queue is not enabled.");
+ updateNotificationAndMediaSession(nextItem.getMedia());
+ return null;
+ }
+
if (!nextItem.getMedia().localFileAvailable() && !NetworkUtils.isStreamingAllowed()
&& UserPreferences.isFollowQueue() && !nextItem.getFeed().isLocalFeed()) {
displayStreamingNotAllowedNotification(
@@ -1285,6 +1290,11 @@ public class PlaybackService extends MediaBrowserServiceCompat {
(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP));
}
+ private void updateNotificationAndMediaSession(final Playable p) {
+ updateMediaSessionMetadata(p);
+ setupNotification(p);
+ }
+
private void updateMediaSessionMetadata(final Playable p) {
if (p == null || mediaSession == null) {
return;
@@ -1326,10 +1336,6 @@ public class PlaybackService extends MediaBrowserServiceCompat {
/**
* Prepares notification and starts the service in the foreground.
*/
- private void setupNotification(final PlaybackServiceMediaPlayer.PSMPInfo info) {
- setupNotification(info.playable);
- }
-
private synchronized void setupNotification(final Playable playable) {
Log.d(TAG, "setupNotification");
if (playableIconLoaderThread != null) {
@@ -1910,7 +1916,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
private final SharedPreferences.OnSharedPreferenceChangeListener prefListener =
(sharedPreferences, key) -> {
if (UserPreferences.PREF_LOCKSCREEN_BACKGROUND.equals(key)) {
- updateMediaSessionMetadata(getPlayable());
+ updateNotificationAndMediaSession(getPlayable());
} else {
flavorHelper.onSharedPreference(key);
}
@@ -1973,7 +1979,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
@Override
public void setupNotification(boolean connected, PlaybackServiceMediaPlayer.PSMPInfo info) {
if (connected) {
- PlaybackService.this.setupNotification(info);
+ PlaybackService.this.updateNotificationAndMediaSession(info.playable);
} else {
PlayerStatus status = info.playerStatus;
if ((status == PlayerStatus.PLAYING ||
@@ -1981,7 +1987,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
status == PlayerStatus.PREPARING ||
UserPreferences.isPersistNotify()) &&
android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- PlaybackService.this.setupNotification(info);
+ PlaybackService.this.updateNotificationAndMediaSession(info.playable);
} else if (!UserPreferences.isPersistNotify()) {
stateManager.stopForeground(true);
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java
index 348ffaa60..3dba0735d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSMedia.java
@@ -47,8 +47,8 @@ public class NSMedia extends Namespace {
String medium = attributes.getValue(MEDIUM);
boolean validTypeMedia = false;
boolean validTypeImage = false;
-
boolean isDefault = "true".equals(defaultStr);
+ String guessedType = SyndTypeUtils.getMimeTypeFromUrl(url);
if (MEDIUM_AUDIO.equals(medium)) {
validTypeMedia = true;
@@ -56,12 +56,14 @@ public class NSMedia extends Namespace {
} else if (MEDIUM_VIDEO.equals(medium)) {
validTypeMedia = true;
type = "video/*";
- } else if (MEDIUM_IMAGE.equals(medium)) {
+ } else if (MEDIUM_IMAGE.equals(medium) && (guessedType == null
+ || (!guessedType.startsWith("audio/") && !guessedType.startsWith("video/")))) {
+ // Apparently, some publishers explicitly specify the audio file as an image
validTypeImage = true;
type = "image/*";
} else {
if (type == null) {
- type = SyndTypeUtils.getMimeTypeFromUrl(url);
+ type = guessedType;
}
if (SyndTypeUtils.enclosureTypeValid(type)) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java b/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java
index cb7db1709..1ac068307 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/URLChecker.java
@@ -5,9 +5,10 @@ import android.text.TextUtils;
import androidx.annotation.NonNull;
import android.util.Log;
-import de.danoeh.antennapod.core.BuildConfig;
import okhttp3.HttpUrl;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
@@ -28,6 +29,7 @@ public final class URLChecker {
private static final String TAG = "URLChecker";
private static final String AP_SUBSCRIBE = "antennapod-subscribe://";
+ private static final String AP_SUBSCRIBE_DEEPLINK = "antennapod.org/deeplink/subscribe?url=";
/**
* Checks if URL is valid and modifies it if necessary.
@@ -39,22 +41,30 @@ public final class URLChecker {
url = url.trim();
String lowerCaseUrl = url.toLowerCase(); // protocol names are case insensitive
if (lowerCaseUrl.startsWith("feed://")) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Replacing feed:// with http://");
+ Log.d(TAG, "Replacing feed:// with http://");
return prepareURL(url.substring("feed://".length()));
} else if (lowerCaseUrl.startsWith("pcast://")) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Removing pcast://");
+ Log.d(TAG, "Removing pcast://");
return prepareURL(url.substring("pcast://".length()));
} else if (lowerCaseUrl.startsWith("pcast:")) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Removing pcast:");
+ Log.d(TAG, "Removing pcast:");
return prepareURL(url.substring("pcast:".length()));
} else if (lowerCaseUrl.startsWith("itpc")) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Replacing itpc:// with http://");
+ Log.d(TAG, "Replacing itpc:// with http://");
return prepareURL(url.substring("itpc://".length()));
} else if (lowerCaseUrl.startsWith(AP_SUBSCRIBE)) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Removing antennapod-subscribe://");
+ Log.d(TAG, "Removing antennapod-subscribe://");
return prepareURL(url.substring(AP_SUBSCRIBE.length()));
+ } else if (lowerCaseUrl.contains(AP_SUBSCRIBE_DEEPLINK)) {
+ Log.d(TAG, "Removing " + AP_SUBSCRIBE_DEEPLINK);
+ String removedWebsite = url.substring(url.indexOf(AP_SUBSCRIBE_DEEPLINK) + AP_SUBSCRIBE_DEEPLINK.length());
+ try {
+ return prepareURL(URLDecoder.decode(removedWebsite, "UTF-8"));
+ } catch (UnsupportedEncodingException e) {
+ return prepareURL(removedWebsite);
+ }
} else if (!(lowerCaseUrl.startsWith("http://") || lowerCaseUrl.startsWith("https://"))) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Adding http:// at the beginning of the URL");
+ Log.d(TAG, "Adding http:// at the beginning of the URL");
return "http://" + url;
} else {
return url;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java
index 17313ca14..b8ec3524b 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/id3reader/ID3Reader.java
@@ -96,6 +96,10 @@ public class ID3Reader {
short version = readShort();
byte flags = readByte();
int size = unsynchsafe(readInt());
+ if ((flags & 0b01000000) != 0) {
+ int extendedHeaderSize = readInt();
+ skipBytes(extendedHeaderSize - 4);
+ }
return new TagHeader("ID3", size, version, flags);
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
index cd69147a6..7f4c1ceaf 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
@@ -274,13 +274,13 @@ public abstract class PlaybackController {
*/
private void handleStatus() {
Log.d(TAG, "status: " + status.toString());
+ checkMediaInfoLoaded();
switch (status) {
case ERROR:
EventBus.getDefault().post(new MessageEvent(activity.getString(R.string.player_error_msg)));
handleError(MediaPlayer.MEDIA_ERROR_UNKNOWN);
break;
case PAUSED:
- checkMediaInfoLoaded();
onPositionObserverUpdate();
updatePlayButtonShowsPlay(true);
if (!PlaybackService.isCasting() && PlaybackService.getCurrentMediaType() == MediaType.VIDEO) {
@@ -288,7 +288,6 @@ public abstract class PlaybackController {
}
break;
case PLAYING:
- checkMediaInfoLoaded();
if (!PlaybackService.isCasting() && PlaybackService.getCurrentMediaType() == MediaType.VIDEO) {
onAwaitingVideoSurface();
setScreenOn(true);
@@ -296,26 +295,23 @@ public abstract class PlaybackController {
updatePlayButtonShowsPlay(false);
break;
case PREPARING:
- checkMediaInfoLoaded();
if (playbackService != null) {
updatePlayButtonShowsPlay(!playbackService.isStartWhenPrepared());
}
break;
- case STOPPED:
- updatePlayButtonShowsPlay(true);
- break;
case PREPARED:
- checkMediaInfoLoaded();
updatePlayButtonShowsPlay(true);
onPositionObserverUpdate();
break;
case SEEKING:
onPositionObserverUpdate();
break;
+ case STOPPED: // Fall-through
case INITIALIZED:
- checkMediaInfoLoaded();
updatePlayButtonShowsPlay(true);
break;
+ default:
+ break;
}
}
diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml
index 33ff270b8..8c15d35c0 100644
--- a/core/src/main/res/values/styles.xml
+++ b/core/src/main/res/values/styles.xml
@@ -32,6 +32,7 @@
<item name="icon_green">#008537</item>
<item name="icon_purple">#5F1984</item>
<item name="icon_gray">#25365A</item>
+ <item name="android:splitMotionEvents">false</item>
</style>
<style name="Theme.AntennaPod.Dark" parent="Theme.Base.AntennaPod.Dark">
@@ -66,6 +67,7 @@
<item name="icon_green">#008537</item>
<item name="icon_purple">#AA55D8</item>
<item name="icon_gray">#CDD9E4</item>
+ <item name="android:splitMotionEvents">false</item>
</style>
<style name="Theme.AntennaPod.TrueBlack" parent="Theme.Base.AntennaPod.TrueBlack">
diff --git a/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java b/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java
index 9fd99f236..38b469e8e 100644
--- a/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java
+++ b/core/src/play/java/de/danoeh/antennapod/core/service/playback/RemotePSMP.java
@@ -32,7 +32,6 @@ import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.model.playback.RemoteMedia;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.model.playback.MediaType;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.util.RewindAfterPauseUtils;
import de.danoeh.antennapod.model.playback.Playable;
@@ -367,8 +366,6 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer {
@Override
public void resume() {
try {
- // TODO see comment on prepare()
- // setVolume(UserPreferences.getLeftVolume(), UserPreferences.getRightVolume());
if (playerStatus == PlayerStatus.PREPARED && media.getPosition() > 0) {
int newPosition = RewindAfterPauseUtils.calculatePositionWithRewind(
media.getPosition(),
@@ -405,9 +402,6 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer {
position,
media.getLastPlayedTime());
}
- // TODO We're not supporting user set stream volume yet, as we need to make a UI
- // that doesn't allow changing playback speed or have different values for left/right
- //setVolume(UserPreferences.getLeftVolume(), UserPreferences.getRightVolume());
castMgr.loadMedia(remoteMedia, startWhenPrepared.get(), position);
} catch (TransientNetworkDisconnectionException | NoConnectionException e) {
Log.e(TAG, "Error loading media", e);
@@ -629,7 +623,7 @@ public class RemotePSMP extends PlaybackServiceMediaPlayer {
if (shouldContinue) {
nextMedia = callback.getNextInQueue(currentMedia);
- boolean playNextEpisode = isPlaying && nextMedia != null && UserPreferences.isFollowQueue();
+ boolean playNextEpisode = isPlaying && nextMedia != null;
if (playNextEpisode) {
Log.d(TAG, "Playback of next episode will start immediately.");
} else if (nextMedia == null){
diff --git a/core/src/test/java/de/danoeh/antennapod/core/util/URLCheckerTest.java b/core/src/test/java/de/danoeh/antennapod/core/util/URLCheckerTest.java
index a4b3dee06..c20398ffc 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/util/URLCheckerTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/util/URLCheckerTest.java
@@ -4,6 +4,9 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -99,6 +102,19 @@ public class URLCheckerTest {
}
@Test
+ public void testAntennaPodSubscribeDeeplink() throws UnsupportedEncodingException {
+ final String feed = "http://example.org/podcast.rss";
+ assertEquals(feed, URLChecker.prepareURL("https://antennapod.org/deeplink/subscribe?url=" + feed));
+ assertEquals(feed, URLChecker.prepareURL("http://antennapod.org/deeplink/subscribe?url=" + feed));
+ assertEquals(feed, URLChecker.prepareURL("https://www.antennapod.org/deeplink/subscribe?url=" + feed));
+ assertEquals(feed, URLChecker.prepareURL("http://www.antennapod.org/deeplink/subscribe?url=" + feed));
+ assertEquals(feed, URLChecker.prepareURL("http://www.antennapod.org/deeplink/subscribe?url="
+ + URLEncoder.encode(feed, "UTF-8")));
+ assertEquals(feed, URLChecker.prepareURL("http://www.antennapod.org/deeplink/subscribe?url="
+ + "example.org/podcast.rss"));
+ }
+
+ @Test
public void testProtocolRelativeUrlIsAbsolute() {
final String in = "https://example.com";
final String inBase = "http://examplebase.com";