From 7702c9ee8c6ef23afd71270ad4126de37eeb7dfb Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Mon, 20 Jan 2020 00:34:12 +0100 Subject: Convert playback speeds to float Advantage: When setting the speed to a value that is not available for the button using the audio controls dialog, we no longer jump to the lowest value. Instead, we jump to the next bigger one. --- .../core/preferences/UserPreferences.java | 30 ++++++++++------------ 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'core/src/main/java/de') 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 4f871e83b..1ba981d27 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 @@ -389,7 +389,7 @@ public class UserPreferences { return Float.parseFloat(prefs.getString(PREF_PLAYBACK_SPEED, "1.00")); } catch (NumberFormatException e) { Log.e(TAG, Log.getStackTraceString(e)); - UserPreferences.setPlaybackSpeed("1.00"); + UserPreferences.setPlaybackSpeed(1.0f); return 1.0f; } } @@ -399,7 +399,7 @@ public class UserPreferences { return Float.parseFloat(prefs.getString(PREF_VIDEO_PLAYBACK_SPEED, "1.00")); } catch (NumberFormatException e) { Log.e(TAG, Log.getStackTraceString(e)); - UserPreferences.setVideoPlaybackSpeed("1.00"); + UserPreferences.setVideoPlaybackSpeed(1.0f); return 1.0f; } } @@ -408,7 +408,7 @@ public class UserPreferences { return prefs.getBoolean(PREF_PLAYBACK_SKIP_SILENCE, false); } - public static String[] getPlaybackSpeedArray() { + public static float[] getPlaybackSpeedArray() { return readPlaybackSpeedArray(prefs.getString(PREF_PLAYBACK_SPEED_ARRAY, null)); } @@ -638,15 +638,15 @@ public class UserPreferences { .apply(); } - public static void setPlaybackSpeed(String speed) { + public static void setPlaybackSpeed(float speed) { prefs.edit() - .putString(PREF_PLAYBACK_SPEED, speed) + .putString(PREF_PLAYBACK_SPEED, String.valueOf(speed)) .apply(); } - public static void setVideoPlaybackSpeed(String speed) { + public static void setVideoPlaybackSpeed(float speed) { prefs.edit() - .putString(PREF_VIDEO_PLAYBACK_SPEED, speed) + .putString(PREF_VIDEO_PLAYBACK_SPEED, String.valueOf(speed)) .apply(); } @@ -769,24 +769,22 @@ public class UserPreferences { } } - private static String[] readPlaybackSpeedArray(String valueFromPrefs) { - String[] selectedSpeeds = null; - // If this preference hasn't been set yet, return the default options - if (valueFromPrefs == null) { - selectedSpeeds = new String[] { "0.75", "1.00", "1.25", "1.50", "1.75", "2.00" }; - } else { + private static float[] readPlaybackSpeedArray(String valueFromPrefs) { + if (valueFromPrefs != null) { try { JSONArray jsonArray = new JSONArray(valueFromPrefs); - selectedSpeeds = new String[jsonArray.length()]; + float[] selectedSpeeds = new float[jsonArray.length()]; for (int i = 0; i < jsonArray.length(); i++) { - selectedSpeeds[i] = jsonArray.getString(i); + selectedSpeeds[i] = (float) jsonArray.getDouble(i); } + return selectedSpeeds; } catch (JSONException e) { Log.e(TAG, "Got JSON error when trying to get speeds from JSONArray"); e.printStackTrace(); } } - return selectedSpeeds; + // If this preference hasn't been set yet, return the default options + return new float[] { 0.75f, 1.0f, 1.25f, 1.5f, 1.75f, 2.0f }; } public static String getMediaPlayer() { -- cgit v1.2.3 From b4b46fb4d844148fe48f46f8978a554e8c876c9d Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Mon, 20 Jan 2020 00:43:24 +0100 Subject: Fix playback button Steps to reproduce: - Play - Pause - Close AudioPlayerActivity - Open AudioPlayerActivity - Tap speed button - Always sets to the one after 1.0 --- .../main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java | 1 + 1 file changed, 1 insertion(+) (limited to 'core/src/main/java/de') 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 485349cb1..1bf0cfb18 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 @@ -639,6 +639,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer { float retVal = 1; if ((playerStatus == PlayerStatus.PLAYING || playerStatus == PlayerStatus.PAUSED + || playerStatus == PlayerStatus.INITIALIZED || playerStatus == PlayerStatus.PREPARED) && mediaPlayer.canSetSpeed()) { retVal = mediaPlayer.getCurrentSpeedMultiplier(); } -- cgit v1.2.3 From 5e842299181000dea688b886abee3d56ca446e13 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Mon, 27 Jan 2020 09:09:14 +0100 Subject: Enable PiP by default --- .../java/de/danoeh/antennapod/core/preferences/UserPreferences.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'core/src/main/java/de') 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 1ba981d27..00cafe226 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 @@ -822,11 +822,11 @@ public class UserPreferences { } public static VideoBackgroundBehavior getVideoBackgroundBehavior() { - switch (prefs.getString(PREF_VIDEO_BEHAVIOR, "stop")) { + switch (prefs.getString(PREF_VIDEO_BEHAVIOR, "pip")) { case "stop": return VideoBackgroundBehavior.STOP; case "pip": return VideoBackgroundBehavior.PICTURE_IN_PICTURE; case "continue": return VideoBackgroundBehavior.CONTINUE_PLAYING; - default: return VideoBackgroundBehavior.STOP; + default: return VideoBackgroundBehavior.PICTURE_IN_PICTURE; } } -- cgit v1.2.3 From 29bc5109a61c6bee9359a2986297917a2896405f Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Fri, 31 Jan 2020 16:37:42 +0100 Subject: Do not restart sleep timer when automatically playing next episode --- .../danoeh/antennapod/core/service/playback/PlaybackService.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'core/src/main/java/de') 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 d53f7d669..b9afb5c75 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 @@ -570,6 +570,7 @@ public class PlaybackService extends MediaBrowserServiceCompat { } else if (mediaPlayer.getPlayable() == null) { startPlayingFromPreferences(); } + taskManager.restartSleepTimer(); return true; case KeyEvent.KEYCODE_MEDIA_PLAY: if (status == PlayerStatus.PAUSED || status == PlayerStatus.PREPARED) { @@ -580,6 +581,7 @@ public class PlaybackService extends MediaBrowserServiceCompat { } else if (mediaPlayer.getPlayable() == null) { startPlayingFromPreferences(); } + taskManager.restartSleepTimer(); return true; case KeyEvent.KEYCODE_MEDIA_PAUSE: if (status == PlayerStatus.PLAYING) { @@ -827,9 +829,6 @@ public class PlaybackService extends MediaBrowserServiceCompat { @Override public void onPlaybackStart(@NonNull Playable playable, int position) { - if (taskManager.isSleepTimerActive()) { - taskManager.restartSleepTimer(); - } taskManager.startWidgetUpdater(); if (position != PlaybackServiceMediaPlayer.INVALID_TIME) { playable.setPosition(position); @@ -1446,10 +1445,12 @@ public class PlaybackService extends MediaBrowserServiceCompat { public void resume() { mediaPlayer.resume(); + taskManager.restartSleepTimer(); } public void prepare() { mediaPlayer.prepare(); + taskManager.restartSleepTimer(); } public void pause(boolean abandonAudioFocus, boolean reinit) { -- cgit v1.2.3 From c524d20cc900104093696c1064f46ad8e4c4bdad Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Mon, 3 Feb 2020 22:43:12 +0100 Subject: Do not add timecode link if timecode equals duration --- .../danoeh/antennapod/core/util/playback/Timeline.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java index 8624ec7e5..917f8e8e2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java @@ -9,6 +9,7 @@ import android.text.TextUtils; import android.util.Log; import android.util.TypedValue; +import de.danoeh.antennapod.core.feed.FeedItem; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; @@ -27,7 +28,8 @@ import de.danoeh.antennapod.core.util.ShownotesProvider; * shownotes to navigate to another position in the podcast or by highlighting certain parts of the shownotesProvider's * shownotes. *

- * A timeline object needs a shownotesProvider from which the chapter information is retrieved and shownotes are generated. + * A timeline object needs a shownotesProvider from which the chapter information + * is retrieved and shownotes are generated. */ public class Timeline { private static final String TAG = "Timeline"; @@ -110,8 +112,6 @@ public class Timeline { */ @NonNull public String processShownotes() { - final Playable playable = (shownotesProvider instanceof Playable) ? (Playable) shownotesProvider : null; - // load shownotes String shownotes; @@ -154,7 +154,7 @@ public class Timeline { document.head().appendElement("style").attr("type", "text/css").text(styleStr); // apply timecode links - addTimecodes(document, playable); + addTimecodes(document); return document.toString(); } @@ -184,7 +184,7 @@ public class Timeline { return -1; } - private void addTimecodes(Document document, final Playable playable) { + private void addTimecodes(Document document) { Elements elementsWithTimeCodes = document.body().getElementsMatchingOwnText(TIMECODE_REGEX); Log.d(TAG, "Recognized " + elementsWithTimeCodes.size() + " timecodes"); @@ -193,7 +193,13 @@ public class Timeline { return; } - int playableDuration = playable == null ? Integer.MAX_VALUE : playable.getDuration(); + int playableDuration = Integer.MAX_VALUE; + if (shownotesProvider instanceof Playable) { + playableDuration = ((Playable) shownotesProvider).getDuration(); + } else if (shownotesProvider instanceof FeedItem && ((FeedItem) shownotesProvider).getMedia() != null) { + playableDuration = ((FeedItem) shownotesProvider).getMedia().getDuration(); + } + boolean useHourFormat = true; if (playableDuration != Integer.MAX_VALUE) { -- cgit v1.2.3 From 6a0542ca1fe23537eeeab361c702a0b60a2579db Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Mon, 3 Feb 2020 23:17:04 +0100 Subject: Moved css to readable file instead of variable --- .../antennapod/core/util/playback/Timeline.java | 97 +++++----------------- 1 file changed, 23 insertions(+), 74 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java index 917f8e8e2..0fd658853 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java @@ -10,11 +10,14 @@ import android.util.Log; import android.util.TypedValue; import de.danoeh.antennapod.core.feed.FeedItem; +import org.apache.commons.io.IOUtils; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; +import java.io.IOException; +import java.io.InputStream; import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -34,43 +37,14 @@ import de.danoeh.antennapod.core.util.ShownotesProvider; public class Timeline { private static final String TAG = "Timeline"; - private static final String WEBVIEW_STYLE = - "@font-face {" - + "font-family: 'Roboto-Light';" - + "src: url('file:///android_asset/Roboto-Light.ttf');" - + "}" - + "* {" - + "color: %s;" - + "font-family: roboto-Light;" - + "font-size: 13pt;" - + "overflow-wrap: break-word;" - + "}" - + "a {" - + "font-style: normal;" - + "text-decoration: none;" - + "font-weight: normal;" - + "color: #00A8DF;" - + "}" - + "a.timecode {" - + "color: #669900;" - + "}" - + "img, iframe {" - + "display: block;" - + "margin: 10 auto;" - + "max-width: %s;" - + "height: auto;" - + "}" - + "body {" - + "margin: %dpx %dpx %dpx %dpx;" - + "}"; - - - private ShownotesProvider shownotesProvider; + private static final Pattern TIMECODE_LINK_REGEX = Pattern.compile("antennapod://timecode/((\\d+))"); + private static final String TIMECODE_LINK = "%s"; + private static final Pattern TIMECODE_REGEX = Pattern.compile("\\b((\\d+):)?(\\d+):(\\d{2})\\b"); + private static final Pattern LINE_BREAK_REGEX = Pattern.compile("
"); + private final ShownotesProvider shownotesProvider; private final String noShownotesLabel; - private final String colorPrimaryString; - private final String colorSecondaryString; - private final int pageMargin; + private final String webviewStyle; public Timeline(Context context, ShownotesProvider shownotesProvider) { if (shownotesProvider == null) { @@ -82,26 +56,21 @@ public class Timeline { TypedArray res = context.getTheme().obtainStyledAttributes(new int[]{android.R.attr.textColorPrimary}); @ColorInt int col = res.getColor(0, 0); - colorPrimaryString = "rgba(" + Color.red(col) + "," + Color.green(col) + "," + - Color.blue(col) + "," + (Color.alpha(col) / 255.0) + ")"; + final String colorPrimary = "rgba(" + Color.red(col) + "," + Color.green(col) + "," + + Color.blue(col) + "," + (Color.alpha(col) / 255.0) + ")"; res.recycle(); - res = context.getTheme().obtainStyledAttributes(new int[]{android.R.attr.textColorSecondary}); - col = res.getColor(0, 0); - colorSecondaryString = "rgba(" + Color.red(col) + "," + Color.green(col) + "," + - Color.blue(col) + "," + (Color.alpha(col) / 255.0) + ")"; - res.recycle(); - - pageMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, - context.getResources().getDisplayMetrics() - ); + final int margin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, + context.getResources().getDisplayMetrics()); + String styleString = ""; + try { + InputStream templateStream = context.getAssets().open("shownotes-style.css"); + styleString = IOUtils.toString(templateStream, "UTF-8"); + } catch (IOException e) { + e.printStackTrace(); + } + webviewStyle = String.format(Locale.getDefault(), styleString, colorPrimary, margin, margin, margin, margin); } - private static final Pattern TIMECODE_LINK_REGEX = Pattern.compile("antennapod://timecode/((\\d+))"); - private static final String TIMECODE_LINK = "%s"; - private static final Pattern TIMECODE_REGEX = Pattern.compile("\\b((\\d+):)?(\\d+):(\\d{2})\\b"); - private static final Pattern LINE_BREAK_REGEX = Pattern.compile("
"); - - /** * Applies an app-specific CSS stylesheet and adds timecode links (optional). *

@@ -112,8 +81,6 @@ public class Timeline { */ @NonNull public String processShownotes() { - // load shownotes - String shownotes; try { shownotes = shownotesProvider.loadShownotes().call(); @@ -124,21 +91,7 @@ public class Timeline { if (TextUtils.isEmpty(shownotes)) { Log.d(TAG, "shownotesProvider contained no shownotes. Returning 'no shownotes' message"); - shownotes = "" + - "" + - "" + - "" + - "" + - "

" + noShownotesLabel + "

" + - "" + - ""; - Log.d(TAG, "shownotes: " + shownotes); - return shownotes; + shownotes = "

" + noShownotesLabel + "

"; } // replace ASCII line breaks with HTML ones if shownotes don't contain HTML line breaks already @@ -147,11 +100,7 @@ public class Timeline { } Document document = Jsoup.parse(shownotes); - - // apply style - String styleStr = String.format(Locale.getDefault(), WEBVIEW_STYLE, colorPrimaryString, "100%", - pageMargin, pageMargin, pageMargin, pageMargin); - document.head().appendElement("style").attr("type", "text/css").text(styleStr); + document.head().appendElement("style").attr("type", "text/css").text(webviewStyle); // apply timecode links addTimecodes(document); -- cgit v1.2.3 From 50dd85276ca3507cfe4d9ec421aa0c406623ac01 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Tue, 4 Feb 2020 23:50:38 +0100 Subject: Fixed search returning duplicates --- .../java/de/danoeh/antennapod/core/storage/FeedSearcher.java | 8 +------- .../java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 9 ++------- .../java/de/danoeh/antennapod/core/storage/SearchLocation.java | 4 +--- 3 files changed, 4 insertions(+), 17 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java index 1d9e33d0e..6d6359a42 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java @@ -47,16 +47,10 @@ public class FeedSearcher { SearchLocation location; if (safeContains(item.getTitle(), query)) { location = SearchLocation.TITLE; - } else if (safeContains(item.getContentEncoded(), query)) { - location = SearchLocation.SHOWNOTES; - } else if (safeContains(item.getDescription(), query)) { - location = SearchLocation.SHOWNOTES; } else if (safeContains(item.getChapters(), query)) { location = SearchLocation.CHAPTERS; - } else if (safeContains(item.getFeed().getAuthor(), query)) { - location = SearchLocation.AUTHORS; } else { - location = SearchLocation.FEED; + location = SearchLocation.SHOWNOTES; } result.add(new SearchResult(item, location)); } 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 17b79a3da..48af7def0 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 @@ -1273,20 +1273,15 @@ public class PodDBAdapter { queryFeedId = "1 = 1"; } - String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS + String query = "SELECT DISTINCT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS + " LEFT JOIN " + TABLE_NAME_SIMPLECHAPTERS + " ON " + TABLE_NAME_SIMPLECHAPTERS + "." + KEY_FEEDITEM + "=" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID - + " LEFT JOIN " + TABLE_NAME_FEEDS - + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_FEED - + "=" + TABLE_NAME_FEEDS + "." + KEY_ID + " WHERE " + queryFeedId + " AND (" + TABLE_NAME_FEED_ITEMS + "." + KEY_DESCRIPTION + " LIKE '%" + preparedQuery + "%' OR " + TABLE_NAME_FEED_ITEMS + "." + KEY_CONTENT_ENCODED + " LIKE '%" + preparedQuery + "%' OR " + TABLE_NAME_FEED_ITEMS + "." + KEY_TITLE + " LIKE '%" + preparedQuery + "%' OR " - + TABLE_NAME_SIMPLECHAPTERS + "." + KEY_TITLE + " LIKE '%" + preparedQuery + "%' OR " - + TABLE_NAME_FEEDS + "." + KEY_AUTHOR + " LIKE '%" + preparedQuery + "%' OR " - + TABLE_NAME_FEEDS + "." + KEY_FEED_IDENTIFIER + " LIKE '%" + preparedQuery + "%'" + + TABLE_NAME_SIMPLECHAPTERS + "." + KEY_TITLE + " LIKE '%" + preparedQuery + "%'" + ") ORDER BY " + KEY_PUBDATE + " DESC " + "LIMIT 500"; return db.rawQuery(query, null); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/SearchLocation.java b/core/src/main/java/de/danoeh/antennapod/core/storage/SearchLocation.java index fabe85b2c..078797bda 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/SearchLocation.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/SearchLocation.java @@ -6,9 +6,7 @@ import de.danoeh.antennapod.core.R; public enum SearchLocation { TITLE(R.string.found_in_title_label), CHAPTERS(R.string.found_in_chapters_label), - SHOWNOTES(R.string.found_in_shownotes_label), - AUTHORS(R.string.found_in_authors_label), - FEED(R.string.found_in_feeds_label); + SHOWNOTES(R.string.found_in_shownotes_label); private int description; SearchLocation(@StringRes int description) { -- cgit v1.2.3 From 8d23571bbaf45062af5bd253281132935a68c0a1 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 5 Feb 2020 00:06:32 +0100 Subject: Search for feeds separately --- .../de/danoeh/antennapod/core/storage/DBTasks.java | 17 ++++++++++++++ .../antennapod/core/storage/FeedSearcher.java | 27 ++++++++++++---------- .../antennapod/core/storage/PodDBAdapter.java | 22 +++++++++++++++++- 3 files changed, 53 insertions(+), 13 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index 91f656bf1..8ebe18dc0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -553,6 +553,23 @@ public final class DBTasks { }); } + public static FutureTask> searchFeeds(final Context context, final String query) { + return new FutureTask<>(new QueryTask>(context) { + @Override + public void execute(PodDBAdapter adapter) { + Cursor cursor = adapter.searchFeeds(query); + List items = new ArrayList<>(); + if (cursor.moveToFirst()) { + do { + items.add(Feed.fromCursor(cursor)); + } while (cursor.moveToNext()); + } + setResult(items); + cursor.close(); + } + }); + } + /** * A runnable which should be used for database queries. The onCompletion * method is executed on the database executor to handle Cursors correctly. diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java index 6d6359a42..100d0e910 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java @@ -2,21 +2,16 @@ package de.danoeh.antennapod.core.storage; import android.content.Context; import androidx.annotation.NonNull; - 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.SearchResult; + import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; -import de.danoeh.antennapod.core.R; -import de.danoeh.antennapod.core.feed.FeedItem; -import de.danoeh.antennapod.core.feed.SearchResult; -import de.danoeh.antennapod.core.util.comparator.InReverseChronologicalOrder; - /** * Performs search on Feeds and FeedItems. */ @@ -40,9 +35,17 @@ public class FeedSearcher { public static List performSearch(final Context context, final String query, final long selectedFeed) { final List result = new ArrayList<>(); try { - FutureTask> searchTask = DBTasks.searchFeedItems(context, selectedFeed, query); - searchTask.run(); - final List items = searchTask.get(); + FutureTask> itemSearchTask = DBTasks.searchFeedItems(context, selectedFeed, query); + FutureTask> feedSearchTask = DBTasks.searchFeeds(context, query); + itemSearchTask.run(); + feedSearchTask.run(); + + final List feeds = feedSearchTask.get(); + for (Feed item : feeds) { + result.add(new SearchResult(item, null)); + } + + final List items = itemSearchTask.get(); for (FeedItem item : items) { SearchLocation location; if (safeContains(item.getTitle(), query)) { 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 48af7def0..749597840 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 @@ -284,10 +284,13 @@ public class PodDBAdapter { * Contains FEEDITEM_SEL_FI_SMALL as comma-separated list. Useful for raw queries. */ private static final String SEL_FI_SMALL_STR; + private static final String FEED_SEL_STD_STR; static { String selFiSmall = Arrays.toString(FEEDITEM_SEL_FI_SMALL); SEL_FI_SMALL_STR = selFiSmall.substring(1, selFiSmall.length() - 1); + String selFeedSmall = Arrays.toString(FEED_SEL_STD); + FEED_SEL_STD_STR = selFeedSmall.substring(1, selFeedSmall.length() - 1); } /** @@ -1283,7 +1286,24 @@ public class PodDBAdapter { + TABLE_NAME_FEED_ITEMS + "." + KEY_TITLE + " LIKE '%" + preparedQuery + "%' OR " + TABLE_NAME_SIMPLECHAPTERS + "." + KEY_TITLE + " LIKE '%" + preparedQuery + "%'" + ") ORDER BY " + KEY_PUBDATE + " DESC " - + "LIMIT 500"; + + "LIMIT 300"; + return db.rawQuery(query, null); + } + + /** + * Searches for the given query in various values of all feeds. + * + * @return A cursor with all search results in SEL_FI_EXTRA selection. + */ + public Cursor searchFeeds(String searchQuery) { + String preparedQuery = prepareSearchQuery(searchQuery); + String query = "SELECT " + FEED_SEL_STD_STR + " FROM " + TABLE_NAME_FEEDS + " WHERE " + + KEY_TITLE + " LIKE '%" + preparedQuery + "%' OR " + + KEY_CUSTOM_TITLE + " LIKE '%" + preparedQuery + "%' OR " + + KEY_AUTHOR + " LIKE '%" + preparedQuery + "%' OR " + + KEY_DESCRIPTION + " LIKE '%" + preparedQuery + "%' " + + "ORDER BY " + KEY_TITLE + " ASC " + + "LIMIT 300"; return db.rawQuery(query, null); } -- cgit v1.2.3 From 75e0d2d7e1929a617ea21e235d96e0448eea091b Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 5 Feb 2020 00:29:07 +0100 Subject: Verify database version before import --- .../antennapod/core/storage/DatabaseExporter.java | 32 ++++++++++------------ .../antennapod/core/storage/PodDBAdapter.java | 12 +++----- 2 files changed, 19 insertions(+), 25 deletions(-) (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java index af3d1206c..234c01b20 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DatabaseExporter.java @@ -1,6 +1,8 @@ package de.danoeh.antennapod.core.storage; import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteException; import android.net.Uri; import android.os.ParcelFileDescriptor; import android.util.Log; @@ -14,21 +16,10 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.channels.FileChannel; -import java.util.Arrays; public class DatabaseExporter { private static final String TAG = "DatabaseExporter"; - private static final byte[] SQLITE3_MAGIC = "SQLite format 3\0".getBytes(); - - public static boolean validateDB(Uri inputUri, Context context) throws IOException { - try (InputStream inputStream = context.getContentResolver().openInputStream(inputUri)) { - byte[] magicBuf = new byte[SQLITE3_MAGIC.length]; - if (inputStream.read(magicBuf) == magicBuf.length) { - return Arrays.equals(SQLITE3_MAGIC, magicBuf); - } - } - return false; - } + private static final String TEMP_DB_NAME = PodDBAdapter.DATABASE_NAME + "_tmp"; public static void exportToDocument(Uri uri, Context context) throws IOException { ParcelFileDescriptor pfd = null; @@ -78,14 +69,21 @@ public class DatabaseExporter { public static void importBackup(Uri inputUri, Context context) throws IOException { InputStream inputStream = null; try { - if (!validateDB(inputUri, context)) { - throw new IOException(context.getString(R.string.import_bad_file)); + File tempDB = context.getDatabasePath(TEMP_DB_NAME); + inputStream = context.getContentResolver().openInputStream(inputUri); + FileUtils.copyInputStreamToFile(inputStream, tempDB); + + SQLiteDatabase db = SQLiteDatabase.openDatabase(tempDB.getAbsolutePath(), + null, SQLiteDatabase.OPEN_READONLY); + if (db.getVersion() > PodDBAdapter.VERSION) { + throw new IOException(context.getString(R.string.import_no_downgrade)); } + db.close(); File currentDB = context.getDatabasePath(PodDBAdapter.DATABASE_NAME); - inputStream = context.getContentResolver().openInputStream(inputUri); - FileUtils.copyInputStreamToFile(inputStream, currentDB); - } catch (IOException e) { + currentDB.delete(); + FileUtils.moveFile(tempDB, currentDB); + } catch (IOException | SQLiteException e) { Log.e(TAG, Log.getStackTraceString(e)); throw e; } finally { 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 17b79a3da..ce55591ae 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 @@ -48,6 +48,7 @@ public class PodDBAdapter { private static final String TAG = "PodDBAdapter"; public static final String DATABASE_NAME = "Antennapod.db"; + public static final int VERSION = 1090000; /** * Maximum number of arguments for IN-operator. @@ -1336,8 +1337,6 @@ public class PodDBAdapter { * Helper class for opening the Antennapod database. */ private static class PodDBHelper extends SQLiteOpenHelper { - private static final int VERSION = 1090000; - /** * Constructor. * @@ -1345,8 +1344,7 @@ public class PodDBAdapter { * @param name Name of the database * @param factory to use for creating cursor objects */ - public PodDBHelper(final Context context, final String name, - final CursorFactory factory) { + public PodDBHelper(final Context context, final String name, final CursorFactory factory) { super(context, name, factory, VERSION, new PodDbErrorHandler()); } @@ -1369,10 +1367,8 @@ public class PodDBAdapter { } @Override - public void onUpgrade(final SQLiteDatabase db, final int oldVersion, - final int newVersion) { - Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to " - + newVersion + "."); + public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) { + Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to " + newVersion + "."); DBUpgrader.upgrade(db, oldVersion, newVersion); } } -- cgit v1.2.3 From f4cfe7bdcafad57ec2c6f92d8fe93e8b45474049 Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 5 Feb 2020 09:51:29 +0100 Subject: Do not search in chapters This speeds up searching a LOT. I hope that most podcasts use good descriptions and we do not need to search for chapters. Podcasts outside of Germany use chapters only very infrequently. --- .../danoeh/antennapod/core/feed/SearchResult.java | 22 ------------ .../core/service/playback/PlaybackService.java | 23 ++++++------ .../antennapod/core/storage/FeedSearcher.java | 42 +++------------------- .../antennapod/core/storage/PodDBAdapter.java | 12 +++---- .../antennapod/core/storage/SearchLocation.java | 19 ---------- .../comparator/InReverseChronologicalOrder.java | 21 ----------- 6 files changed, 21 insertions(+), 118 deletions(-) delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/feed/SearchResult.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/storage/SearchLocation.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/util/comparator/InReverseChronologicalOrder.java (limited to 'core/src/main/java/de') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/SearchResult.java b/core/src/main/java/de/danoeh/antennapod/core/feed/SearchResult.java deleted file mode 100644 index 062a6abac..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/SearchResult.java +++ /dev/null @@ -1,22 +0,0 @@ -package de.danoeh.antennapod.core.feed; - -import de.danoeh.antennapod.core.storage.SearchLocation; - -public class SearchResult { - private final FeedComponent component; - private SearchLocation location; - - public SearchResult(FeedComponent component, SearchLocation location) { - super(); - this.component = component; - this.location = location; - } - - public FeedComponent getComponent() { - return component; - } - - public SearchLocation getLocation() { - return location; - } -} 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 37deb6dc0..01e84d732 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 @@ -54,10 +54,10 @@ 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.FeedComponent; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; -import de.danoeh.antennapod.core.feed.SearchResult; import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; @@ -1634,16 +1634,17 @@ public class PlaybackService extends MediaBrowserServiceCompat { public void onPlayFromSearch(String query, Bundle extras) { Log.d(TAG, "onPlayFromSearch query=" + query + " extras=" + extras.toString()); - List results = FeedSearcher.performSearch(getBaseContext(), query, 0); - for (SearchResult result : results) { - try { - FeedMedia p = ((FeedItem) (result.getComponent())).getMedia(); - mediaPlayer.playMediaObject(p, !p.localFileAvailable(), true, true); - return; - } catch (Exception e) { - Log.d(TAG, e.getMessage()); - e.printStackTrace(); - continue; + List results = FeedSearcher.performSearch(getBaseContext(), query, 0); + for (FeedComponent result : results) { + if (result instanceof FeedItem) { + try { + FeedMedia media = ((FeedItem) result).getMedia(); + mediaPlayer.playMediaObject(media, !media.localFileAvailable(), true, true); + return; + } catch (Exception e) { + Log.d(TAG, e.getMessage()); + e.printStackTrace(); + } } } onPlay(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java index 100d0e910..bbe8b26f1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java @@ -2,10 +2,9 @@ package de.danoeh.antennapod.core.storage; import android.content.Context; import androidx.annotation.NonNull; -import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.feed.FeedComponent; import de.danoeh.antennapod.core.feed.FeedItem; -import de.danoeh.antennapod.core.feed.SearchResult; import java.util.ArrayList; import java.util.List; @@ -32,50 +31,19 @@ public class FeedSearcher { * @return list of episodes containing the query */ @NonNull - public static List performSearch(final Context context, final String query, final long selectedFeed) { - final List result = new ArrayList<>(); + public static List performSearch(final Context context, final String query, final long selectedFeed) { + final List result = new ArrayList<>(); try { FutureTask> itemSearchTask = DBTasks.searchFeedItems(context, selectedFeed, query); FutureTask> feedSearchTask = DBTasks.searchFeeds(context, query); itemSearchTask.run(); feedSearchTask.run(); - final List feeds = feedSearchTask.get(); - for (Feed item : feeds) { - result.add(new SearchResult(item, null)); - } - - final List items = itemSearchTask.get(); - for (FeedItem item : items) { - SearchLocation location; - if (safeContains(item.getTitle(), query)) { - location = SearchLocation.TITLE; - } else if (safeContains(item.getChapters(), query)) { - location = SearchLocation.CHAPTERS; - } else { - location = SearchLocation.SHOWNOTES; - } - result.add(new SearchResult(item, location)); - } + result.addAll(feedSearchTask.get()); + result.addAll(itemSearchTask.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } return result; } - - private static boolean safeContains(String haystack, String needle) { - return haystack != null && haystack.contains(needle); - } - - private static boolean safeContains(List haystack, String needle) { - if (haystack == null) { - return false; - } - for (Chapter chapter : haystack) { - if (safeContains(chapter.getTitle(), needle)) { - return true; - } - } - return false; - } } 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 749597840..10daebedc 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 @@ -1276,15 +1276,11 @@ public class PodDBAdapter { queryFeedId = "1 = 1"; } - String query = "SELECT DISTINCT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS - + " LEFT JOIN " + TABLE_NAME_SIMPLECHAPTERS - + " ON " + TABLE_NAME_SIMPLECHAPTERS + "." + KEY_FEEDITEM - + "=" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS + " WHERE " + queryFeedId + " AND (" - + TABLE_NAME_FEED_ITEMS + "." + KEY_DESCRIPTION + " LIKE '%" + preparedQuery + "%' OR " - + TABLE_NAME_FEED_ITEMS + "." + KEY_CONTENT_ENCODED + " LIKE '%" + preparedQuery + "%' OR " - + TABLE_NAME_FEED_ITEMS + "." + KEY_TITLE + " LIKE '%" + preparedQuery + "%' OR " - + TABLE_NAME_SIMPLECHAPTERS + "." + KEY_TITLE + " LIKE '%" + preparedQuery + "%'" + + KEY_DESCRIPTION + " LIKE '%" + preparedQuery + "%' OR " + + KEY_CONTENT_ENCODED + " LIKE '%" + preparedQuery + "%' OR " + + KEY_TITLE + " LIKE '%" + preparedQuery + "%'" + ") ORDER BY " + KEY_PUBDATE + " DESC " + "LIMIT 300"; return db.rawQuery(query, null); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/SearchLocation.java b/core/src/main/java/de/danoeh/antennapod/core/storage/SearchLocation.java deleted file mode 100644 index 078797bda..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/SearchLocation.java +++ /dev/null @@ -1,19 +0,0 @@ -package de.danoeh.antennapod.core.storage; - -import androidx.annotation.StringRes; -import de.danoeh.antennapod.core.R; - -public enum SearchLocation { - TITLE(R.string.found_in_title_label), - CHAPTERS(R.string.found_in_chapters_label), - SHOWNOTES(R.string.found_in_shownotes_label); - - private int description; - SearchLocation(@StringRes int description) { - this.description = description; - } - - public @StringRes int getDescription() { - return description; - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/InReverseChronologicalOrder.java b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/InReverseChronologicalOrder.java deleted file mode 100644 index 80246af8f..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/InReverseChronologicalOrder.java +++ /dev/null @@ -1,21 +0,0 @@ -package de.danoeh.antennapod.core.util.comparator; - -import java.util.Comparator; - -import de.danoeh.antennapod.core.feed.FeedItem; -import de.danoeh.antennapod.core.feed.SearchResult; - -public class InReverseChronologicalOrder implements Comparator { - /** - * Compare items and sort it on chronological order. - */ - @Override - public int compare(SearchResult o1, SearchResult o2) { - if ((o1.getComponent() instanceof FeedItem) && (o2.getComponent() instanceof FeedItem)) { - FeedItem item1 = (FeedItem) o1.getComponent(); - FeedItem item2 = (FeedItem) o2.getComponent(); - return item2.getPubDate().compareTo(item1.getPubDate()); - } - return 0; - } -} -- cgit v1.2.3