summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/build.gradle6
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/export/favorites/FavoritesWriter.java15
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/glide/ResizingOkHttpStreamFetcher.java5
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java48
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java9
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java9
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java75
-rw-r--r--core/src/main/res/values/strings.xml4
-rw-r--r--core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java5
9 files changed, 86 insertions, 90 deletions
diff --git a/core/build.gradle b/core/build.gradle
index 32899cb5d..700487701 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -39,10 +39,10 @@ dependencies {
implementation 'androidx.documentfile:documentfile:1.0.1'
implementation "androidx.fragment:fragment:$fragmentVersion"
implementation "androidx.media:media:$mediaVersion"
+ implementation "androidx.palette:palette:$paletteVersion"
implementation "androidx.preference:preference:$preferenceVersion"
implementation "androidx.work:work-runtime:$workManagerVersion"
implementation "com.google.android.material:material:$googleMaterialVersion"
- implementation 'androidx.palette:palette:1.0.0'
implementation "org.apache.commons:commons-lang3:$commonslangVersion"
implementation "commons-io:commons-io:$commonsioVersion"
@@ -69,9 +69,9 @@ dependencies {
testImplementation 'androidx.test:core:1.2.0'
testImplementation "org.awaitility:awaitility:$awaitilityVersion"
- testImplementation 'junit:junit:4.13'
+ testImplementation "junit:junit:$junitVersion"
testImplementation 'org.mockito:mockito-inline:3.5.13'
- testImplementation 'org.robolectric:robolectric:4.5-alpha-1'
+ testImplementation "org.robolectric:robolectric:$robolectricVersion"
testImplementation 'javax.inject:javax.inject:1'
androidTestImplementation "com.jayway.android.robotium:robotium-solo:$robotiumSoloVersion"
androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion"
diff --git a/core/src/main/java/de/danoeh/antennapod/core/export/favorites/FavoritesWriter.java b/core/src/main/java/de/danoeh/antennapod/core/export/favorites/FavoritesWriter.java
index 9bc273c9e..29de6ca80 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/export/favorites/FavoritesWriter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/export/favorites/FavoritesWriter.java
@@ -117,10 +117,17 @@ public class FavoritesWriter implements ExportWriter {
}
private void writeFavoriteItem(Writer writer, FeedItem item, String favoriteTemplate) throws IOException {
- String favItem = favoriteTemplate
- .replace("{FAV_TITLE}", item.getTitle().trim())
- .replace("{FAV_WEBSITE}", item.getLink())
- .replace("{FAV_MEDIA}", item.getMedia().getDownload_url());
+ String favItem = favoriteTemplate.replace("{FAV_TITLE}", item.getTitle().trim());
+ if (item.getLink() != null) {
+ favItem = favItem.replace("{FAV_WEBSITE}", item.getLink());
+ } else {
+ favItem = favItem.replace("{FAV_WEBSITE}", "");
+ }
+ if (item.getMedia() != null && item.getMedia().getDownload_url() != null) {
+ favItem = favItem.replace("{FAV_MEDIA}", item.getMedia().getDownload_url());
+ } else {
+ favItem = favItem.replace("{FAV_MEDIA}", "");
+ }
writer.append(favItem);
}
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
index 11e2f944e..1871723bb 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/glide/ResizingOkHttpStreamFetcher.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ResizingOkHttpStreamFetcher.java
@@ -3,12 +3,13 @@ package de.danoeh.antennapod.core.glide;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
+import android.util.Log;
+
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;
@@ -22,7 +23,7 @@ import java.io.InputStream;
import java.io.OutputStream;
public class ResizingOkHttpStreamFetcher extends OkHttpStreamFetcher {
- private static final String TAG = "ResizingOkHttpStreamFetcher";
+ private static final String TAG = "ResizingOkHttpStreamFet";
private static final int MAX_DIMENSIONS = 1500;
private static final int MAX_FILE_SIZE = 1024 * 1024; // 1 MB
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java
index 7ce06a9fb..d4008b3f2 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java
@@ -12,20 +12,21 @@ import com.google.android.exoplayer2.DefaultLoadControl;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.Format;
+import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SeekParameters;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.audio.AudioAttributes;
-import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSourceFactory;
+import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSource;
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
+import com.google.android.exoplayer2.trackselection.ExoTrackSelection;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector;
-import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.ui.DefaultTrackNameProvider;
import com.google.android.exoplayer2.ui.TrackNameProvider;
@@ -48,6 +49,7 @@ import org.antennapod.audio.MediaPlayer;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -88,12 +90,12 @@ public class ExoPlayerWrapper implements IPlayer {
trackSelector = new DefaultTrackSelector(context);
exoPlayer = new SimpleExoPlayer.Builder(context, new DefaultRenderersFactory(context))
.setTrackSelector(trackSelector)
- .setLoadControl(loadControl.createDefaultLoadControl())
+ .setLoadControl(loadControl.build())
.build();
exoPlayer.setSeekParameters(SeekParameters.EXACT);
- exoPlayer.addListener(new Player.EventListener() {
+ exoPlayer.addListener(new Player.Listener() {
@Override
- public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
+ public void onPlaybackStateChanged(@Player.State int playbackState) {
if (audioCompletionListener != null && playbackState == Player.STATE_ENDED) {
audioCompletionListener.onCompletion(null);
} else if (infoListener != null && playbackState == Player.STATE_BUFFERING) {
@@ -119,8 +121,10 @@ public class ExoPlayerWrapper implements IPlayer {
}
@Override
- public void onSeekProcessed() {
- if (audioSeekCompleteListener != null) {
+ public void onPositionDiscontinuity(@NonNull Player.PositionInfo oldPosition,
+ @NonNull Player.PositionInfo newPosition,
+ @Player.DiscontinuityReason int reason) {
+ if (audioSeekCompleteListener != null && reason == Player.DISCONTINUITY_REASON_SEEK) {
audioSeekCompleteListener.onSeekComplete(null);
}
}
@@ -157,12 +161,13 @@ public class ExoPlayerWrapper implements IPlayer {
@Override
public void pause() {
- exoPlayer.setPlayWhenReady(false);
+ exoPlayer.pause();
}
@Override
public void prepare() throws IllegalStateException {
- exoPlayer.prepare(mediaSource, false, true);
+ exoPlayer.setMediaSource(mediaSource, false);
+ exoPlayer.prepare();
}
@Override
@@ -198,25 +203,31 @@ public class ExoPlayerWrapper implements IPlayer {
b.setContentType(i);
b.setFlags(a.flags);
b.setUsage(a.usage);
- exoPlayer.setAudioAttributes(b.build());
+ exoPlayer.setAudioAttributes(b.build(), false);
}
public void setDataSource(String s, String user, String password)
throws IllegalArgumentException, IllegalStateException {
Log.d(TAG, "setDataSource: " + s);
- OkHttpDataSourceFactory httpDataSourceFactory = new OkHttpDataSourceFactory(
- AntennapodHttpClient.getHttpClient(), ClientConfig.USER_AGENT);
+ final OkHttpDataSource.Factory httpDataSourceFactory =
+ new OkHttpDataSource.Factory(AntennapodHttpClient.getHttpClient())
+ .setUserAgent(ClientConfig.USER_AGENT);
if (!TextUtils.isEmpty(user) && !TextUtils.isEmpty(password)) {
- httpDataSourceFactory.getDefaultRequestProperties().set("Authorization",
- HttpDownloader.encodeCredentials(user, password, "ISO-8859-1"));
+ final HashMap<String, String> requestProperties = new HashMap<>();
+ requestProperties.put(
+ "Authorization",
+ HttpDownloader.encodeCredentials(user, password, "ISO-8859-1")
+ );
+ httpDataSourceFactory.setDefaultRequestProperties(requestProperties);
}
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context, null, httpDataSourceFactory);
DefaultExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
extractorsFactory.setConstantBitrateSeekingEnabled(true);
extractorsFactory.setMp3ExtractorFlags(Mp3Extractor.FLAG_DISABLE_ID3_METADATA);
ProgressiveMediaSource.Factory f = new ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory);
- mediaSource = f.createMediaSource(Uri.parse(s));
+ final MediaItem mediaItem = MediaItem.fromUri(Uri.parse(s));
+ mediaSource = f.createMediaSource(mediaItem);
}
@Override
@@ -231,7 +242,8 @@ public class ExoPlayerWrapper implements IPlayer {
@Override
public void setPlaybackParams(float speed, boolean skipSilence) {
- playbackParameters = new PlaybackParameters(speed, playbackParameters.pitch, skipSilence);
+ playbackParameters = new PlaybackParameters(speed, playbackParameters.pitch);
+ exoPlayer.setSkipSilenceEnabled(skipSilence);
exoPlayer.setPlaybackParameters(playbackParameters);
}
@@ -252,7 +264,7 @@ public class ExoPlayerWrapper implements IPlayer {
@Override
public void start() {
- exoPlayer.setPlayWhenReady(true);
+ exoPlayer.play();
// Can't set params when paused - so always set it on start in case they changed
exoPlayer.setPlaybackParameters(playbackParameters);
}
@@ -312,7 +324,7 @@ public class ExoPlayerWrapper implements IPlayer {
TrackSelectionArray trackSelections = exoPlayer.getCurrentTrackSelections();
List<Format> availableFormats = getFormats();
for (int i = 0; i < trackSelections.length; i++) {
- TrackSelection track = trackSelections.get(i);
+ ExoTrackSelection track = (ExoTrackSelection) trackSelections.get(i);
if (track == null) {
continue;
}
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 d5e0140d0..22378e01a 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
@@ -1231,7 +1231,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
| PlaybackStateCompat.ACTION_PAUSE
| PlaybackStateCompat.ACTION_FAST_FORWARD
| PlaybackStateCompat.ACTION_SKIP_TO_NEXT
- | PlaybackStateCompat.ACTION_SEEK_TO;
+ | PlaybackStateCompat.ACTION_SEEK_TO
+ | PlaybackStateCompat.ACTION_SET_PLAYBACK_SPEED;
if (useSkipToPreviousForRewindInLockscreen()) {
// Workaround to fool Android so that Lockscreen will expose a skip-to-previous button,
@@ -1888,6 +1889,12 @@ public class PlaybackService extends MediaBrowserServiceCompat {
}
@Override
+ public void onSetPlaybackSpeed(float speed) {
+ Log.d(TAG, "onSetPlaybackSpeed()");
+ setSpeed(speed);
+ }
+
+ @Override
public boolean onMediaButtonEvent(final Intent mediaButton) {
Log.d(TAG, "onMediaButtonEvent(" + mediaButton + ")");
if (mediaButton != null) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
index 0e996c6c8..fdaab745e 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
@@ -149,7 +149,6 @@ public class DBWriter {
*/
public static Future<?> deleteFeed(final Context context, final long feedId) {
return dbExec.submit(() -> {
- DownloadRequester requester = DownloadRequester.getInstance();
final Feed feed = DBReader.getFeed(feedId);
if (feed == null) {
return;
@@ -167,7 +166,9 @@ public class DBWriter {
adapter.removeFeed(feed);
adapter.close();
- SynchronizationQueueSink.enqueueFeedRemovedIfSynchronizationIsActive(context, feed.getDownload_url());
+ if (!feed.isLocalFeed()) {
+ SynchronizationQueueSink.enqueueFeedRemovedIfSynchronizationIsActive(context, feed.getDownload_url());
+ }
EventBus.getDefault().post(new FeedListUpdateEvent(feed));
});
}
@@ -779,7 +780,9 @@ public class DBWriter {
adapter.close();
for (Feed feed : feeds) {
- SynchronizationQueueSink.enqueueFeedAddedIfSynchronizationIsActive(context, feed.getDownload_url());
+ if (!feed.isLocalFeed()) {
+ SynchronizationQueueSink.enqueueFeedAddedIfSynchronizationIsActive(context, feed.getDownload_url());
+ }
}
BackupManager backupManager = new BackupManager(context);
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 719e546b5..b7e221a33 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
@@ -44,8 +44,6 @@ import de.danoeh.antennapod.model.feed.SortOrder;
import static de.danoeh.antennapod.model.feed.FeedPreferences.SPEED_USE_GLOBAL;
import static de.danoeh.antennapod.model.feed.SortOrder.toCodeString;
-// TODO Remove media column from feeditem table
-
/**
* Implements methods for accessing the database
*/
@@ -842,43 +840,32 @@ public class PodDBAdapter {
db.delete(TABLE_NAME_QUEUE, null, null);
}
- private void removeFeedMedia(FeedMedia media) {
- // delete download log entries for feed media
- db.delete(TABLE_NAME_DOWNLOAD_LOG, KEY_FEEDFILE + "=? AND " + KEY_FEEDFILETYPE + "=?",
- new String[]{String.valueOf(media.getId()), String.valueOf(FeedMedia.FEEDFILETYPE_FEEDMEDIA)});
-
- db.delete(TABLE_NAME_FEED_MEDIA, KEY_ID + "=?",
- new String[]{String.valueOf(media.getId())});
- }
-
- private void removeChaptersOfItem(FeedItem item) {
- db.delete(TABLE_NAME_SIMPLECHAPTERS, KEY_FEEDITEM + "=?",
- new String[]{String.valueOf(item.getId())});
- }
-
- /**
- * Remove a FeedItem and its FeedMedia entry.
- */
- private void removeFeedItem(FeedItem item) {
- if (item.getMedia() != null) {
- removeFeedMedia(item.getMedia());
- }
- if (item.hasChapters() || item.getChapters() != null) {
- removeChaptersOfItem(item);
- }
- db.delete(TABLE_NAME_FEED_ITEMS, KEY_ID + "=?",
- new String[]{String.valueOf(item.getId())});
- }
-
/**
* Remove the listed items and their FeedMedia entries.
*/
public void removeFeedItems(@NonNull List<FeedItem> items) {
try {
- db.beginTransactionNonExclusive();
+ StringBuilder mediaIds = new StringBuilder();
+ StringBuilder itemIds = new StringBuilder();
for (FeedItem item : items) {
- removeFeedItem(item);
+ if (item.getMedia() != null) {
+ if (mediaIds.length() != 0) {
+ mediaIds.append(",");
+ }
+ mediaIds.append(item.getMedia().getId());
+ }
+ if (itemIds.length() != 0) {
+ itemIds.append(",");
+ }
+ itemIds.append(item.getId());
}
+
+ db.beginTransactionNonExclusive();
+ db.delete(TABLE_NAME_SIMPLECHAPTERS, KEY_FEEDITEM + " IN (" + itemIds + ")", null);
+ db.delete(TABLE_NAME_DOWNLOAD_LOG, KEY_FEEDFILETYPE + "=" + FeedMedia.FEEDFILETYPE_FEEDMEDIA
+ + " AND " + KEY_FEEDFILE + " IN (" + mediaIds + ")", null);
+ db.delete(TABLE_NAME_FEED_MEDIA, KEY_ID + " IN (" + mediaIds + ")", null);
+ db.delete(TABLE_NAME_FEED_ITEMS, KEY_ID + " IN (" + itemIds + ")", null);
db.setTransactionSuccessful();
} catch (SQLException e) {
Log.e(TAG, Log.getStackTraceString(e));
@@ -894,9 +881,7 @@ public class PodDBAdapter {
try {
db.beginTransactionNonExclusive();
if (feed.getItems() != null) {
- for (FeedItem item : feed.getItems()) {
- removeFeedItem(item);
- }
+ removeFeedItems(feed.getItems());
}
// delete download log entries for feed
db.delete(TABLE_NAME_DOWNLOAD_LOG, KEY_FEEDFILE + "=? AND " + KEY_FEEDFILETYPE + "=?",
@@ -1359,25 +1344,7 @@ public class PodDBAdapter {
}
/**
- * Select number of items, new items, the date of the latest episode and the number of episodes in progress. The result
- * is sorted by the title of the feed.
- */
- private static final String FEED_STATISTICS_QUERY = "SELECT Feeds.id, num_items, new_items, latest_episode, in_progress FROM " +
- " Feeds LEFT JOIN " +
- "(SELECT feed,count(*) AS num_items," +
- " COUNT(CASE WHEN read=0 THEN 1 END) AS new_items," +
- " MAX(pubDate) AS latest_episode," +
- " COUNT(CASE WHEN position>0 THEN 1 END) AS in_progress," +
- " COUNT(CASE WHEN downloaded=1 THEN 1 END) AS episodes_downloaded " +
- " FROM FeedItems LEFT JOIN FeedMedia ON FeedItems.id=FeedMedia.feeditem GROUP BY FeedItems.feed)" +
- " ON Feeds.id = feed ORDER BY Feeds.title COLLATE NOCASE ASC;";
-
- public Cursor getFeedStatisticsCursor() {
- return db.rawQuery(FEED_STATISTICS_QUERY, null);
- }
-
- /**
- * Insert raw data to the database. *
+ * Insert raw data to the database.
* Call method only for unit tests.
*/
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index 86b3443f3..22607f58b 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -202,8 +202,8 @@
<string name="delete_failed">Unable to delete file. Rebooting the device could help.</string>
<string name="delete_episode_label">Delete Episode</string>
<plurals name="deleted_multi_episode_batch_label">
- <item quantity="one">%d episode selected, %d download deleted.</item>
- <item quantity="other">%d episodes selected, %d download(s) deleted.</item>
+ <item quantity="one">1 downloaded episode deleted.</item>
+ <item quantity="other">%d downloaded episodes deleted.</item>
</plurals>
<string name="remove_new_flag_label">Remove \"new\" flag</string>
<string name="removed_new_flag_label">Removed \"new\" flag</string>
diff --git a/core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java b/core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java
index f70ed6e29..5e73773db 100644
--- a/core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java
+++ b/core/src/test/java/de/danoeh/antennapod/core/storage/DbWriterTest.java
@@ -188,14 +188,13 @@ public class DbWriterTest {
assertTrue(queue.size() != 0);
DBWriter.deleteFeedMediaOfItem(context, media.getId());
- Awaitility.await().until(() -> !dest.exists());
+ Awaitility.await().timeout(2, TimeUnit.SECONDS).until(() -> !dest.exists());
media = DBReader.getFeedMedia(media.getId());
assertNotNull(media);
assertFalse(dest.exists());
assertFalse(media.isDownloaded());
assertNull(media.getFile_url());
- queue = DBReader.getQueue();
- assertEquals(0, queue.size());
+ Awaitility.await().timeout(2, TimeUnit.SECONDS).until(() -> DBReader.getQueue().isEmpty());
}
@Test