From 5fe65f470e4f5e279e57f5107975428f3c232eab Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Wed, 22 Apr 2015 11:21:59 +0200 Subject: Reorganize episode cache size values --- core/src/main/res/values/arrays.xml | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'core/src') diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index ccf14d329..57de2ca2e 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -39,30 +39,24 @@ 12 24 + - @string/pref_episode_cache_unlimited - 1 - 2 5 10 - 20 - 40 - 60 - 80 + 25 + 50 100 + @string/pref_episode_cache_unlimited - -1 - 1 - 2 5 10 - 20 - 40 - 60 - 80 + 25 + 50 100 + -1 + 0.5 0.6 -- cgit v1.2.3 From ce6cd1a353e27f598c7197a360d26602dd894caa Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 18 Jun 2015 17:15:56 +0200 Subject: Don't propose to open malformed URLs --- .../de/danoeh/antennapod/core/util/IntentUtils.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java new file mode 100644 index 000000000..2d5a6e5a1 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java @@ -0,0 +1,18 @@ +package de.danoeh.antennapod.core.util; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; + +import java.util.List; + +public class IntentUtils { + + public static boolean isCallable(final Context context, final Intent intent) { + List list = context.getPackageManager().queryIntentActivities(intent, + PackageManager.MATCH_DEFAULT_ONLY); + return list.size() > 0; + } + +} -- cgit v1.2.3 From b0ba5a08f7423e5e75c25a638418444e9a7b8f27 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 6 Jun 2015 00:05:19 +0200 Subject: Sharing in options and context menus --- .../de/danoeh/antennapod/core/util/ShareUtils.java | 56 ++++++++++++++++++---- core/src/main/res/values/strings.xml | 8 +++- 2 files changed, 52 insertions(+), 12 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java index 85f32ed50..bc310ae21 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java @@ -2,6 +2,8 @@ package de.danoeh.antennapod.core.util; import android.content.Context; import android.content.Intent; + +import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedItem; @@ -11,24 +13,58 @@ public class ShareUtils { private ShareUtils() {} - public static void shareLink(Context context, String link) { + public static void shareLink(Context context, String subject, String text) { Intent i = new Intent(Intent.ACTION_SEND); i.setType("text/plain"); - i.putExtra(Intent.EXTRA_SUBJECT, "Sharing URL"); - i.putExtra(Intent.EXTRA_TEXT, link); + i.putExtra(Intent.EXTRA_SUBJECT, subject); + i.putExtra(Intent.EXTRA_TEXT, text); context.startActivity(Intent.createChooser(i, "Share URL")); } - - public static void shareFeedItemLink(Context context, FeedItem item) { - shareLink(context, item.getLink()); + + public static void shareFeedlink(Context context, Feed feed) { + String subject = context.getString(R.string.share_link_label); + shareLink(context, subject, feed.getLink()); } public static void shareFeedDownloadLink(Context context, Feed feed) { - shareLink(context, feed.getDownload_url()); + String subject = context.getString(R.string.share_feed_url_label); + shareLink(context, subject, feed.getDownload_url()); } - - public static void shareFeedlink(Context context, Feed feed) { - shareLink(context, feed.getLink()); + + public static void shareFeedItemLink(Context context, FeedItem item) { + shareFeedItemLink(context, item, false); + } + + public static void shareFeedItemDownloadLink(Context context, FeedItem item) { + shareFeedItemDownloadLink(context, item, false); + } + + public static void shareFeedItemLink(Context context, FeedItem item, boolean withPosition) { + String subject; + String text; + if(withPosition) { + subject = context.getString(R.string.share_link_with_position_label); + int pos = item.getMedia().getPosition(); + text = item.getLink() + " [" + Converter.getDurationStringLong(pos) + "]"; + } else { + subject = context.getString(R.string.share_link_label); + text = item.getLink(); + } + shareLink(context, subject, text); + } + + public static void shareFeedItemDownloadLink(Context context, FeedItem item, boolean withPosition) { + String subject; + String text; + if(withPosition) { + subject = context.getString(R.string.share_item_url_with_position_label); + int pos = item.getMedia().getPosition(); + text = item.getMedia().getDownload_url() + " [" + Converter.getDurationStringLong(pos) + "]"; + } else { + subject = context.getString(R.string.share_item_url_label); + text = item.getMedia().getDownload_url(); + } + shareLink(context, subject, text); } } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 3cedfb8e5..462e0657c 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -86,8 +86,12 @@ Please confirm that you want to mark all episodes in this feed as being played. Show information Remove podcast - Share website link - Share feed link + Share... + Share Link + Share Link with Position + Share Feed URL + Share Episode URL + Share Episode URL with Position Please confirm that you want to delete this feed and ALL episodes of this feed that you have downloaded. Removing feed Refresh complete feed -- cgit v1.2.3 From 8a9229ede62e9f1efef0e2ac102f1d7e930280b0 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 6 Jun 2015 00:25:23 +0200 Subject: Capitalize titles --- .../de/danoeh/antennapod/core/util/ShareUtils.java | 21 ++-- core/src/main/res/values/strings.xml | 112 ++++++++++----------- 2 files changed, 62 insertions(+), 71 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java index bc310ae21..c065a62c3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java @@ -13,22 +13,19 @@ public class ShareUtils { private ShareUtils() {} - public static void shareLink(Context context, String subject, String text) { + public static void shareLink(Context context, String text) { Intent i = new Intent(Intent.ACTION_SEND); i.setType("text/plain"); - i.putExtra(Intent.EXTRA_SUBJECT, subject); i.putExtra(Intent.EXTRA_TEXT, text); - context.startActivity(Intent.createChooser(i, "Share URL")); + context.startActivity(Intent.createChooser(i, context.getString(R.string.share_url_label))); } public static void shareFeedlink(Context context, Feed feed) { - String subject = context.getString(R.string.share_link_label); - shareLink(context, subject, feed.getLink()); + shareLink(context, feed.getLink()); } public static void shareFeedDownloadLink(Context context, Feed feed) { - String subject = context.getString(R.string.share_feed_url_label); - shareLink(context, subject, feed.getDownload_url()); + shareLink(context, feed.getDownload_url()); } public static void shareFeedItemLink(Context context, FeedItem item) { @@ -40,31 +37,25 @@ public class ShareUtils { } public static void shareFeedItemLink(Context context, FeedItem item, boolean withPosition) { - String subject; String text; if(withPosition) { - subject = context.getString(R.string.share_link_with_position_label); int pos = item.getMedia().getPosition(); text = item.getLink() + " [" + Converter.getDurationStringLong(pos) + "]"; } else { - subject = context.getString(R.string.share_link_label); text = item.getLink(); } - shareLink(context, subject, text); + shareLink(context, text); } public static void shareFeedItemDownloadLink(Context context, FeedItem item, boolean withPosition) { - String subject; String text; if(withPosition) { - subject = context.getString(R.string.share_item_url_with_position_label); int pos = item.getMedia().getPosition(); text = item.getMedia().getDownload_url() + " [" + Converter.getDurationStringLong(pos) + "]"; } else { - subject = context.getString(R.string.share_item_url_label); text = item.getMedia().getDownload_url(); } - shareLink(context, subject, text); + shareLink(context, text); } } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 462e0657c..ac9255ac9 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -7,27 +7,27 @@ AntennaPod Feeds - Add podcast + Add Podcast PODCASTS EPISODES - New episodes - All episodes + New Episodes + All Episodes New - Waiting list + Waiting List Settings - Add podcast + Add Podcast Downloads Running Completed Log Cancel Download - Playback history + Playback History gpodder.net - gpodder.net login + gpodder.net Login Recently published - Show only new episodes + Show only new Episodes Open menu @@ -35,14 +35,14 @@ Drawer Preferences - Open in browser + Open in Browser Copy URL Share URL - Copied URL to clipboard. - Go to this position + Copied URL to Clipboard + Go to this Position - Clear history + Clear History Confirm @@ -59,7 +59,7 @@ Chapters Shownotes Description - Most Recent Episode:\u0020 + Most recent episode:\u0020 \u0020episodes Length:\u0020 Size:\u0020 @@ -75,17 +75,17 @@ Feed URL www.example.com/feed Add Podcast by URL - Find podcast in directory + Find Podcast in Directory You can search for new podcasts by name, category or popularity in the gpodder.net directory, or search the iTunes store. Browse gpodder.net Mark all as played - Marked all episodes as played + Marked all Episodes as played Please confirm that you want to mark all episodes as being played. Please confirm that you want to mark all episodes in this feed as being played. Show information - Remove podcast + Remove Podcast Share... Share Link Share Link with Position @@ -93,9 +93,9 @@ Share Episode URL Share Episode URL with Position Please confirm that you want to delete this feed and ALL episodes of this feed that you have downloaded. - Removing feed - Refresh complete feed - Hide episodes + Removing Feed + Refresh complete Feed + Hide Episodes Unplayed Paused Played @@ -104,7 +104,7 @@ Downloaded Not downloaded Filtered - {fa-exclamation-circle} Last refresh failed + {fa-exclamation-circle} Last Refresh failed Download @@ -113,7 +113,7 @@ Stop Stream Remove - Remove episode + Remove Episode Mark as played Mark as unplayed Marked as played @@ -125,39 +125,39 @@ Enqueue all Download all Skip episode - Activate auto download - Deactivate auto download - Reset playback position + Activate Auto Download + Deactivate Auto Download + Reset Playback Position successful failed Download pending Download running - Storage device not found - Insufficient space - File error + Storage Device not found + Insufficient Space + File Error HTTP Data Error Unknown Error Parser Exception - Unsupported Feed type - Connection error - Unknown host - Authentication error + Unsupported Feed Type + Connection Error + Unknown Host + Authentication Error Cancel all downloads Download canceled Download canceled\nDisabled Auto Download for this item Downloads completed with error(s) - Download report + Download Report Malformed URL IO Error - Request error - Database access error + Request Error + Database Access Error \u0020Downloads left Processing downloads Downloading podcast data %1$d downloads succeeded, %2$d failed - Unknown title + Unknown Title Feed Media file Image @@ -185,9 +185,9 @@ AntennaPod - Unknown media key: %1$d - Lock queue - Unlock queue - Clear queue + Lock Queue + Unlock Queue + Clear Queue Undo Item removed Move to top @@ -253,38 +253,38 @@ Smart mark as played Playback Network - Update interval + Update Interval Specify an interval in which the feeds are refreshed automatically or disable it Download media files only over WiFi - Continuous playback + Continuous Playback WiFi media download - Headphones disconnect - Headphones reconnect - Mobile updates + Headphones Disconnect + Headphones Reconnect + Mobile Updates Allow updates over the mobile data connection Refreshing Flattr settings Flattr sign-in Sign in to your flattr account to flattr things directly from the app. - Flattr this app + Flattr this App Support the development of AntennaPod by flattring it. Thanks! Revoke access Revoke the access permission to your flattr account for this app. Automatic Flattr Configure automatic flattring User Interface - Select theme - Change navigation drawer + Select Theme + Change Navigation Drawer Change which items appear in the navigation drawer. Change the appearance of AntennaPod. - Automatic download + Automatic Download Configure the automatic download of episodes. Enable Wi-Fi filter Allow automatic download only for selected Wi-Fi networks. Download when not charging Allow automatic download when the battery is not charging - Parallel downloads - Episode cache + Parallel Downloads + Episode Cache Light Dark Unlimited @@ -305,11 +305,11 @@ Use default host Expand Notification Always expand the notification to show playback buttons. - Persistent playback controls + Persistent Playback Controls Keep notification and lockscreen controls when playback is paused. Android versions before 4.1 do not support expanded notifications. Add new episodes to the front of the queue. - Enqueue at front. + Enqueue at Front Disabled @@ -332,7 +332,7 @@ Choose a specific file path from the local filesystem. Use an external applications like Dropbox, Google Drive or your favourite file manager to open an OPML file. Many applications like Google Mail, Dropbox, Google Drive and most file managers can open OPML files with AntennaPod. Start import - OPML import + OPML Import ERROR! Reading OPML file An error has occurred while reading the opml document: @@ -344,7 +344,7 @@ OPML export Exporting... Export error - OPML export successful. + OPML Export successful. The .opml file was written to:\u0020 @@ -392,7 +392,7 @@ Selected folder: Create folder - Choose data folder + Choose Data Folder Create new folder with name "%1$s"? Created new folder Cannot write to this folder @@ -402,9 +402,9 @@ The folder you have selected is not empty. Media downloads and other files will be placed directly in this folder. Continue anyway? Choose default folder Pause playback instead of lowering volume when another app wants to play sounds - Pause for interruptions + Pause for Interruptions Resume playback after a phone call completes - Resume after call + Resume after Call Subscribe -- cgit v1.2.3 From 7c944cbe65098ea46ee7e85166ada2cdb4b2a20b Mon Sep 17 00:00:00 2001 From: Simon Danner Date: Sun, 21 Jun 2015 12:46:42 +0200 Subject: Download Report: introduce setting to disable Give the use the option to disable the download report. While it is useful to see the failed downloads, if a user is subscribed to many podcasts, most of the times a few fail, which makes the notifications rather annonying. --- .../antennapod/core/preferences/UserPreferences.java | 16 ++++++++++++++++ .../core/service/download/DownloadService.java | 3 ++- core/src/main/res/values/strings.xml | 3 +++ 3 files changed, 21 insertions(+), 1 deletion(-) (limited to 'core/src') 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 594241573..6ef91a22a 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 @@ -44,6 +44,7 @@ public class UserPreferences implements public static final String PREF_HIDDEN_DRAWER_ITEMS = "prefHiddenDrawerItems"; public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify"; public static final String PREF_PERSISTENT_NOTIFICATION = "prefPersistNotify"; + public static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport"; // Queue public static final String PREF_QUEUE_ADD_TO_FRONT = "prefQueueAddToFront"; @@ -94,6 +95,7 @@ public class UserPreferences implements private List hiddenDrawerItems; private int notifyPriority; private boolean persistNotify; + private boolean showDownloadReport; // Queue private boolean enqueueAtFront; @@ -164,6 +166,7 @@ public class UserPreferences implements } hiddenDrawerItems = Arrays.asList(StringUtils.split(sp.getString(PREF_HIDDEN_DRAWER_ITEMS, ""), ',')); persistNotify = sp.getBoolean(PREF_PERSISTENT_NOTIFICATION, false); + showDownloadReport = sp.getBoolean(PREF_SHOW_DOWNLOAD_REPORT, true); // Queue enqueueAtFront = sp.getBoolean(PREF_QUEUE_ADD_TO_FRONT, false); @@ -307,6 +310,16 @@ public class UserPreferences implements return instance.persistNotify; } + /** + * Returns true if download reports are shown + * + * @return {@code true} if download reports are shown, {@code false} otherwise + */ + public static boolean showDownloadReport() { + instanceAvailable(); + return instance.showDownloadReport; + } + /** * Returns {@code true} if new queue elements are added to the front * @@ -463,6 +476,9 @@ public class UserPreferences implements case PREF_PERSISTENT_NOTIFICATION: persistNotify = sp.getBoolean(PREF_PERSISTENT_NOTIFICATION, false); break; + case PREF_SHOW_DOWNLOAD_REPORT: + showDownloadReport = sp.getBoolean(PREF_SHOW_DOWNLOAD_REPORT, true); + break; // Queue case PREF_QUEUE_ADD_TO_FRONT: enqueueAtFront = sp.getBoolean(PREF_QUEUE_ADD_TO_FRONT, false); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index e7b226eca..fae6dee1d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -309,7 +309,8 @@ public class DownloadService extends Service { Log.d(TAG, "Service shutting down"); isRunning = false; - if (ClientConfig.downloadServiceCallbacks.shouldCreateReport()) { + if (ClientConfig.downloadServiceCallbacks.shouldCreateReport() && + UserPreferences.showDownloadReport()) { updateReport(); } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 3cedfb8e5..cf0630ea0 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -303,6 +303,9 @@ Always expand the notification to show playback buttons. Persistent playback controls Keep notification and lockscreen controls when playback is paused. + Show Download Report + If downloads fail, generate a report that shows the details of the failure. + Android versions before 4.1 do not support expanded notifications. Add new episodes to the front of the queue. Enqueue at front. -- cgit v1.2.3 From 80c719d432d2bc2441a3adeefe542e45af6575da Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 21 Jun 2015 15:43:14 +0200 Subject: Fix datetime parsing (seconds absent) --- .../java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java | 8 ++++++++ core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java | 4 ++++ 2 files changed, 12 insertions(+) (limited to 'core/src') diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java b/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java index 2a2d6414a..7429b50b3 100644 --- a/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java +++ b/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java @@ -66,6 +66,14 @@ public class DateUtilsTest extends AndroidTestCase { assertEquals(expected, actual); } + public void testParseDateWithTimezoneName2() throws Exception { + GregorianCalendar exp = new GregorianCalendar(2015, 2, 28, 6, 31, 0); + exp.setTimeZone(TimeZone.getTimeZone("UTC")); + Date expected = new Date(exp.getTimeInMillis()); + Date actual = DateUtils.parse("Sat, 28 Mar 2015 01:31 EST"); + assertEquals(expected, actual); + } + public void testParseDateWithTimeZoneOffset() throws Exception { GregorianCalendar exp = new GregorianCalendar(2015, 2, 28, 12, 16, 12); exp.setTimeZone(TimeZone.getTimeZone("UTC")); diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java index b6df2dc85..10512dd48 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java @@ -49,6 +49,10 @@ public class DateUtils { "EEE, dd MMMM yyyy HH:mm:ss Z", "EEEE, dd MMM yy HH:mm:ss Z", "EEE MMM d HH:mm:ss yyyy", + "EEE, dd MMM yyyy HH:mm Z", + "EEE, dd MMMM yyyy HH:mm Z", + "EEEE, dd MMM yy HH:mm Z", + "EEE MMM d HH:mm yyyy", "yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd'T'HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ss.SSS Z", -- cgit v1.2.3 From 978eadbc16a3a5fd675994796f0af84459af413a Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 21 Jun 2015 16:28:29 +0200 Subject: Fixes Queue transition from playing local to streaming --- .../de/danoeh/antennapod/core/service/playback/PlaybackService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src') 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 3f6769ee4..43a91933c 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 @@ -634,7 +634,7 @@ public class PlaybackService extends Service { writePlaybackPreferencesNoMediaPlaying(); if (nextMedia != null) { - stream = !playable.localFileAvailable(); + stream = !nextMedia.localFileAvailable(); mediaPlayer.playMediaObject(nextMedia, stream, startWhenPrepared, prepareImmediately); sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, (nextMedia.getMediaType() == MediaType.VIDEO) ? EXTRA_CODE_VIDEO : EXTRA_CODE_AUDIO); -- cgit v1.2.3 From c452d311e290d1b7c747ddb5df5c7c042398ab9a Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 19 Jun 2015 01:57:49 +0200 Subject: Store information if media has an embedded picture in the database --- .../antennapod/core/event/ProgressEvent.java | 36 ++++++++++++++++++++++ .../de/danoeh/antennapod/core/feed/FeedMedia.java | 15 +++++++++ .../core/service/download/DownloadService.java | 1 + .../danoeh/antennapod/core/storage/DBReader.java | 15 ++++++++- .../danoeh/antennapod/core/storage/DBWriter.java | 1 + .../antennapod/core/storage/PodDBAdapter.java | 14 ++++++++- core/src/main/res/values/strings.xml | 4 +++ 7 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/event/ProgressEvent.java (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/ProgressEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/ProgressEvent.java new file mode 100644 index 000000000..3769d6bb1 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/event/ProgressEvent.java @@ -0,0 +1,36 @@ +package de.danoeh.antennapod.core.event; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +public class ProgressEvent { + + public enum Action { + START, END + } + + public final Action action; + public final String message; + + private ProgressEvent(Action action, String message) { + this.action = action; + this.message = message; + } + + public static ProgressEvent start(String message) { + return new ProgressEvent(Action.START, message); + } + + public static ProgressEvent end() { + return new ProgressEvent(Action.END, null); + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("action", action) + .append("message", message) + .toString(); + } + +} 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 ee05020cc..b4cca505c 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 @@ -35,6 +35,8 @@ public class FeedMedia extends FeedFile implements Playable { private String mime_type; private volatile FeedItem item; private Date playbackCompletionDate; + + // if null: unknown, will be checked private Boolean hasEmbeddedPicture; /* Used for loading item when restoring from parcel. */ @@ -63,6 +65,15 @@ public class FeedMedia extends FeedFile implements Playable { ? null : (Date) playbackCompletionDate.clone(); } + public FeedMedia(long id, FeedItem item, int duration, int position, + long size, String mime_type, String file_url, String download_url, + boolean downloaded, Date playbackCompletionDate, int played_duration, + Boolean hasEmbeddedPicture) { + this(id, item, duration, position, size, mime_type, file_url, download_url, downloaded, + playbackCompletionDate, played_duration); + this.hasEmbeddedPicture = hasEmbeddedPicture; + } + @Override public String getHumanReadableIdentifier() { if (item != null && item.getTitle() != null) { @@ -429,6 +440,10 @@ public class FeedMedia extends FeedFile implements Playable { } } + public void setHasEmbeddedPicture(Boolean hasEmbeddedPicture) { + this.hasEmbeddedPicture = hasEmbeddedPicture; + } + @Override public void setDownloaded(boolean downloaded) { super.setDownloaded(downloaded); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index e7b226eca..06bca3129 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -1143,6 +1143,7 @@ public class DownloadService extends Service { boolean chaptersRead = false; media.setDownloaded(true); media.setFile_url(request.getDestination()); + media.setHasEmbeddedPicture(null); // Get duration MediaMetadataRetriever mmr = null; 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 dc24c5784..4a329c2f6 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 @@ -274,6 +274,18 @@ public final class DBReader { playbackCompletionDate = new Date( playbackCompletionTime); } + Boolean hasEmbeddedPicture; + switch(cursor.getInt(cursor.getColumnIndex(PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE))) { + case 1: + hasEmbeddedPicture = Boolean.TRUE; + break; + case 0: + hasEmbeddedPicture = Boolean.FALSE; + break; + default: + hasEmbeddedPicture = null; + break; + } return new FeedMedia( mediaId, @@ -286,7 +298,8 @@ public final class DBReader { cursor.getString(PodDBAdapter.KEY_DOWNLOAD_URL_INDEX), cursor.getInt(PodDBAdapter.KEY_DOWNLOADED_INDEX) > 0, playbackCompletionDate, - cursor.getInt(PodDBAdapter.KEY_PLAYED_DURATION_INDEX)); + cursor.getInt(PodDBAdapter.KEY_PLAYED_DURATION_INDEX), + hasEmbeddedPicture); } private static Feed extractFeedFromCursorRow(PodDBAdapter adapter, 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 fe5d0dfd3..feeee48c5 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 @@ -100,6 +100,7 @@ public class DBWriter { } media.setDownloaded(false); media.setFile_url(null); + media.setHasEmbeddedPicture(false); PodDBAdapter adapter = new PodDBAdapter(context); adapter.open(); adapter.setMedia(media); 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 6fabf9005..ed3cb71e9 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 @@ -19,6 +19,8 @@ import java.util.List; import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.ClientConfig; +import de.danoeh.antennapod.core.R; +import de.danoeh.antennapod.core.event.ProgressEvent; import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedComponent; @@ -29,6 +31,7 @@ import de.danoeh.antennapod.core.feed.FeedPreferences; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.util.LongIntMap; import de.danoeh.antennapod.core.util.flattr.FlattrStatus; +import de.greenrobot.event.EventBus; ; @@ -155,6 +158,8 @@ public class PodDBAdapter { public static final String KEY_NEXT_PAGE_LINK = "next_page_link"; public static final String KEY_HIDE = "hide"; public static final String KEY_LAST_UPDATE_FAILED = "last_update_failed"; + public static final String KEY_HAS_EMBEDDED_PICTURE = "has_embedded_picture"; + // Table names public static final String TABLE_NAME_FEEDS = "Feeds"; @@ -209,7 +214,7 @@ public class PodDBAdapter { + KEY_PLAYBACK_COMPLETION_DATE + " INTEGER," + KEY_FEEDITEM + " INTEGER," + KEY_PLAYED_DURATION + " INTEGER," - + KEY_AUTO_DOWNLOAD + " INTEGER)"; + + KEY_HAS_EMBEDDED_PICTURE + " INTEGER)"; public static final String CREATE_TABLE_DOWNLOAD_LOG = "CREATE TABLE " + TABLE_NAME_DOWNLOAD_LOG + " (" + TABLE_PRIMARY_KEY + KEY_FEEDFILE @@ -516,6 +521,7 @@ public class PodDBAdapter { values.put(KEY_DOWNLOAD_URL, media.getDownload_url()); values.put(KEY_DOWNLOADED, media.isDownloaded()); values.put(KEY_FILE_URL, media.getFile_url()); + values.put(KEY_HAS_EMBEDDED_PICTURE, media.hasEmbeddedPicture()); if (media.getPlaybackCompletionDate() != null) { values.put(KEY_PLAYBACK_COMPLETION_DATE, media @@ -1463,6 +1469,9 @@ public class PodDBAdapter { * Helper class for opening the Antennapod database. */ private static class PodDBHelper extends SQLiteOpenHelper { + + private Context context; + /** * Constructor. * @@ -1474,6 +1483,7 @@ public class PodDBAdapter { public PodDBHelper(final Context context, final String name, final CursorFactory factory, final int version) { super(context, name, factory, version); + this.context = context; } @Override @@ -1497,7 +1507,9 @@ public class PodDBAdapter { @Override public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) { + EventBus.getDefault().post(ProgressEvent.start(context.getString(R.string.progress_upgrading_database))); ClientConfig.storageCallbacks.onUpgrade(db, oldVersion, newVersion); + EventBus.getDefault().post(ProgressEvent.end()); } } } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index ac9255ac9..fe8c08e9e 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -435,6 +435,10 @@ Authentication Change your username and password for this podcast and its episodes. + + + Upgrading the database + Importing subscriptions from single-purpose apps… -- cgit v1.2.3 From 20ab6ec260f3e7bd3ba189a155111de631d1bc7d Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 21 Jun 2015 18:22:17 -0400 Subject: set autodownload == false once an item is downloaded --- .../antennapod/core/service/download/DownloadService.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 06bca3129..fb3f480ff 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -1171,12 +1171,16 @@ public class DownloadService extends Service { } try { - if (chaptersRead) { - DBWriter.setFeedItem(DownloadService.this, media.getItem()).get(); - } + // we've received the media, we don't want to autodownload it again + FeedItem item = media.getItem(); + item.setAutoDownload(false); + + // update the db + DBWriter.setFeedItem(DownloadService.this, item).get(); + DBWriter.setFeedMedia(DownloadService.this, media).get(); - if (!DBTasks.isInQueue(DownloadService.this, media.getItem().getId())) { - DBWriter.addQueueItem(DownloadService.this, media.getItem().getId()).get(); + if (!DBTasks.isInQueue(DownloadService.this, item.getId())) { + DBWriter.addQueueItem(DownloadService.this, item.getId()).get(); } } catch (ExecutionException e) { e.printStackTrace(); -- cgit v1.2.3 From c2ca3e1bbdfb67a5b8bc6dea6a4f80d900ac65c7 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Mon, 22 Jun 2015 20:06:28 -0400 Subject: Only call getPSMPInfo if you need both the status and the playable. Fixes AntennaPod/AntennaPod#942 --- .../core/service/playback/PlaybackService.java | 23 +++++++++------------ .../playback/PlaybackServiceMediaPlayer.java | 24 ++++++++++++++++++---- 2 files changed, 30 insertions(+), 17 deletions(-) (limited to 'core/src') 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 43a91933c..9ab3d93a1 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 @@ -442,7 +442,7 @@ public class PlaybackService extends Service { } writePlayerStatusPlaybackPreferences(); - final Playable playable = mediaPlayer.getPSMPInfo().playable; + final Playable playable = newInfo.playable; // Gpodder: send play action if(GpodnetPreferences.loggedIn() && playable instanceof FeedMedia) { @@ -525,7 +525,7 @@ public class PlaybackService extends Service { public boolean onMediaPlayerError(Object inObj, int what, int extra) { final String TAG = "PlaybackService.onErrorListener"; Log.w(TAG, "An error has occured: " + what + " " + extra); - if (mediaPlayer.getPSMPInfo().playerStatus == PlayerStatus.PLAYING) { + if (mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING) { mediaPlayer.pause(true, false); } sendNotificationBroadcast(NOTIFICATION_TYPE_ERROR, what); @@ -549,7 +549,7 @@ public class PlaybackService extends Service { private void endPlayback(boolean playNextEpisode) { Log.d(TAG, "Playback ended"); - final Playable playable = mediaPlayer.getPSMPInfo().playable; + final Playable playable = mediaPlayer.getPlayable(); if (playable == null) { Log.e(TAG, "Cannot end playback: media was null"); return; @@ -744,8 +744,7 @@ public class PlaybackService extends Service { SharedPreferences.Editor editor = PreferenceManager .getDefaultSharedPreferences(getApplicationContext()).edit(); - PlaybackServiceMediaPlayer.PSMPInfo info = mediaPlayer.getPSMPInfo(); - int playerStatus = getCurrentPlayerStatusAsInt(info.playerStatus); + int playerStatus = getCurrentPlayerStatusAsInt(mediaPlayer.getPlayerStatus()); editor.putInt( PlaybackPreferences.PREF_CURRENT_PLAYER_STATUS, playerStatus); @@ -819,7 +818,7 @@ public class PlaybackService extends Service { if (mediaPlayer == null) { return; } - PlaybackServiceMediaPlayer.PSMPInfo newInfo = mediaPlayer.getPSMPInfo(); + PlayerStatus playerStatus = mediaPlayer.getPlayerStatus(); final int smallIcon = ClientConfig.playbackServiceCallbacks.getNotificationIconResource(getApplicationContext()); if (!isCancelled() && @@ -865,7 +864,7 @@ public class PlaybackService extends Service { .setLargeIcon(icon) .setSmallIcon(smallIcon) .setPriority(UserPreferences.getNotifyPriority()); // set notification priority - if (newInfo.playerStatus == PlayerStatus.PLAYING) { + if (playerStatus == PlayerStatus.PLAYING) { notificationBuilder.addAction(android.R.drawable.ic_media_pause, //pause action getString(R.string.pause_label), pauseButtonPendingIntent); @@ -923,7 +922,7 @@ public class PlaybackService extends Service { int position = getCurrentPosition(); int duration = getDuration(); float playbackSpeed = getCurrentPlaybackSpeed(); - final Playable playable = mediaPlayer.getPSMPInfo().playable; + final Playable playable = mediaPlayer.getPlayable(); if (position != INVALID_TIME && duration != INVALID_TIME && playable != null) { Log.d(TAG, "Saving current position to " + position); if (updatePlayedDuration && playable instanceof FeedMedia) { @@ -1200,12 +1199,10 @@ public class PlaybackService extends Service { } public PlayerStatus getStatus() { - return mediaPlayer.getPSMPInfo().playerStatus; + return mediaPlayer.getPlayerStatus(); } - public Playable getPlayable() { - return mediaPlayer.getPSMPInfo().playable; - } + public Playable getPlayable() { return mediaPlayer.getPlayable(); } public void setSpeed(float speed) { mediaPlayer.setSpeed(speed); @@ -1231,7 +1228,7 @@ public class PlaybackService extends Service { public void seekTo(final int t) { if(mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING && GpodnetPreferences.loggedIn()) { - final Playable playable = mediaPlayer.getPSMPInfo().playable; + final Playable playable = mediaPlayer.getPlayable(); if (playable instanceof FeedMedia) { FeedMedia media = (FeedMedia) playable; FeedItem item = media.getItem(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 7a8e38c59..d4b63fdb1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -623,10 +623,6 @@ public class PlaybackServiceMediaPlayer { return mediaType; } - public PlayerStatus getPlayerStatus() { - return playerStatus; - } - public boolean isStreaming() { return stream; } @@ -705,6 +701,26 @@ public class PlaybackServiceMediaPlayer { return new PSMPInfo(playerStatus, media); } + /** + * Returns the current status, if you need the media and the player status together, you should + * use getPSMPInfo() to make sure they're properly synchronized. Otherwise a race condition + * could result in nonsensical results (like a status of PLAYING, but a null playable) + * @return the current player status + */ + public PlayerStatus getPlayerStatus() { + return playerStatus; + } + + /** + * Returns the current media, if you need the media and the player status together, you should + * use getPSMPInfo() to make sure they're properly synchronized. Otherwise a race condition + * could result in nonsensical results (like a status of PLAYING, but a null playable) + * @return the current media. May be null + */ + public Playable getPlayable() { + return media; + } + /** * Returns a token to this object's MediaSession. The MediaSession should only be used for notifications * at the moment. -- cgit v1.2.3 From 33778e30ac156e22c9d748f905ddb26c65eadd78 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Mon, 22 Jun 2015 19:59:57 +0200 Subject: Don't cache shared preferences anymore. Some refactoring. --- .../core/preferences/UserPreferences.java | 547 ++++++--------------- .../danoeh/antennapod/core/storage/DBReader.java | 3 +- .../de/danoeh/antennapod/core/storage/DBTasks.java | 5 +- 3 files changed, 142 insertions(+), 413 deletions(-) (limited to 'core/src') 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 6ef91a22a..520bba72b 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 @@ -29,17 +29,16 @@ import de.danoeh.antennapod.core.receiver.FeedUpdateReceiver; /** * Provides access to preferences set by the user in the settings screen. A * private instance of this class must first be instantiated via - * createInstance() or otherwise every public method will throw an Exception + * init() or otherwise every public method will throw an Exception * when called. */ -public class UserPreferences implements - SharedPreferences.OnSharedPreferenceChangeListener { +public class UserPreferences { public static final String IMPORT_DIR = "import/"; private static final String TAG = "UserPreferences"; - // User Infercasce + // User Interface public static final String PREF_THEME = "prefTheme"; public static final String PREF_HIDDEN_DRAWER_ITEMS = "prefHiddenDrawerItems"; public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify"; @@ -55,7 +54,7 @@ public class UserPreferences implements public static final String PREF_FOLLOW_QUEUE = "prefFollowQueue"; public static final String PREF_AUTO_DELETE = "prefAutoDelete"; public static final String PREF_SMART_MARK_AS_PLAYED_SECS = "prefSmartMarkAsPlayedSecs"; - private static final String PREF_PLAYBACK_SPEED_ARRAY = "prefPlaybackSpeedArray"; + public static final String PREF_PLAYBACK_SPEED_ARRAY = "prefPlaybackSpeedArray"; public static final String PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS = "prefPauseForFocusLoss"; public static final String PREF_RESUME_AFTER_CALL = "prefResumeAfterCall"; @@ -82,188 +81,26 @@ public class UserPreferences implements private static final String PREF_REWIND_SECS = "prefRewindSecs"; public static final String PREF_QUEUE_LOCKED = "prefQueueLocked"; - // TODO: Make this value configurable - private static final float PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD_DEFAULT = 0.8f; - + // Constants private static int EPISODE_CACHE_SIZE_UNLIMITED = -1; - private static UserPreferences instance; - private final Context context; - - // User Interface - private int theme; - private List hiddenDrawerItems; - private int notifyPriority; - private boolean persistNotify; - private boolean showDownloadReport; - - // Queue - private boolean enqueueAtFront; - - // Playback - private boolean pauseOnHeadsetDisconnect; - private boolean unpauseOnHeadsetReconnect; - private boolean followQueue; - private boolean autoDelete; - private int smartMarkAsPlayedSecs; - private String[] playbackSpeedArray; - private boolean pauseForFocusLoss; - private boolean resumeAfterCall; - - // Network - private long updateInterval; - private boolean allowMobileUpdate; - private int parallelDownloads; - private int episodeCacheSize; - private boolean enableAutodownload; - private boolean enableAutodownloadOnBattery; - private boolean enableAutodownloadWifiFilter; - private String[] autodownloadSelectedNetworks; - - // Services - private boolean autoFlattr; - private float autoFlattrPlayedDurationThreshold; - - // Settings somewhere in the GUI - private String playbackSpeed; - private int fastForwardSecs; - private int rewindSecs; - private boolean queueLocked; - - - private UserPreferences(Context context) { - this.context = context; - loadPreferences(); - } + private static Context context; + private static SharedPreferences prefs; /** * Sets up the UserPreferences class. * * @throws IllegalArgumentException if context is null */ - public static void createInstance(Context context) { + public static void init(Context context) { Log.d(TAG, "Creating new instance of UserPreferences"); Validate.notNull(context); - instance = new UserPreferences(context); + UserPreferences.context = context; + UserPreferences.prefs = PreferenceManager.getDefaultSharedPreferences(context); createImportDirectory(); createNoMediaFile(); - PreferenceManager.getDefaultSharedPreferences(context) - .registerOnSharedPreferenceChangeListener(instance); - - } - - private void loadPreferences() { - SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); - - // User Interface - theme = readThemeValue(sp.getString(PREF_THEME, "0")); - if (sp.getBoolean(PREF_EXPANDED_NOTIFICATION, false)) { - notifyPriority = NotificationCompat.PRIORITY_MAX; - } else { - notifyPriority = NotificationCompat.PRIORITY_DEFAULT; - } - hiddenDrawerItems = Arrays.asList(StringUtils.split(sp.getString(PREF_HIDDEN_DRAWER_ITEMS, ""), ',')); - persistNotify = sp.getBoolean(PREF_PERSISTENT_NOTIFICATION, false); - showDownloadReport = sp.getBoolean(PREF_SHOW_DOWNLOAD_REPORT, true); - - // Queue - enqueueAtFront = sp.getBoolean(PREF_QUEUE_ADD_TO_FRONT, false); - - // Playback - pauseOnHeadsetDisconnect = sp.getBoolean(PREF_PAUSE_ON_HEADSET_DISCONNECT, true); - unpauseOnHeadsetReconnect = sp.getBoolean(PREF_UNPAUSE_ON_HEADSET_RECONNECT, true); - followQueue = sp.getBoolean(PREF_FOLLOW_QUEUE, false); - autoDelete = sp.getBoolean(PREF_AUTO_DELETE, false); - smartMarkAsPlayedSecs = Integer.valueOf(sp.getString(PREF_SMART_MARK_AS_PLAYED_SECS, "30")); - playbackSpeedArray = readPlaybackSpeedArray(sp.getString( - PREF_PLAYBACK_SPEED_ARRAY, null)); - pauseForFocusLoss = sp.getBoolean(PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS, false); - - // Network - updateInterval = readUpdateInterval(sp.getString(PREF_UPDATE_INTERVAL, "0")); - allowMobileUpdate = sp.getBoolean(PREF_MOBILE_UPDATE, false); - parallelDownloads = Integer.valueOf(sp.getString(PREF_PARALLEL_DOWNLOADS, "6")); - EPISODE_CACHE_SIZE_UNLIMITED = context.getResources().getInteger( - R.integer.episode_cache_size_unlimited); - episodeCacheSize = readEpisodeCacheSizeInternal(sp.getString(PREF_EPISODE_CACHE_SIZE, "20")); - enableAutodownload = sp.getBoolean(PREF_ENABLE_AUTODL, false); - enableAutodownloadOnBattery = sp.getBoolean(PREF_ENABLE_AUTODL_ON_BATTERY, true); - enableAutodownloadWifiFilter = sp.getBoolean(PREF_ENABLE_AUTODL_WIFI_FILTER, false); - autodownloadSelectedNetworks = StringUtils.split( - sp.getString(PREF_AUTODL_SELECTED_NETWORKS, ""), ','); - - // Services - autoFlattr = sp.getBoolean(PREF_AUTO_FLATTR, false); - autoFlattrPlayedDurationThreshold = sp.getFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD, - PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD_DEFAULT); - - // MediaPlayer - playbackSpeed = sp.getString(PREF_PLAYBACK_SPEED, "1.0"); - fastForwardSecs = sp.getInt(PREF_FAST_FORWARD_SECS, 30); - rewindSecs = sp.getInt(PREF_REWIND_SECS, 30); - queueLocked = sp.getBoolean(PREF_QUEUE_LOCKED, false); - } - - private int readThemeValue(String valueFromPrefs) { - switch (Integer.parseInt(valueFromPrefs)) { - case 0: - return R.style.Theme_AntennaPod_Light; - case 1: - return R.style.Theme_AntennaPod_Dark; - default: - return R.style.Theme_AntennaPod_Light; - } - } - - private long readUpdateInterval(String valueFromPrefs) { - int hours = Integer.parseInt(valueFromPrefs); - return TimeUnit.HOURS.toMillis(hours); - } - - private int readEpisodeCacheSizeInternal(String valueFromPrefs) { - if (valueFromPrefs.equals(context - .getString(R.string.pref_episode_cache_unlimited))) { - return EPISODE_CACHE_SIZE_UNLIMITED; - } else { - return Integer.valueOf(valueFromPrefs); - } - } - - private String[] readPlaybackSpeedArray(String valueFromPrefs) { - String[] selectedSpeeds = null; - // If this preference hasn't been set yet, return the default options - if (valueFromPrefs == null) { - String[] allSpeeds = context.getResources().getStringArray( - R.array.playback_speed_values); - List speedList = new LinkedList(); - for (String speedStr : allSpeeds) { - float speed = Float.parseFloat(speedStr); - if (speed < 2.0001 && speed * 10 % 1 == 0) { - speedList.add(speedStr); - } - } - selectedSpeeds = speedList.toArray(new String[speedList.size()]); - } else { - try { - JSONArray jsonArray = new JSONArray(valueFromPrefs); - selectedSpeeds = new String[jsonArray.length()]; - for (int i = 0; i < jsonArray.length(); i++) { - selectedSpeeds[i] = jsonArray.getString(i); - } - } catch (JSONException e) { - Log.e(TAG, "Got JSON error when trying to get speeds from JSONArray"); - e.printStackTrace(); - } - } - return selectedSpeeds; - } - - private static void instanceAvailable() { - if (instance == null) { - throw new IllegalStateException("UserPreferences was used before being set up"); - } } /** @@ -272,8 +109,7 @@ public class UserPreferences implements * @return R.style.Theme_AntennaPod_Light or R.style.Theme_AntennaPod_Dark */ public static int getTheme() { - instanceAvailable(); - return instance.theme; + return readThemeValue(prefs.getString(PREF_THEME, "0")); } public static int getNoTitleTheme() { @@ -286,8 +122,8 @@ public class UserPreferences implements } public static List getHiddenDrawerItems() { - instanceAvailable(); - return new ArrayList(instance.hiddenDrawerItems); + String hiddenItems = prefs.getString(PREF_HIDDEN_DRAWER_ITEMS, ""); + return new ArrayList(Arrays.asList(StringUtils.split(hiddenItems, ','))); } /** @@ -296,8 +132,11 @@ public class UserPreferences implements * @return NotificationCompat.PRIORITY_MAX or NotificationCompat.PRIORITY_DEFAULT */ public static int getNotifyPriority() { - instanceAvailable(); - return instance.notifyPriority; + if (prefs.getBoolean(PREF_EXPANDED_NOTIFICATION, false)) { + return NotificationCompat.PRIORITY_MAX; + } else { + return NotificationCompat.PRIORITY_DEFAULT; + } } /** @@ -306,8 +145,7 @@ public class UserPreferences implements * @return {@code true} if notifications are persistent, {@code false} otherwise */ public static boolean isPersistNotify() { - instanceAvailable(); - return instance.persistNotify; + return prefs.getBoolean(PREF_PERSISTENT_NOTIFICATION, false); } /** @@ -316,8 +154,7 @@ public class UserPreferences implements * @return {@code true} if download reports are shown, {@code false} otherwise */ public static boolean showDownloadReport() { - instanceAvailable(); - return instance.showDownloadReport; + return prefs.getBoolean(PREF_SHOW_DOWNLOAD_REPORT, true); } /** @@ -326,73 +163,61 @@ public class UserPreferences implements * @return {@code true} if new queue elements are added to the front; {@code false} otherwise */ public static boolean enqueueAtFront() { - instanceAvailable(); - return instance.enqueueAtFront; + return prefs.getBoolean(PREF_QUEUE_ADD_TO_FRONT, false); } public static boolean isPauseOnHeadsetDisconnect() { - instanceAvailable(); - return instance.pauseOnHeadsetDisconnect; + return prefs.getBoolean(PREF_PAUSE_ON_HEADSET_DISCONNECT, true); } public static boolean isUnpauseOnHeadsetReconnect() { - instanceAvailable(); - return instance.unpauseOnHeadsetReconnect; + return prefs.getBoolean(PREF_UNPAUSE_ON_HEADSET_RECONNECT, true); } public static boolean isFollowQueue() { - instanceAvailable(); - return instance.followQueue; + return prefs.getBoolean(PREF_FOLLOW_QUEUE, false); } public static boolean isAutoDelete() { - instanceAvailable(); - return instance.autoDelete; + return prefs.getBoolean(PREF_AUTO_DELETE, false); } public static int getSmartMarkAsPlayedSecs() { - instanceAvailable(); - return instance.smartMarkAsPlayedSecs; + return Integer.valueOf(prefs.getString(PREF_SMART_MARK_AS_PLAYED_SECS, "30")); } public static boolean isAutoFlattr() { - instanceAvailable(); - return instance.autoFlattr; + return prefs.getBoolean(PREF_AUTO_FLATTR, false); } public static String getPlaybackSpeed() { - instanceAvailable(); - return instance.playbackSpeed; + return prefs.getString(PREF_PLAYBACK_SPEED, "1.0"); + } public static String[] getPlaybackSpeedArray() { - instanceAvailable(); - return instance.playbackSpeedArray; + return readPlaybackSpeedArray(prefs.getString(PREF_PLAYBACK_SPEED_ARRAY, null)); } public static boolean shouldPauseForFocusLoss() { - instanceAvailable(); - return instance.pauseForFocusLoss; + return prefs.getBoolean(PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS, false); } public static long getUpdateInterval() { - instanceAvailable(); - return instance.updateInterval; + return readUpdateInterval(prefs.getString(PREF_UPDATE_INTERVAL, "0")); } public static boolean isAllowMobileUpdate() { - instanceAvailable(); - return instance.allowMobileUpdate; + return prefs.getBoolean(PREF_MOBILE_UPDATE, false); } public static int getParallelDownloads() { - instanceAvailable(); - return instance.parallelDownloads; + return Integer.valueOf(prefs.getString(PREF_PARALLEL_DOWNLOADS, "4")); } public static int getEpisodeCacheSizeUnlimited() { - return EPISODE_CACHE_SIZE_UNLIMITED; + return context.getResources().getInteger(R.integer.episode_cache_size_unlimited); } /** @@ -401,33 +226,27 @@ public class UserPreferences implements * 'unlimited'. */ public static int getEpisodeCacheSize() { - instanceAvailable(); - return instance.episodeCacheSize; + return readEpisodeCacheSizeInternal(prefs.getString(PREF_EPISODE_CACHE_SIZE, "20")); } public static boolean isEnableAutodownload() { - instanceAvailable(); - return instance.enableAutodownload; + return prefs.getBoolean(PREF_ENABLE_AUTODL, false); } public static boolean isEnableAutodownloadOnBattery() { - instanceAvailable(); - return instance.enableAutodownloadOnBattery; + return prefs.getBoolean(PREF_ENABLE_AUTODL_ON_BATTERY, true); } public static boolean isEnableAutodownloadWifiFilter() { - instanceAvailable(); - return instance.enableAutodownloadWifiFilter; + return prefs.getBoolean(PREF_ENABLE_AUTODL_WIFI_FILTER, false); } public static int getFastFowardSecs() { - instanceAvailable(); - return instance.fastForwardSecs; + return prefs.getInt(PREF_FAST_FORWARD_SECS, 30); } public static int getRewindSecs() { - instanceAvailable(); - return instance.rewindSecs; + return prefs.getInt(PREF_REWIND_SECS, 30); } @@ -436,148 +255,40 @@ public class UserPreferences implements * duration. */ public static float getAutoFlattrPlayedDurationThreshold() { - instanceAvailable(); - return instance.autoFlattrPlayedDurationThreshold; + return prefs.getFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD, 0.8f); } public static String[] getAutodownloadSelectedNetworks() { - instanceAvailable(); - return instance.autodownloadSelectedNetworks; + String selectedNetWorks = prefs.getString(PREF_AUTODL_SELECTED_NETWORKS, ""); + return StringUtils.split(selectedNetWorks, ','); } public static boolean shouldResumeAfterCall() { - instanceAvailable(); - return instance.resumeAfterCall; + return prefs.getBoolean(PREF_RESUME_AFTER_CALL, true); } public static boolean isQueueLocked() { - instanceAvailable(); - return instance.queueLocked; - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sp, String key) { - Log.d(TAG, "Registered change of user preferences. Key: " + key); - switch(key) { - // User Interface - case PREF_THEME: - theme = readThemeValue(sp.getString(PREF_THEME, "")); - break; - case PREF_HIDDEN_DRAWER_ITEMS: - hiddenDrawerItems = Arrays.asList(StringUtils.split(sp.getString(PREF_HIDDEN_DRAWER_ITEMS, ""), ',')); - break; - case PREF_EXPANDED_NOTIFICATION: - if (sp.getBoolean(PREF_EXPANDED_NOTIFICATION, false)) { - notifyPriority = NotificationCompat.PRIORITY_MAX; - } else { - notifyPriority = NotificationCompat.PRIORITY_DEFAULT; - } - break; - case PREF_PERSISTENT_NOTIFICATION: - persistNotify = sp.getBoolean(PREF_PERSISTENT_NOTIFICATION, false); - break; - case PREF_SHOW_DOWNLOAD_REPORT: - showDownloadReport = sp.getBoolean(PREF_SHOW_DOWNLOAD_REPORT, true); - break; - // Queue - case PREF_QUEUE_ADD_TO_FRONT: - enqueueAtFront = sp.getBoolean(PREF_QUEUE_ADD_TO_FRONT, false); - break; - // Playback - case PREF_PAUSE_ON_HEADSET_DISCONNECT: - pauseOnHeadsetDisconnect = sp.getBoolean(PREF_PAUSE_ON_HEADSET_DISCONNECT, true); - break; - case PREF_UNPAUSE_ON_HEADSET_RECONNECT: - unpauseOnHeadsetReconnect = sp.getBoolean(PREF_UNPAUSE_ON_HEADSET_RECONNECT, true); - break; - case PREF_FOLLOW_QUEUE: - followQueue = sp.getBoolean(PREF_FOLLOW_QUEUE, false); - break; - case PREF_AUTO_DELETE: - autoDelete = sp.getBoolean(PREF_AUTO_DELETE, false); - break; - case PREF_SMART_MARK_AS_PLAYED_SECS: - smartMarkAsPlayedSecs = Integer.valueOf(sp.getString(PREF_SMART_MARK_AS_PLAYED_SECS, "30")); - break; - case PREF_PLAYBACK_SPEED_ARRAY: - playbackSpeedArray = readPlaybackSpeedArray(sp.getString(PREF_PLAYBACK_SPEED_ARRAY, null)); - break; - case PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS: - pauseForFocusLoss = sp.getBoolean(PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS, false); - break; - case PREF_RESUME_AFTER_CALL: - resumeAfterCall = sp.getBoolean(PREF_RESUME_AFTER_CALL, true); - break; - // Network - case PREF_UPDATE_INTERVAL: - updateInterval = readUpdateInterval(sp.getString(PREF_UPDATE_INTERVAL, "0")); - ClientConfig.applicationCallbacks.setUpdateInterval(updateInterval); - break; - case PREF_MOBILE_UPDATE: - allowMobileUpdate = sp.getBoolean(PREF_MOBILE_UPDATE, false); - break; - case PREF_PARALLEL_DOWNLOADS: - parallelDownloads = Integer.valueOf(sp.getString(PREF_PARALLEL_DOWNLOADS, "6")); - break; - case PREF_EPISODE_CACHE_SIZE: - episodeCacheSize = readEpisodeCacheSizeInternal(sp.getString(PREF_EPISODE_CACHE_SIZE, "20")); - break; - case PREF_ENABLE_AUTODL: - enableAutodownload = sp.getBoolean(PREF_ENABLE_AUTODL, false); - break; - case PREF_ENABLE_AUTODL_ON_BATTERY: - enableAutodownloadOnBattery = sp.getBoolean(PREF_ENABLE_AUTODL_ON_BATTERY, true); - break; - case PREF_ENABLE_AUTODL_WIFI_FILTER: - enableAutodownloadWifiFilter = sp.getBoolean(PREF_ENABLE_AUTODL_WIFI_FILTER, false); - break; - case PREF_AUTODL_SELECTED_NETWORKS: - autodownloadSelectedNetworks = StringUtils.split( - sp.getString(PREF_AUTODL_SELECTED_NETWORKS, ""), ','); - break; - // Services - case PREF_AUTO_FLATTR: - autoFlattr = sp.getBoolean(PREF_AUTO_FLATTR, false); - break; - case PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD: - autoFlattrPlayedDurationThreshold = sp.getFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD, - PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD_DEFAULT); - break; - // Mediaplayer - case PREF_PLAYBACK_SPEED: - playbackSpeed = sp.getString(PREF_PLAYBACK_SPEED, "1.0"); - break; - case PREF_FAST_FORWARD_SECS: - fastForwardSecs = sp.getInt(PREF_FAST_FORWARD_SECS, 30); - break; - case PREF_REWIND_SECS: - rewindSecs = sp.getInt(PREF_REWIND_SECS, 30); - break; - case PREF_QUEUE_LOCKED: - queueLocked = sp.getBoolean(PREF_QUEUE_LOCKED, false); - break; - default: - Log.w(TAG, "Unhandled key: " + key); - } + return prefs.getBoolean(PREF_QUEUE_LOCKED, false); } public static void setPrefFastForwardSecs(int secs) { Log.d(TAG, "setPrefFastForwardSecs(" + secs +")"); - SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(instance.context).edit(); + SharedPreferences.Editor editor = prefs.edit(); editor.putInt(PREF_FAST_FORWARD_SECS, secs); editor.commit(); } public static void setPrefRewindSecs(int secs) { Log.d(TAG, "setPrefRewindSecs(" + secs +")"); - SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(instance.context).edit(); - editor.putInt(PREF_REWIND_SECS, secs); - editor.commit(); + prefs.edit() + .putInt(PREF_REWIND_SECS, secs) + .apply(); } public static void setPlaybackSpeed(String speed) { - PreferenceManager.getDefaultSharedPreferences(instance.context).edit() - .putString(PREF_PLAYBACK_SPEED, speed).apply(); + prefs.edit() + .putString(PREF_PLAYBACK_SPEED, speed) + .apply(); } public static void setPlaybackSpeedArray(String[] speeds) { @@ -585,72 +296,105 @@ public class UserPreferences implements for (String speed : speeds) { jsonArray.put(speed); } - PreferenceManager.getDefaultSharedPreferences(instance.context).edit() - .putString(PREF_PLAYBACK_SPEED_ARRAY, jsonArray.toString()) - .apply(); - } - - public static void setAutodownloadSelectedNetworks(Context context, - String[] value) { - SharedPreferences.Editor editor = PreferenceManager - .getDefaultSharedPreferences(context.getApplicationContext()) - .edit(); - editor.putString(PREF_AUTODL_SELECTED_NETWORKS, - StringUtils.join(value, ',')); - editor.commit(); + prefs.edit() + .putString(PREF_PLAYBACK_SPEED_ARRAY, jsonArray.toString()) + .apply(); + } + + public static void setAutodownloadSelectedNetworks(String[] value) { + prefs.edit() + .putString(PREF_AUTODL_SELECTED_NETWORKS, StringUtils.join(value, ',')) + .apply(); } /** * Sets the update interval value. Should only be used for testing purposes! */ - public static void setUpdateInterval(Context context, long newValue) { - instanceAvailable(); - SharedPreferences.Editor editor = PreferenceManager - .getDefaultSharedPreferences(context.getApplicationContext()) - .edit(); - editor.putString(PREF_UPDATE_INTERVAL, - String.valueOf(newValue)); - editor.commit(); - instance.updateInterval = newValue; + public static void setUpdateInterval(long hours) { + prefs.edit() + .putString(PREF_UPDATE_INTERVAL, String.valueOf(hours)) + .apply(); + restartUpdateAlarm(TimeUnit.HOURS.toMillis(hours), TimeUnit.HOURS.toMillis(hours)); } /** * Change the auto-flattr settings * - * @param context For accessing the shared preferences * @param enabled Whether automatic flattring should be enabled at all * @param autoFlattrThreshold The percentage of playback time after which an episode should be * flattrd. Must be a value between 0 and 1 (inclusive) * */ - public static void setAutoFlattrSettings(Context context, boolean enabled, float autoFlattrThreshold) { - instanceAvailable(); + public static void setAutoFlattrSettings( boolean enabled, float autoFlattrThreshold) { Validate.inclusiveBetween(0.0, 1.0, autoFlattrThreshold); - PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()) - .edit() - .putBoolean(PREF_AUTO_FLATTR, enabled) - .putFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD, autoFlattrThreshold) - .commit(); - instance.autoFlattr = enabled; - instance.autoFlattrPlayedDurationThreshold = autoFlattrThreshold; + prefs.edit() + .putBoolean(PREF_AUTO_FLATTR, enabled) + .putFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD, autoFlattrThreshold) + .apply(); } public static void setHiddenDrawerItems(Context context, List items) { - instanceAvailable(); - instance.hiddenDrawerItems = items; String str = StringUtils.join(items, ','); - PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()) - .edit() - .putString(PREF_HIDDEN_DRAWER_ITEMS, str) - .commit(); + prefs.edit() + .putString(PREF_HIDDEN_DRAWER_ITEMS, str) + .apply(); } public static void setQueueLocked(boolean locked) { - instanceAvailable(); - instance.queueLocked = locked; - PreferenceManager.getDefaultSharedPreferences(instance.context) - .edit() - .putBoolean(PREF_QUEUE_LOCKED, locked) - .commit(); + prefs.edit() + .putBoolean(PREF_QUEUE_LOCKED, locked) + .apply(); + } + + private static int readThemeValue(String valueFromPrefs) { + switch (Integer.parseInt(valueFromPrefs)) { + case 0: + return R.style.Theme_AntennaPod_Light; + case 1: + return R.style.Theme_AntennaPod_Dark; + default: + return R.style.Theme_AntennaPod_Light; + } + } + + private static long readUpdateInterval(String valueFromPrefs) { + int hours = Integer.parseInt(valueFromPrefs); + return TimeUnit.HOURS.toMillis(hours); + } + + private static int readEpisodeCacheSizeInternal(String valueFromPrefs) { + if (valueFromPrefs.equals(context.getString(R.string.pref_episode_cache_unlimited))) { + return EPISODE_CACHE_SIZE_UNLIMITED; + } else { + return Integer.valueOf(valueFromPrefs); + } + } + + private static String[] readPlaybackSpeedArray(String valueFromPrefs) { + String[] selectedSpeeds = null; + // If this preference hasn't been set yet, return the default options + if (valueFromPrefs == null) { + String[] allSpeeds = context.getResources().getStringArray(R.array.playback_speed_values); + List speedList = new LinkedList(); + for (String speedStr : allSpeeds) { + float speed = Float.parseFloat(speedStr); + if (speed < 2.0001 && speed * 10 % 1 == 0) { + speedList.add(speedStr); + } + } + selectedSpeeds = speedList.toArray(new String[speedList.size()]); + } else { + try { + JSONArray jsonArray = new JSONArray(valueFromPrefs); + selectedSpeeds = new String[jsonArray.length()]; + for (int i = 0; i < jsonArray.length(); i++) { + selectedSpeeds[i] = jsonArray.getString(i); + } + } catch (JSONException e) { + Log.e(TAG, "Got JSON error when trying to get speeds from JSONArray"); + e.printStackTrace(); + } + } + return selectedSpeeds; } @@ -664,9 +408,6 @@ public class UserPreferences implements * could not be created. */ public static File getDataFolder(Context context, String type) { - instanceAvailable(); - SharedPreferences prefs = PreferenceManager - .getDefaultSharedPreferences(context.getApplicationContext()); String strDir = prefs.getString(PREF_DATA_FOLDER, null); if (strDir == null) { Log.d(TAG, "Using default data folder"); @@ -712,12 +453,9 @@ public class UserPreferences implements public static void setDataFolder(String dir) { Log.d(TAG, "Result from DirectoryChooser: " + dir); - instanceAvailable(); - SharedPreferences prefs = PreferenceManager - .getDefaultSharedPreferences(instance.context); - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(PREF_DATA_FOLDER, dir); - editor.commit(); + prefs.edit() + .putString(PREF_DATA_FOLDER, dir) + .apply(); createImportDirectory(); } @@ -725,8 +463,7 @@ public class UserPreferences implements * Create a .nomedia file to prevent scanning by the media scanner. */ private static void createNoMediaFile() { - File f = new File(instance.context.getExternalFilesDir(null), - ".nomedia"); + File f = new File(context.getExternalFilesDir(null), ".nomedia"); if (!f.exists()) { try { f.createNewFile(); @@ -743,8 +480,7 @@ public class UserPreferences implements * available */ private static void createImportDirectory() { - File importDir = getDataFolder(instance.context, - IMPORT_DIR); + File importDir = getDataFolder(context, IMPORT_DIR); if (importDir != null) { if (importDir.exists()) { Log.d(TAG, "Import directory already exists"); @@ -761,12 +497,10 @@ public class UserPreferences implements * Updates alarm registered with the AlarmManager service or deactivates it. */ public static void restartUpdateAlarm(long triggerAtMillis, long intervalMillis) { - instanceAvailable(); Log.d(TAG, "Restarting update alarm."); - AlarmManager alarmManager = (AlarmManager) instance.context - .getSystemService(Context.ALARM_SERVICE); - PendingIntent updateIntent = PendingIntent.getBroadcast( - instance.context, 0, new Intent(ClientConfig.applicationCallbacks.getApplicationInstance(), FeedUpdateReceiver.class), 0); + AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + PendingIntent updateIntent = PendingIntent.getBroadcast(context, 0, + new Intent(ClientConfig.applicationCallbacks.getApplicationInstance(), FeedUpdateReceiver.class), 0); alarmManager.cancel(updateIntent); if (intervalMillis != 0) { alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtMillis, intervalMillis, @@ -777,12 +511,11 @@ public class UserPreferences implements } } - /** * Reads episode cache size as it is saved in the episode_cache_size_values array. */ public static int readEpisodeCacheSize(String valueFromPrefs) { - instanceAvailable(); - return instance.readEpisodeCacheSizeInternal(valueFromPrefs); + return readEpisodeCacheSizeInternal(valueFromPrefs); } + } 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 4a329c2f6..95c033dc5 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 @@ -124,8 +124,7 @@ public final class DBReader { * can be loaded separately with {@link #getFeedItemList(android.content.Context, de.danoeh.antennapod.core.feed.Feed)}. */ public static List getExpiredFeedsList(final Context context, final long expirationTime) { - if (BuildConfig.DEBUG) - Log.d(TAG, String.format("getExpiredFeedsList(%d)", expirationTime)); + Log.d(TAG, String.format("getExpiredFeedsList(%d)", expirationTime)); PodDBAdapter adapter = new PodDBAdapter(context); adapter.open(); 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 defce5930..711cd773e 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 @@ -199,11 +199,8 @@ public final class DBTasks { */ public static List getExpiredFeeds(final Context context) { long millis = UserPreferences.getUpdateInterval(); - if (millis > 0) { - - List feedList = DBReader.getExpiredFeedsList(context, - millis); + List feedList = DBReader.getExpiredFeedsList(context, millis); if (feedList.size() > 0) { refreshFeeds(context, feedList); } -- cgit v1.2.3 From f2dd49d533475a9486ed00ba88abf30489b59519 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 23 Jun 2015 20:05:12 -0400 Subject: Return NULL instead of result when unable to load bitmap. There are still cases where 'bitmap' could be null. We shouldn't return a result when that's the case. Returnning null appears to be supported by Picasso. (see Picasso.NetworkRequestHandler) Fixes AntennaPod/AntennaPod#947 --- .../java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java index 09fe0d654..8e47a5b71 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java @@ -170,6 +170,12 @@ public class PicassoProvider { bitmap = decodeStreamFromFile(data, fallback); } } + + if (bitmap == null) { + Log.e(TAG, "Could not load media"); + return null; + } + return new Result(bitmap, Picasso.LoadedFrom.DISK); } -- cgit v1.2.3 From bf3ef27b384162cfe55694937b7d8e0c0e109dfc Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Wed, 24 Jun 2015 11:53:10 +0200 Subject: Cache DateTime parser --- core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java index 10512dd48..7b06128f9 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java @@ -16,6 +16,11 @@ public class DateUtils { private static final String TAG = "DateUtils"; + private static final SimpleDateFormat parser = new SimpleDateFormat("", Locale.US); + static { + parser.setLenient(false); + } + public static Date parse(final String input) { if(input == null) { throw new IllegalArgumentException("Date most not be null"); @@ -61,8 +66,7 @@ public class DateUtils { "yyyy-MM-ddZ", "yyyy-MM-dd" }; - SimpleDateFormat parser = new SimpleDateFormat("", Locale.US); - parser.setLenient(false); + ParsePosition pos = new ParsePosition(0); for(String pattern : patterns) { parser.applyPattern(pattern); -- cgit v1.2.3 From 717a6a645e3e9dfbcef7d3dd6b509be98c68ef22 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Wed, 24 Jun 2015 17:43:50 +0200 Subject: Set update interval or time of day --- .../core/preferences/UserPreferences.java | 68 ++++++++++++++++++++-- core/src/main/res/values/arrays.xml | 11 ---- core/src/main/res/values/strings.xml | 8 ++- 3 files changed, 69 insertions(+), 18 deletions(-) (limited to 'core/src') 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 5d53db5b3..d96d25fc2 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 @@ -19,6 +19,7 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; import java.util.LinkedList; import java.util.List; import java.util.concurrent.TimeUnit; @@ -206,7 +207,24 @@ public class UserPreferences { } public static long getUpdateInterval() { - return readUpdateInterval(prefs.getString(PREF_UPDATE_INTERVAL, "0")); + String updateInterval = prefs.getString(PREF_UPDATE_INTERVAL, "0"); + if(false == updateInterval.contains(":")) { + return readUpdateInterval(updateInterval); + } else { + return 0; + } + } + + public static int[] getUpdateTimeOfDay() { + String datetime = prefs.getString(PREF_UPDATE_INTERVAL, ""); + if(datetime.length() >= 3 && datetime.contains(":")) { + String[] parts = datetime.split(":"); + int hourOfDay = Integer.valueOf(parts[0]); + int minute = Integer.valueOf(parts[1]); + return new int[] { hourOfDay, minute }; + } else { + return new int[0]; + } } public static boolean isAllowMobileUpdate() { @@ -316,6 +334,16 @@ public class UserPreferences { restartUpdateAlarm(); } + /** + * Sets the update interval value. Should only be used for testing purposes! + */ + public static void setUpdateTimeOfDay(int hourOfDay, int minute) { + prefs.edit() + .putString(PREF_UPDATE_INTERVAL, hourOfDay + ":" + minute) + .apply(); + restartUpdateAlarm(); + } + /** * Change the auto-flattr settings * @@ -493,14 +521,19 @@ public class UserPreferences { } public static void restartUpdateAlarm() { - long hours = getUpdateInterval(); - restartUpdateAlarm(TimeUnit.SECONDS.toMillis(10), hours); + int[] timeOfDay = getUpdateTimeOfDay(); + if (timeOfDay.length == 2) { + restartUpdateTimeOfDayAlarm(timeOfDay[0], timeOfDay[1]); + } else { + long hours = getUpdateInterval(); + restartUpdateIntervalAlarm(TimeUnit.SECONDS.toMillis(10), hours); + } } /** - * Updates alarm registered with the AlarmManager service or deactivates it. + * Sets the interval in which the feeds are refreshed automatically */ - public static void restartUpdateAlarm(long triggerAtMillis, long intervalMillis) { + public static void restartUpdateIntervalAlarm(long triggerAtMillis, long intervalMillis) { Log.d(TAG, "Restarting update alarm."); AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); PendingIntent updateIntent = PendingIntent.getBroadcast(context, 0, @@ -517,6 +550,31 @@ public class UserPreferences { } } + /** + * Sets time of day the feeds are refreshed automatically + */ + public static void restartUpdateTimeOfDayAlarm(int hoursOfDay, int minute) { + Log.d(TAG, "Restarting update alarm."); + AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + PendingIntent updateIntent = PendingIntent.getBroadcast(context, 0, + new Intent(ClientConfig.applicationCallbacks.getApplicationInstance(), FeedUpdateReceiver.class), 0); + alarmManager.cancel(updateIntent); + + Calendar now = Calendar.getInstance(); + Calendar alarm = (Calendar)now.clone(); + alarm.set(Calendar.HOUR_OF_DAY, hoursOfDay); + alarm.set(Calendar.MINUTE, minute); + if(alarm.before(now)) { + alarm.add(Calendar.DATE, 1); + } + + alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, + alarm.getTimeInMillis(), + AlarmManager.INTERVAL_DAY, + updateIntent); + Log.d(TAG, "Changed alarm to new time of day " + hoursOfDay + ":" + minute); + } + /** * Reads episode cache size as it is saved in the episode_cache_size_values array. */ diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 4ecf2cf61..afcb31078 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -20,18 +20,7 @@ 60 - - Manual - 1 hour - 2 hours - 4 hours - 8 hours - 12 hours - 24 hours - - - 0 1 2 4 diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index c2147cccc..0f1830202 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -253,8 +253,12 @@ Smart mark as played Playback Network - Update Interval - Specify an interval in which the feeds are refreshed automatically or disable it + Update Interval or Time of Day + Specify an interval or a specific time of day to refresh the feeds automatically + You can set an interval like \"every 2 hours\", set a specific time of day like \"7:00 AM\" or disable automatic updates altogether.\n\nPlease note: Update times are inexact. You may encounter a short delay." + Disable + Set Interval + Set Time of Day Download media files only over WiFi Continuous Playback WiFi media download -- cgit v1.2.3 From e3d0f8fbe51c95c26e03ecdbdcd2e3a869117fd4 Mon Sep 17 00:00:00 2001 From: Simon Schubert <2@0x2c.org> Date: Thu, 25 Jun 2015 11:12:59 +0200 Subject: gpoddernet: do not crash on unknown remote actions According to [1] and my own episode actions feed, "action":"flattr" is a valid action. Future-proof the episode actions code by ignoring actions that we don't know and care about. This fixes the java.lang.IllegalArgumentException: FLATTR is not a constant exception when fetching the episode actions list. [1]: https://gpoddernet.readthedocs.org/en/latest/api/reference/events.html --- .../antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java index bd6210d13..efe39485e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java +++ b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java @@ -93,7 +93,12 @@ public class GpodnetEpisodeAction { if(StringUtils.isEmpty(podcast) || StringUtils.isEmpty(episode) || StringUtils.isEmpty(actionString)) { return null; } - GpodnetEpisodeAction.Action action = GpodnetEpisodeAction.Action.valueOf(actionString.toUpperCase()); + GpodnetEpisodeAction.Action action; + try { + action = GpodnetEpisodeAction.Action.valueOf(actionString.toUpperCase()); + } catch (IllegalArgumentException e) { + return null; + } String deviceId = object.optString("device", ""); GpodnetEpisodeAction.Builder builder = new GpodnetEpisodeAction.Builder(podcast, episode, action) .deviceId(deviceId); -- cgit v1.2.3 From d4fb1b09686cb998c850dc52abb9654e27bd31e9 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 27 Jun 2015 09:25:24 -0400 Subject: Return a copy of the downloads. This should prevent any IndexOutOfBounds errors fixes AntennaPod/AntennaPod#968 --- .../danoeh/antennapod/core/service/download/DownloadService.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 03e323aa3..1ad4a9d0d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -243,7 +243,7 @@ public class DownloadService extends Service { handler = new Handler(); newMediaFiles = Collections.synchronizedList(new ArrayList()); reportQueue = Collections.synchronizedList(new ArrayList()); - downloads = new ArrayList(); + downloads = Collections.synchronizedList(new ArrayList()); numberOfDownloads = new AtomicInteger(0); IntentFilter cancelDownloadReceiverFilter = new IntentFilter(); @@ -1246,7 +1246,10 @@ public class DownloadService extends Service { } public List getDownloads() { - return downloads; + // return a copy of downloads, but the copy doesn't need to be synchronized. + synchronized (downloads) { + return new ArrayList(downloads); + } } } -- cgit v1.2.3 From 8399da878faff6f6b649ad4c893f212e3f9beb7b Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 27 Jun 2015 10:05:33 -0400 Subject: Guard use of 'media' It can be null in this class, so we should make sure it isn't accessed if it is. fixes AntennaPod/AntennaPod#972 --- .../de/danoeh/antennapod/core/util/playback/PlaybackController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src') 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 a0d12d3e7..ba5428b81 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 @@ -555,7 +555,7 @@ public abstract class PlaybackController { * Should be used by classes which implement the OnSeekBarChanged interface. */ public void onSeekBarStopTrackingTouch(SeekBar seekBar, float prog) { - if (playbackService != null) { + if (playbackService != null && media != null) { playbackService.seekTo((int) (prog * media.getDuration())); setupPositionObserver(); } -- cgit v1.2.3 From c64217e2b485f3c6b997a55b1ef910c8b72779d3 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 26 Jun 2015 02:39:22 +0200 Subject: Add episode action fragment --- .../danoeh/antennapod/core/storage/DBWriter.java | 14 +++++++++--- core/src/main/res/values/strings.xml | 25 +++++++++++++++++++++- 2 files changed, 35 insertions(+), 4 deletions(-) (limited to 'core/src') 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 feeee48c5..7d60746e1 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 @@ -375,14 +375,21 @@ public class DBWriter { } + public static Future addQueueItem(final Context context, + final long... itemIds) { + return addQueueItem(context, false, itemIds); + } + + /** * Appends FeedItem objects to the end of the queue. The 'read'-attribute of all items will be set to true. * If a FeedItem is already in the queue, the FeedItem will not change its position in the queue. * * @param context A context that is used for opening a database connection. + * @param performAutoDownload true if an auto-download process should be started after the operation. * @param itemIds IDs of the FeedItem objects that should be added to the queue. */ - public static Future addQueueItem(final Context context, + public static Future addQueueItem(final Context context, final boolean performAutoDownload, final long... itemIds) { return dbExec.submit(new Runnable() { @@ -423,11 +430,12 @@ public class DBWriter { } } adapter.close(); - DBTasks.autodownloadUndownloadedItems(context); + if (performAutoDownload) { + DBTasks.autodownloadUndownloadedItems(context); + } } } }); - } /** diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 0f1830202..7ee026fa2 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -96,6 +96,7 @@ Removing Feed Refresh complete Feed Hide Episodes + Apply actions Unplayed Paused Played @@ -115,8 +116,8 @@ Remove Remove Episode Mark as played - Mark as unplayed Marked as played + Mark as unplayed Add to Queue Added to Queue Remove from Queue @@ -346,6 +347,7 @@ The import directory is empty. Select all Deselect all + Select ... From local filesystem Use external application OPML export @@ -450,4 +452,25 @@ Importing subscriptions from single-purpose apps… Search iTunes + + Select ... + All + Selected all Episodes + None + Deselected all Episodes + Played + Selected played Episodes + Unplayed + Selected unplayed Episodes + Downloaded + Selected downloaded Episodes + Unplayed + Selected not downloaded Episodes + Sort by ... + Title (A \u2192 Z) + Title (Z \u2192 A) + Date (New \u2192 Old) + Date (Old \u2192 New) + Duration (Short \u2192 Long) + Duration (Long \u2192 Short) -- cgit v1.2.3 From 473444291f68c7f8a205712c1b51fad74b0b1420 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 27 Jun 2015 14:55:48 -0400 Subject: Folks weren't always getting the updated copy of the download list, now they are. fixes AntennaPod/AntennaPod#968 --- .../antennapod/core/asynctask/DownloadObserver.java | 15 +++++++++------ .../antennapod/core/service/download/DownloadService.java | 7 +++++++ 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java index a13130082..85b1f699f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java @@ -12,6 +12,7 @@ import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.service.download.Downloader; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; @@ -85,15 +86,15 @@ public class DownloadObserver { if (downloadService == null) { connectToDownloadService(); } - callback.onContentChanged(); + if (downloadService != null) { + callback.onContentChanged(downloadService.getDownloads()); + } startRefresher(); } }; public interface Callback { - void onContentChanged(); - - void onDownloadDataAvailable(List downloaderList); + void onContentChanged(List downloaderList); } private void connectToDownloadService() { @@ -116,7 +117,7 @@ public class DownloadObserver { Log.d(TAG, "Connection to service established"); List downloaderList = downloadService.getDownloads(); if (downloaderList != null && !downloaderList.isEmpty()) { - callback.onDownloadDataAvailable(downloaderList); + callback.onContentChanged(downloaderList); startRefresher(); } } @@ -156,12 +157,14 @@ public class DownloadObserver { handler.post(new Runnable() { @Override public void run() { - callback.onContentChanged(); if (downloadService != null) { List downloaderList = downloadService.getDownloads(); + callback.onContentChanged(downloaderList); if (downloaderList == null || downloaderList.isEmpty()) { Thread.currentThread().interrupt(); } + } else { + callback.onContentChanged(new ArrayList()); } } }); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 1ad4a9d0d..238cad763 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -435,6 +435,7 @@ public class DownloadService extends Service { } else { Log.e(TAG, "Could not cancel download with url " + url); } + sendBroadcast(new Intent(ACTION_DOWNLOADS_CONTENT_CHANGED)); } else if (StringUtils.equals(intent.getAction(), ACTION_CANCEL_ALL_DOWNLOADS)) { for (Downloader d : downloads) { @@ -1246,6 +1247,12 @@ public class DownloadService extends Service { } public List getDownloads() { + if (downloads == null) { + // this is unusual, but it should be OK, we'll return + // an empty list to make it easy for people + return new ArrayList(); + } + // return a copy of downloads, but the copy doesn't need to be synchronized. synchronized (downloads) { return new ArrayList(downloads); -- cgit v1.2.3 From 957497d787e1268e09b629de42db8a689a3edd0e Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 27 Jun 2015 22:17:18 +0200 Subject: Enqueue and items in the currently display order, submit changes on bulk --- .../de/danoeh/antennapod/core/storage/DBWriter.java | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'core/src') 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 7d60746e1..2c403d9ca 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 @@ -603,16 +603,24 @@ public class DBWriter { adapter.close(); } - /** - * Sets the 'read'-attribute of a FeedItem to the specified value. + /* + * Sets the 'read'-attribute of all specified FeedItems * * @param context A context that is used for opening a database connection. - * @param itemId ID of the FeedItem * @param read New value of the 'read'-attribute + * @param itemIds IDs of the FeedItems. */ - public static Future markItemRead(final Context context, final long itemId, - final boolean read) { - return markItemRead(context, itemId, read, 0, false); + public static Future markItemRead(final Context context, final boolean read, final long... itemIds) { + return dbExec.submit(new Runnable() { + @Override + public void run() { + final PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + adapter.setFeedItemRead(read, itemIds); + adapter.close(); + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + } + }); } -- cgit v1.2.3 From 23e1594165f8d3d67f00d7076db237becd1b7c33 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 27 Jun 2015 17:05:19 -0400 Subject: need to handle cases where the download service is gone --- .../java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java index 85b1f699f..732fa2d27 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java @@ -88,6 +88,9 @@ public class DownloadObserver { } if (downloadService != null) { callback.onContentChanged(downloadService.getDownloads()); + } else { + // the service is gone, there are no more downloads. + callback.onContentChanged(new ArrayList()); } startRefresher(); } -- cgit v1.2.3 From c7256d8152cf062c8e608b87e62f645ef2c72642 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 28 Jun 2015 21:53:40 +0200 Subject: Fix enqueueing order, prevent NPEs --- core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java | 2 +- core/src/main/res/values/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'core/src') 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 2c403d9ca..e103007e3 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 @@ -415,7 +415,7 @@ public class DBWriter { boolean addToFront = UserPreferences.enqueueAtFront(); if(addToFront){ - queue.add(0, item); + queue.add(0+i, item); } else { queue.add(item); } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 7ee026fa2..00d7ed1bd 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -464,7 +464,7 @@ Selected unplayed Episodes Downloaded Selected downloaded Episodes - Unplayed + Not downloaded Selected not downloaded Episodes Sort by ... Title (A \u2192 Z) -- cgit v1.2.3 From 5178de86810594342b283565584cbc21f0983a5d Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Tue, 23 Jun 2015 18:34:03 +0200 Subject: Make new explicit --- .../de/danoeh/antennapod/core/feed/FeedItem.java | 43 ++++++++---- .../antennapod/core/feed/FeedItemFilter.java | 4 +- .../de/danoeh/antennapod/core/feed/FeedMedia.java | 6 ++ .../core/service/download/DownloadService.java | 2 +- .../core/storage/APCleanupAlgorithm.java | 2 +- .../danoeh/antennapod/core/storage/DBReader.java | 19 +---- .../de/danoeh/antennapod/core/storage/DBTasks.java | 12 ++-- .../danoeh/antennapod/core/storage/DBWriter.java | 14 ++-- .../antennapod/core/storage/PodDBAdapter.java | 82 +++++++++------------- 9 files changed, 85 insertions(+), 99 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java index 1168c60e4..e93aea9ac 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java @@ -44,7 +44,11 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr private Feed feed; private long feedId; - private boolean read; + private int state; + public final static int NEW = -1; + public final static int UNPLAYED = 0; + public final static int PLAYED = 1; + private String paymentLink; private FlattrStatus flattrStatus; @@ -66,7 +70,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr private boolean autoDownload = true; public FeedItem() { - this.read = true; + this.state = UNPLAYED; this.flattrStatus = new FlattrStatus(); this.hasChapters = false; } @@ -75,7 +79,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr * This constructor is used by DBReader. * */ public FeedItem(long id, String title, String link, Date pubDate, String paymentLink, long feedId, - FlattrStatus flattrStatus, boolean hasChapters, FeedImage image, boolean read, + FlattrStatus flattrStatus, boolean hasChapters, FeedImage image, int state, String itemIdentifier, boolean autoDownload) { this.id = id; this.title = title; @@ -86,7 +90,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr this.flattrStatus = flattrStatus; this.hasChapters = hasChapters; this.image = image; - this.read = read; + this.state = state; this.itemIdentifier = itemIdentifier; this.autoDownload = autoDownload; } @@ -94,13 +98,13 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr /** * This constructor should be used for creating test objects. */ - public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, boolean read, Feed feed) { + public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, int state, Feed feed) { this.id = id; this.title = title; this.itemIdentifier = itemIdentifier; this.link = link; this.pubDate = (pubDate != null) ? (Date) pubDate.clone() : null; - this.read = read; + this.state = state; this.feed = feed; this.flattrStatus = new FlattrStatus(); this.hasChapters = false; @@ -109,13 +113,13 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr /** * This constructor should be used for creating test objects involving chapter marks. */ - public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, boolean read, Feed feed, boolean hasChapters) { + public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, int read, Feed feed, boolean hasChapters) { this.id = id; this.title = title; this.itemIdentifier = itemIdentifier; this.link = link; this.pubDate = (pubDate != null) ? (Date) pubDate.clone() : null; - this.read = read; + this.state = state; this.feed = feed; this.flattrStatus = new FlattrStatus(); this.hasChapters = hasChapters; @@ -238,12 +242,25 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr this.feed = feed; } - public boolean isRead() { - return read; + public boolean isNew() { + return state == NEW; + } + + + public void setNew() { + state = NEW; + } + + public boolean isPlayed() { + return state == PLAYED; } - public void setRead(boolean read) { - this.read = read; + public void setPlayed(boolean played) { + if(played) { + state = PLAYED; + } else { + state = UNPLAYED; + } } private boolean isInProgress() { @@ -342,7 +359,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr return State.IN_PROGRESS; } } - return (isRead() ? State.READ : State.UNREAD); + return (isPlayed() ? State.READ : State.UNREAD); } public long getFeedId() { diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java index 4ad084b39..2fd5666c8 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java @@ -61,9 +61,9 @@ public class FeedItemFilter { } List result = new ArrayList(); for(FeedItem item : items) { - if(hideUnplayed && false == item.isRead()) continue; + if(hideUnplayed && false == item.isPlayed()) continue; if(hidePaused && item.getState() == FeedItem.State.IN_PROGRESS) continue; - if(hidePlayed && item.isRead()) continue; + if(hidePlayed && item.isPlayed()) continue; boolean isQueued = DBReader.getQueueIDList(context).contains(item.getId()); if(hideQueued && isQueued) continue; if(hideNotQueued && false == isQueued) continue; 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 b4cca505c..bd5fc58b8 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 @@ -186,6 +186,9 @@ public class FeedMedia extends FeedFile implements Playable { public void setPosition(int position) { this.position = position; + if(position > 0) { + this.item.setPlayed(false); + } } public long getSize() { @@ -447,6 +450,9 @@ public class FeedMedia extends FeedFile implements Playable { @Override public void setDownloaded(boolean downloaded) { super.setDownloaded(downloaded); + if(downloaded) { + item.setPlayed(false); + } } @Override diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 238cad763..7fb878680 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -815,7 +815,7 @@ public class DownloadService extends Service { e.printStackTrace(); } } - if (!item.isRead() && item.hasMedia() && !item.getMedia().isDownloaded()) { + if (!item.isPlayed() && item.hasMedia() && !item.getMedia().isDownloaded()) { newMediaFiles.add(item.getMedia().getId()); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java index f647fd537..a07705e69 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java @@ -28,7 +28,7 @@ public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm { List delete; for (FeedItem item : downloadedItems) { if (item.hasMedia() && item.getMedia().isDownloaded() - && !queue.contains(item.getId()) && item.isRead()) { + && !queue.contains(item.getId()) && item.isPlayed()) { candidates.add(item); } 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 95c033dc5..0347c1b72 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 @@ -229,7 +229,7 @@ public final class DBReader { new FlattrStatus(itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_FLATTR_STATUS)), itemlistCursor.getInt(PodDBAdapter.IDX_FI_SMALL_HAS_CHAPTERS) > 0, image, - (itemlistCursor.getInt(PodDBAdapter.IDX_FI_SMALL_READ) > 0), + itemlistCursor.getInt(PodDBAdapter.IDX_FI_SMALL_READ), itemlistCursor.getString(PodDBAdapter.IDX_FI_SMALL_ITEM_IDENTIFIER), itemlistCursor.getInt(itemlistCursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DOWNLOAD)) > 0 ); @@ -481,8 +481,7 @@ public final class DBReader { * Loads a list of FeedItems whose 'read'-attribute is set to false. * * @param context A context that is used for opening a database connection. - * @return A list of FeedItems whose 'read'-attribute it set to false. If the FeedItems in the list are not used, - * consider using {@link #getUnreadItemIds(android.content.Context)} instead. + * @return A list of FeedItems whose 'read'-attribute it set to false. */ public static List getUnreadItemsList(Context context) { if (BuildConfig.DEBUG) @@ -1012,20 +1011,6 @@ public final class DBReader { return result; } - /** - * Returns a map containing the number of unread items per feed - * - * @param context A context that is used for opening a database connection. - * @return The number of unread items per feed. - */ - public static LongIntMap getNumberOfUnreadFeedItems(final Context context, long... feedIds) { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - final LongIntMap result = adapter.getNumberOfUnreadFeedItems(feedIds); - adapter.close(); - return result; - } - /** * Searches the DB for a FeedImage of the given id. * 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 711cd773e..9273cf11e 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 @@ -561,7 +561,7 @@ public final class DBTasks { // all new feeds will have the most recent item marked as unplayed FeedItem mostRecent = newFeed.getMostRecentItem(); if (mostRecent != null) { - mostRecent.setRead(false); + mostRecent.setNew(); } newFeedsList.add(newFeed); @@ -572,16 +572,16 @@ public final class DBTasks { Collections.sort(newFeed.getItems(), new FeedItemPubdateComparator()); - final boolean markNewItemsAsUnread; + final boolean markNewItems; if (newFeed.getPageNr() == savedFeed.getPageNr()) { if (savedFeed.compareWithOther(newFeed)) { Log.d(TAG, "Feed has updated attribute values. Updating old feed's attributes"); savedFeed.updateFromOther(newFeed); } - markNewItemsAsUnread = true; + markNewItems = true; } else { Log.d(TAG, "New feed has a higher page number. Merging without marking as unread"); - markNewItemsAsUnread = false; + markNewItems = false; savedFeed.setNextPageLink(newFeed.getNextPageLink()); } if (savedFeed.getPreferences().compareWithOther(newFeed.getPreferences())) { @@ -599,8 +599,8 @@ public final class DBTasks { item.setFeed(savedFeed); item.setAutoDownload(savedFeed.getPreferences().getAutoDownload()); savedFeed.getItems().add(i, item); - if (markNewItemsAsUnread) { - item.setRead(false); + if (markNewItems) { + item.setNew(); } } else { oldItem.updateFromOther(item); 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 e103007e3..278d897b6 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 @@ -16,7 +16,6 @@ import java.net.URLEncoder; import java.util.Collections; import java.util.Comparator; import java.util.Date; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; @@ -352,7 +351,7 @@ public class DBWriter { final PodDBAdapter adapter = new PodDBAdapter(context); adapter.open(); final List queue = DBReader.getQueue(context, adapter); - FeedItem item = null; + FeedItem item; if (queue != null) { if (!itemListContains(queue, itemId)) { @@ -403,23 +402,18 @@ public class DBWriter { if (queue != null) { boolean queueModified = false; - boolean unreadItemsModified = false; - List itemsToSave = new LinkedList(); for (int i = 0; i < itemIds.length; i++) { if (!itemListContains(queue, itemIds[i])) { - final FeedItem item = DBReader.getFeedItem( - context, itemIds[i]); + final FeedItem item = DBReader.getFeedItem(context, itemIds[i]); if (item != null) { // add item to either front ot back of queue boolean addToFront = UserPreferences.enqueueAtFront(); - if(addToFront){ queue.add(0+i, item); } else { queue.add(item); } - queueModified = true; } } @@ -677,7 +671,7 @@ public class DBWriter { itemCursor.moveToNext(); } itemCursor.close(); - adapter.setFeedItemRead(true, itemIds); + adapter.setFeedItemRead(FeedItem.PLAYED, itemIds); adapter.close(); EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); @@ -706,7 +700,7 @@ public class DBWriter { itemCursor.moveToNext(); } itemCursor.close(); - adapter.setFeedItemRead(true, itemIds); + adapter.setFeedItemRead(FeedItem.PLAYED, itemIds); adapter.close(); EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); 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 ed3cb71e9..50df0f0a7 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 @@ -742,7 +742,13 @@ public class PodDBAdapter { setFeed(item.getFeed()); } values.put(KEY_FEED, item.getFeed().getId()); - values.put(KEY_READ, item.isRead()); + if(item.isNew()) { + values.put(KEY_READ, FeedItem.NEW); + } else if(item.isPlayed()) { + values.put(KEY_READ, FeedItem.PLAYED); + } else { + values.put(KEY_READ, FeedItem.UNPLAYED); + } values.put(KEY_HAS_CHAPTERS, item.getChapters() != null || item.hasChapters()); values.put(KEY_ITEM_IDENTIFIER, item.getItemIdentifier()); values.put(KEY_FLATTR_STATUS, item.getFlattrStatus().toLong()); @@ -774,7 +780,7 @@ public class PodDBAdapter { db.beginTransaction(); ContentValues values = new ContentValues(); - values.put(KEY_READ, read); + values.put(KEY_READ, read ? FeedItem.PLAYED : FeedItem.UNPLAYED); db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?", new String[]{String.valueOf(itemId)}); if (resetMediaPosition) { @@ -787,7 +793,7 @@ public class PodDBAdapter { db.endTransaction(); } - public void setFeedItemRead(boolean read, long... itemIds) { + public void setFeedItemRead(int read, long... itemIds) { db.beginTransaction(); ContentValues values = new ContentValues(); for (long id : itemIds) { @@ -873,18 +879,23 @@ public class PodDBAdapter { public void setQueue(List queue) { ContentValues values = new ContentValues(); + long[] ids = new long[queue.size()]; db.beginTransaction(); db.delete(TABLE_NAME_QUEUE, null, null); for (int i = 0; i < queue.size(); i++) { FeedItem item = queue.get(i); + ids[i] = item.getId(); values.put(KEY_ID, i); values.put(KEY_FEEDITEM, item.getId()); values.put(KEY_FEED, item.getFeed().getId()); - db.insertWithOnConflict(TABLE_NAME_QUEUE, null, values, - SQLiteDatabase.CONFLICT_REPLACE); + db.insertWithOnConflict(TABLE_NAME_QUEUE, null, values, SQLiteDatabase.CONFLICT_REPLACE); } db.setTransactionSuccessful(); db.endTransaction(); + db.execSQL("UPDATE " + TABLE_NAME_FEED_ITEMS + + " SET " + KEY_READ + "=" + FeedItem.UNPLAYED + + " WHERE " + KEY_ID + " IN(" + TextUtils.join(",", Arrays.asList(ids)) + ")" + + " AND " + KEY_READ + "=" + FeedItem.NEW); } public void clearQueue() { @@ -1059,6 +1070,7 @@ public class PodDBAdapter { /** * Returns a cursor which contains all feed items in the queue. The returned * cursor uses the FEEDITEM_SEL_FI_SMALL selection. + * cursor uses the FEEDITEM_SEL_FI_SMALL selection. */ public final Cursor getQueueCursor() { Object[] args = (Object[]) new String[]{ @@ -1090,24 +1102,14 @@ public class PodDBAdapter { */ public final Cursor getUnreadItemsCursor() { Cursor c = db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL, KEY_READ - + "=0", null, null, null, KEY_PUBDATE + " DESC"); + + "<" + FeedItem.PLAYED, null, null, null, KEY_PUBDATE + " DESC"); return c; } public final Cursor getNewItemIdsCursor() { - final String query = "SELECT " + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + final String query = "SELECT " + KEY_ID + " FROM " + TABLE_NAME_FEED_ITEMS - + " INNER JOIN " + TABLE_NAME_FEED_MEDIA + " ON " - + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" - + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM - + " LEFT OUTER JOIN " + TABLE_NAME_QUEUE + " ON " - + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" - + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM - + " WHERE " - + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed - + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded - + TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played - + TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL"; // not in queue + + " WHERE " + KEY_READ + "=" + FeedItem.NEW; return db.rawQuery(query, null); } @@ -1116,18 +1118,9 @@ public class PodDBAdapter { * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection. */ public final Cursor getNewItemsCursor() { - final String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS - + " INNER JOIN " + TABLE_NAME_FEED_MEDIA + " ON " - + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" - + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM - + " LEFT OUTER JOIN " + TABLE_NAME_QUEUE + " ON " - + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" - + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM - + " WHERE " - + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed - + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded - + TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played - + TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL" // not in queue + final String query = "SELECT " + SEL_FI_SMALL_STR + + " FROM " + TABLE_NAME_FEED_ITEMS + + " WHERE " + KEY_READ + "=" + FeedItem.NEW + " ORDER BY " + KEY_PUBDATE + " DESC"; Cursor c = db.rawQuery(query, null); return c; @@ -1139,11 +1132,11 @@ public class PodDBAdapter { } public Cursor getDownloadedItemsCursor() { - final String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS - + " INNER JOIN " + TABLE_NAME_FEED_MEDIA + " ON " - + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" - + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + " WHERE " - + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + ">0"; + final String query = "SELECT " + SEL_FI_SMALL_STR + + " FROM " + TABLE_NAME_FEED_ITEMS + + " INNER JOIN " + TABLE_NAME_FEED_MEDIA + + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + + " WHERE " + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + ">0"; Cursor c = db.rawQuery(query, null); return c; } @@ -1277,19 +1270,9 @@ public class PodDBAdapter { } public final int getNumberOfNewItems() { - final String query = "SELECT COUNT(" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + ")" - +" FROM " + TABLE_NAME_FEED_ITEMS - + " LEFT JOIN " + TABLE_NAME_FEED_MEDIA + " ON " - + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" - + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM - + " LEFT JOIN " + TABLE_NAME_QUEUE + " ON " - + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" - + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM - + " WHERE " - + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed - + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded - + TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played - + TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL"; // not in queue + final String query = "SELECT COUNT(" + KEY_ID + ")" + + " FROM " + TABLE_NAME_FEED_ITEMS + + " WHERE " + KEY_READ + "=" + FeedItem.NEW; Cursor c = db.rawQuery(query, null); int result = 0; if (c.moveToFirst()) { @@ -1315,7 +1298,8 @@ public class PodDBAdapter { final String query = "SELECT " + KEY_FEED + ", COUNT(" + KEY_ID + ") AS count " + " FROM " + TABLE_NAME_FEED_ITEMS + " WHERE " + KEY_FEED + " IN (" + builder.toString() + ") " - + " AND " + KEY_READ + " = 0" + + " AND (" + KEY_READ + "=" + FeedItem.NEW + + " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")" + " GROUP BY " + KEY_FEED; Cursor c = db.rawQuery(query, null); LongIntMap result = new LongIntMap(c.getCount()); -- cgit v1.2.3 From 5643933a51027e58c4381a3f06f3b7e8e9bc30fa Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Tue, 30 Jun 2015 00:04:06 +0200 Subject: Set subscription order and counter in the preferences --- .../core/preferences/UserPreferences.java | 18 ++++++++++++++++++ core/src/main/res/values/arrays.xml | 22 ++++++++++++++++++++++ core/src/main/res/values/strings.xml | 15 ++++++++++++++- 3 files changed, 54 insertions(+), 1 deletion(-) (limited to 'core/src') 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 d96d25fc2..573f01765 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 @@ -43,6 +43,8 @@ public class UserPreferences { // User Interface public static final String PREF_THEME = "prefTheme"; public static final String PREF_HIDDEN_DRAWER_ITEMS = "prefHiddenDrawerItems"; + public static final String PREF_DRAWER_FEED_ORDER = "prefDrawerFeedOrder"; + public static final String PREF_DRAWER_FEED_INDICATOR = "prefDrawerFeedIndicator"; public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify"; public static final String PREF_PERSISTENT_NOTIFICATION = "prefPersistNotify"; public static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport"; @@ -85,6 +87,12 @@ public class UserPreferences { // Constants private static int EPISODE_CACHE_SIZE_UNLIMITED = -1; + public static int ORDER_UNPLAYED_EPISODES = 0; + public static int ORDER_ALPHABETICAL = 1; + public static int SHOW_NEW_UNPLAYED_SUM = 0; + public static int SHOW_NEW = 1; + public static int SHOW_UNPLAYED = 2; + public static int SHOW_NONE= 3; private static Context context; private static SharedPreferences prefs; @@ -128,6 +136,16 @@ public class UserPreferences { return new ArrayList(Arrays.asList(StringUtils.split(hiddenItems, ','))); } + public static int getFeedOrder() { + String value = prefs.getString(PREF_DRAWER_FEED_ORDER, "0"); + return Integer.valueOf(value); + } + + public static int getFeedIndicator() { + String value = prefs.getString(PREF_DRAWER_FEED_INDICATOR, "0"); + return Integer.valueOf(value); + } + /** * Returns notification priority. * diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index afcb31078..82596e970 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -126,6 +126,28 @@ @string/add_feed_label + + @string/drawer_feed_order_unplayed_episodes + @string/drawer_feed_order_alphabetical + + + 0 + 1 + + + + @string/drawer_feed_indicator_new_unplayed + @string/drawer_feed_indicator_new + @string/drawer_feed_indicator_unplayed + @string/drawer_feed_indicator_none + + + 0 + 1 + 2 + 3 + + @string/hide_unplayed_episodes_label @string/hide_paused_episodes_label diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 00d7ed1bd..9cebfa26e 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -33,6 +33,12 @@ Open menu Close menu Drawer Preferences + Sort by counter + Sort alphabetically + Number of new and unplayed episodes + Number of new episodes + Number of unplayed episodes + None Open in Browser @@ -84,6 +90,7 @@ Marked all Episodes as played Please confirm that you want to mark all episodes as being played. Please confirm that you want to mark all episodes in this feed as being played. + Mark all as seen Show information Remove Podcast Share... @@ -279,8 +286,14 @@ Configure automatic flattring User Interface Select Theme - Change Navigation Drawer + Customize Navigation Drawer + Customize the appearance of the navigation drawer. + Set Navigation Drawer items Change which items appear in the navigation drawer. + Set Subscription Order + Change the order of your subscriptions + Set Subscription Counter + Change the information displayed by the subscription counter Change the appearance of AntennaPod. Automatic Download Configure the automatic download of episodes. -- cgit v1.2.3 From 936ecc2b8e7fc5a392ef8206fe773757821a8e95 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Tue, 30 Jun 2015 00:18:24 +0200 Subject: Nav drawer subscriptions context menu --- .../de/danoeh/antennapod/core/ClientConfig.java | 2 - .../danoeh/antennapod/core/StorageCallbacks.java | 27 --- .../java/de/danoeh/antennapod/core/feed/Feed.java | 19 +- .../core/storage/APSPCleanupAlgorithm.java | 139 ------------ .../core/storage/APSPDownloadAlgorithm.java | 72 ------- .../danoeh/antennapod/core/storage/DBReader.java | 60 ++++-- .../danoeh/antennapod/core/storage/DBWriter.java | 37 +++- .../antennapod/core/storage/PodDBAdapter.java | 232 +++++++++++++++++++-- 8 files changed, 306 insertions(+), 282 deletions(-) delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/StorageCallbacks.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java b/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java index 1a2671555..6619e706b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java +++ b/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java @@ -21,7 +21,5 @@ public class ClientConfig { public static FlattrCallbacks flattrCallbacks; - public static StorageCallbacks storageCallbacks; - public static DBTasksCallbacks dbTasksCallbacks; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/StorageCallbacks.java b/core/src/main/java/de/danoeh/antennapod/core/StorageCallbacks.java deleted file mode 100644 index 5d1a0fffc..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/StorageCallbacks.java +++ /dev/null @@ -1,27 +0,0 @@ -package de.danoeh.antennapod.core; - -import android.database.sqlite.SQLiteDatabase; - -/** - * Callbacks for the classes in the storage package of the core module. - */ -public interface StorageCallbacks { - - /** - * Returns the current version of the database. - * - * @return The non-negative version number of the database. - */ - public int getDatabaseVersion(); - - /** - * Upgrades the given database from an old version to a newer version. - * - * @param db The database that is supposed to be upgraded. - * @param oldVersion The old version of the database. - * @param newVersion The version that the database is supposed to be upgraded to. - */ - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion); - - -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java index 29ba721fe..25b3a9ae6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java @@ -177,10 +177,21 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource */ public boolean hasNewItems() { for (FeedItem item : items) { - if (item.getState() == FeedItem.State.UNREAD) { - if (item.getMedia() != null) { - return true; - } + if (item.isNew()) { + return true; + } + } + return false; + } + + /** + * Returns true if at least one item in the itemlist is unread. + * + */ + public boolean hasUnplayedItems() { + for (FeedItem item : items) { + if (false == item.isNew() && false == item.isPlayed()) { + return true; } } return false; diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java deleted file mode 100644 index 420bbc09d..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java +++ /dev/null @@ -1,139 +0,0 @@ -package de.danoeh.antennapod.core.storage; - -import android.content.Context; -import android.util.Log; - -import org.apache.commons.io.FileUtils; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.ExecutionException; - -import de.danoeh.antennapod.core.feed.FeedItem; - -/** - * Implementation of the EpisodeCleanupAlgorithm interface used by AntennaPodSP apps. - */ -public class APSPCleanupAlgorithm implements EpisodeCleanupAlgorithm { - private static final String TAG = "APSPCleanupAlgorithm"; - - final int numberOfNewAutomaticallyDownloadedEpisodes; - - public APSPCleanupAlgorithm(int numberOfNewAutomaticallyDownloadedEpisodes) { - this.numberOfNewAutomaticallyDownloadedEpisodes = numberOfNewAutomaticallyDownloadedEpisodes; - } - - /** - * Performs an automatic cleanup. Episodes that have been downloaded first will also be deleted first. - * The episode that is currently playing as well as the n most recent episodes (the exact value is determined - * by AppPreferences.numberOfNewAutomaticallyDownloadedEpisodes) will never be deleted. - * - * @param context - * @param episodeSize The maximum amount of space that should be freed by this method - * @return The number of episodes that have been deleted - */ - @Override - public int performCleanup(Context context, Integer episodeSize) { - Log.i(TAG, String.format("performAutoCleanup(%d)", episodeSize)); - if (episodeSize <= 0) { - return 0; - } - - List candidates = getAutoCleanupCandidates(context); - List deleteList = new ArrayList(); - long deletedEpisodesSize = 0; - Collections.sort(candidates, new Comparator() { - @Override - public int compare(FeedItem lhs, FeedItem rhs) { - File lFile = new File(lhs.getMedia().getFile_url()); - File rFile = new File(rhs.getMedia().getFile_url()); - if (!lFile.exists() || !rFile.exists()) { - return 0; - } - if (FileUtils.isFileOlder(lFile, rFile)) { - return -1; - } else { - return 1; - } - } - }); - // listened episodes will be deleted first - Iterator it = candidates.iterator(); - if (it.hasNext()) { - for (FeedItem i = it.next(); it.hasNext() && deletedEpisodesSize <= episodeSize; i = it.next()) { - if (!i.getMedia().isPlaying() && i.getMedia().getPlaybackCompletionDate() != null) { - it.remove(); - deleteList.add(i); - deletedEpisodesSize += i.getMedia().getSize(); - } - } - } - - // delete unlistened old episodes if necessary - it = candidates.iterator(); - if (it.hasNext()) { - for (FeedItem i = it.next(); it.hasNext() && deletedEpisodesSize <= episodeSize; i = it.next()) { - if (!i.getMedia().isPlaying()) { - it.remove(); - deleteList.add(i); - deletedEpisodesSize += i.getMedia().getSize(); - } - } - } - for (FeedItem item : deleteList) { - try { - DBWriter.deleteFeedMediaOfItem(context, item.getMedia().getId()).get(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } - } - Log.i(TAG, String.format("performAutoCleanup(%d) deleted %d episodes and freed %d bytes of memory", - episodeSize, deleteList.size(), deletedEpisodesSize)); - return deleteList.size(); - } - - @Override - public Integer getDefaultCleanupParameter(Context context) { - return 0; - } - - @Override - public Integer getPerformCleanupParameter(Context context, List items) { - int episodeSize = 0; - for (FeedItem item : items) { - if (item.hasMedia() && !item.getMedia().isDownloaded()) { - episodeSize += item.getMedia().getSize(); - } - } - return episodeSize; - } - - /** - * Returns list of FeedItems that have been downloaded, but are not one of the - * [numberOfNewAutomaticallyDownloadedEpisodes] most recent items. - */ - private List getAutoCleanupCandidates(Context context) { - List downloaded = new ArrayList(DBReader.getDownloadedItems(context)); - List recent = new ArrayList(DBReader.getRecentlyPublishedEpisodes(context, - numberOfNewAutomaticallyDownloadedEpisodes)); - for (FeedItem r : recent) { - if (r.hasMedia() && r.getMedia().isDownloaded()) { - for (int i = 0; i < downloaded.size(); i++) { - if (downloaded.get(i).getId() == r.getId()) { - downloaded.remove(i); - break; - } - } - } - } - - return downloaded; - - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java deleted file mode 100644 index f760ec0ce..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java +++ /dev/null @@ -1,72 +0,0 @@ -package de.danoeh.antennapod.core.storage; - -import android.content.Context; -import android.util.Log; - -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -import de.danoeh.antennapod.core.BuildConfig; -import de.danoeh.antennapod.core.feed.FeedItem; -import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.util.NetworkUtils; - -/** - * Implements the automatic download algorithm used by AntennaPodSP apps. - */ -public class APSPDownloadAlgorithm implements AutomaticDownloadAlgorithm { - private static final String TAG = "APSPDownloadAlgorithm"; - - private final int numberOfNewAutomaticallyDownloadedEpisodes; - - public APSPDownloadAlgorithm(int numberOfNewAutomaticallyDownloadedEpisodes) { - this.numberOfNewAutomaticallyDownloadedEpisodes = numberOfNewAutomaticallyDownloadedEpisodes; - } - - /** - * Downloads the most recent episodes automatically. The exact number of - * episodes that will be downloaded can be set in the AppPreferences. - * - * @param context Used for accessing the DB. - * @return A Runnable that will be submitted to an ExecutorService. - */ - @Override - public Runnable autoDownloadUndownloadedItems(final Context context, final long... mediaIds) { - return new Runnable() { - @Override - public void run() { - if (BuildConfig.DEBUG) - Log.d(TAG, "Performing auto-dl of undownloaded episodes"); - if (NetworkUtils.autodownloadNetworkAvailable(context) - && UserPreferences.isEnableAutodownload()) { - - Arrays.sort(mediaIds); - List itemsToDownload = DBReader.getRecentlyPublishedEpisodes(context, - numberOfNewAutomaticallyDownloadedEpisodes); - Iterator it = itemsToDownload.iterator(); - - for (FeedItem item = it.next(); it.hasNext(); item = it.next()) { - if (!item.hasMedia() - || item.getMedia().isDownloaded() - || Arrays.binarySearch(mediaIds, item.getMedia().getId()) < 0) { - it.remove(); - } - } - if (BuildConfig.DEBUG) - Log.d(TAG, "Enqueueing " + itemsToDownload.size() - + " items for automatic download"); - if (!itemsToDownload.isEmpty()) { - try { - DBTasks.downloadFeedItems(false, context, - itemsToDownload.toArray(new FeedItem[itemsToDownload - .size()])); - } catch (DownloadRequestException e) { - e.printStackTrace(); - } - } - } - } - }; - } -} 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 0347c1b72..3b33c28df 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 @@ -22,6 +22,7 @@ import de.danoeh.antennapod.core.feed.FeedPreferences; import de.danoeh.antennapod.core.feed.ID3Chapter; import de.danoeh.antennapod.core.feed.SimpleChapter; import de.danoeh.antennapod.core.feed.VorbisCommentChapter; +import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.util.DownloadError; import de.danoeh.antennapod.core.util.LongIntMap; @@ -1139,27 +1140,42 @@ public final class DBReader { for(int i=0; i < feeds.size(); i++) { feedIds[i] = feeds.get(i).getId(); } - final LongIntMap numUnreadFeedItems = adapter.getNumberOfUnreadFeedItems(feedIds); - Collections.sort(feeds, new Comparator() { - @Override - public int compare(Feed lhs, Feed rhs) { - long numUnreadLhs = numUnreadFeedItems.get(lhs.getId()); - Log.d(TAG, "feed with id " + lhs.getId() + " has " + numUnreadLhs + " unread items"); - long numUnreadRhs = numUnreadFeedItems.get(rhs.getId()); - Log.d(TAG, "feed with id " + rhs.getId() + " has " + numUnreadRhs + " unread items"); - if(numUnreadLhs > numUnreadRhs) { - // reverse natural order: podcast with most unplayed episodes first - return -1; - } else if(numUnreadLhs == numUnreadRhs) { + final LongIntMap feedCounters = adapter.getFeedCounters(feedIds); + + Comparator comparator; + int feedOrder = UserPreferences.getFeedOrder(); + if(feedOrder == UserPreferences.ORDER_UNPLAYED_EPISODES) { + comparator = new Comparator() { + @Override + public int compare(Feed lhs, Feed rhs) { + long counterLhs = feedCounters.get(lhs.getId()); + long counterRhs = feedCounters.get(rhs.getId()); + if(counterLhs > counterRhs) { + // reverse natural order: podcast with most unplayed episodes first + return -1; + } else if(counterLhs == counterRhs) { + return lhs.getTitle().compareTo(rhs.getTitle()); + } else { + return 1; + } + } + }; + } else { + comparator = new Comparator() { + @Override + public int compare(Feed lhs, Feed rhs) { + if(lhs.getTitle() == null) { + return 1; + } return lhs.getTitle().compareTo(rhs.getTitle()); - } else { - return 1; } - } - }); + }; + } + + Collections.sort(feeds, comparator); int queueSize = adapter.getQueueSize(); int numNewItems = adapter.getNumberOfNewItems(); - NavDrawerData result = new NavDrawerData(feeds, queueSize, numNewItems, numUnreadFeedItems); + NavDrawerData result = new NavDrawerData(feeds, queueSize, numNewItems, feedCounters); adapter.close(); return result; } @@ -1168,14 +1184,16 @@ public final class DBReader { public List feeds; public int queueSize; public int numNewItems; - public LongIntMap numUnreadFeedItems; + public LongIntMap feedCounters; - public NavDrawerData(List feeds, int queueSize, int numNewItems, - LongIntMap numUnreadFeedItems) { + public NavDrawerData(List feeds, + int queueSize, + int numNewItems, + LongIntMap feedIndicatorValues) { this.feeds = feeds; this.queueSize = queueSize; this.numNewItems = numNewItems; - this.numUnreadFeedItems = numUnreadFeedItems; + this.feedCounters = feedIndicatorValues; } } } 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 278d897b6..d0da0b194 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 @@ -409,8 +409,8 @@ public class DBWriter { if (item != null) { // add item to either front ot back of queue boolean addToFront = UserPreferences.enqueueAtFront(); - if(addToFront){ - queue.add(0+i, item); + if (addToFront) { + queue.add(0 + i, item); } else { queue.add(item); } @@ -610,7 +610,8 @@ public class DBWriter { public void run() { final PodDBAdapter adapter = new PodDBAdapter(context); adapter.open(); - adapter.setFeedItemRead(read, itemIds); + int played = read ? FeedItem.PLAYED : FeedItem.UNPLAYED; + adapter.setFeedItemRead(played, itemIds); adapter.close(); EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); } @@ -650,6 +651,35 @@ public class DBWriter { }); } + /** + * Sets the 'read'-attribute of all FeedItems of a specific Feed to true. + * + * @param context A context that is used for opening a database connection. + * @param feedId ID of the Feed. + */ + public static Future markFeedSeen(final Context context, final long feedId) { + return dbExec.submit(new Runnable() { + + @Override + public void run() { + final PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + Cursor itemCursor = adapter.getNewItemsIdsCursor(feedId); + long[] ids = new long[itemCursor.getCount()]; + itemCursor.moveToFirst(); + for (int i = 0; i < ids.length; i++) { + ids[i] = itemCursor.getLong(0); + itemCursor.moveToNext(); + } + itemCursor.close(); + adapter.setFeedItemRead(FeedItem.UNPLAYED, ids); + adapter.close(); + + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + } + }); + } + /** * Sets the 'read'-attribute of all FeedItems of a specific Feed to true. * @@ -677,7 +707,6 @@ public class DBWriter { EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); } }); - } /** 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 50df0f0a7..c3466c621 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 @@ -9,6 +9,7 @@ import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; +import android.media.MediaMetadataRetriever; import android.text.TextUtils; import android.util.Log; @@ -18,7 +19,6 @@ import java.util.Arrays; import java.util.List; import de.danoeh.antennapod.core.BuildConfig; -import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.event.ProgressEvent; import de.danoeh.antennapod.core.feed.Chapter; @@ -28,13 +28,12 @@ import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.FeedPreferences; +import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.util.LongIntMap; import de.danoeh.antennapod.core.util.flattr.FlattrStatus; import de.greenrobot.event.EventBus; -; - // TODO Remove media column from feeditem table /** @@ -369,8 +368,7 @@ public class PodDBAdapter { private static synchronized PodDBHelper getDbHelperSingleton(Context appContext) { if (dbHelperSingleton == null) { - dbHelperSingleton = new PodDBHelper(appContext, DATABASE_NAME, null, - ClientConfig.storageCallbacks.getDatabaseVersion()); + dbHelperSingleton = new PodDBHelper(appContext, DATABASE_NAME, null); } return dbHelperSingleton; } @@ -1113,6 +1111,20 @@ public class PodDBAdapter { return db.rawQuery(query, null); } + /** + * Returns a cursor which contains all items of a feed that are considered new. + * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection. + */ + public final Cursor getNewItemsIdsCursor(long feedId) { + final String query = "SELECT " + KEY_ID + + " FROM " + TABLE_NAME_FEED_ITEMS + + " WHERE " + KEY_FEED + "=" + feedId + + " AND " + KEY_READ + "=" + FeedItem.NEW + + " ORDER BY " + KEY_PUBDATE + " DESC"; + Cursor c = db.rawQuery(query, null); + return c; + } + /** * Returns a cursor which contains all feed items that are considered new. * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection. @@ -1282,7 +1294,20 @@ public class PodDBAdapter { return result; } - public final LongIntMap getNumberOfUnreadFeedItems(long... feedIds) { + public final LongIntMap getFeedCounters(long... feedIds) { + int indicator = UserPreferences.getFeedIndicator(); + String whereRead; + if(indicator == UserPreferences.SHOW_NEW_UNPLAYED_SUM) { + whereRead = "(" + KEY_READ + "=" + FeedItem.NEW + + " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")"; + } else if(indicator == UserPreferences.SHOW_NEW) { + whereRead = KEY_READ + "=" + FeedItem.NEW; + } else if(indicator == UserPreferences.SHOW_UNPLAYED) { + whereRead = KEY_READ + "=" + FeedItem.UNPLAYED; + } else { + return new LongIntMap(0); + } + // work around TextUtils.join wanting only boxed items // and StringUtils.join() causing NoSuchMethodErrors on MIUI StringBuilder builder = new StringBuilder(); @@ -1298,9 +1323,8 @@ public class PodDBAdapter { final String query = "SELECT " + KEY_FEED + ", COUNT(" + KEY_ID + ") AS count " + " FROM " + TABLE_NAME_FEED_ITEMS + " WHERE " + KEY_FEED + " IN (" + builder.toString() + ") " - + " AND (" + KEY_READ + "=" + FeedItem.NEW - + " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")" - + " GROUP BY " + KEY_FEED; + + " AND " + whereRead + " GROUP BY " + KEY_FEED; + Cursor c = db.rawQuery(query, null); LongIntMap result = new LongIntMap(c.getCount()); if (c.moveToFirst()) { @@ -1454,6 +1478,8 @@ public class PodDBAdapter { */ private static class PodDBHelper extends SQLiteOpenHelper { + private final static int VERSION = 17; + private Context context; /** @@ -1462,11 +1488,10 @@ public class PodDBAdapter { * @param context Context to use * @param name Name of the database * @param factory to use for creating cursor objects - * @param version number of the database */ public PodDBHelper(final Context context, final String name, - final CursorFactory factory, final int version) { - super(context, name, factory, version); + final CursorFactory factory) { + super(context, name, factory, VERSION); this.context = context; } @@ -1492,7 +1517,188 @@ public class PodDBAdapter { public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) { EventBus.getDefault().post(ProgressEvent.start(context.getString(R.string.progress_upgrading_database))); - ClientConfig.storageCallbacks.onUpgrade(db, oldVersion, newVersion); + Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to " + + newVersion + "."); + if (oldVersion <= 1) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " + + KEY_TYPE + " TEXT"); + } + if (oldVersion <= 2) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS + + " ADD COLUMN " + KEY_LINK + " TEXT"); + } + if (oldVersion <= 3) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + + " ADD COLUMN " + KEY_ITEM_IDENTIFIER + " TEXT"); + } + if (oldVersion <= 4) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " + + KEY_FEED_IDENTIFIER + " TEXT"); + } + if (oldVersion <= 5) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG + + " ADD COLUMN " + KEY_REASON_DETAILED + " TEXT"); + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG + + " ADD COLUMN " + KEY_DOWNLOADSTATUS_TITLE + " TEXT"); + } + if (oldVersion <= 6) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS + + " ADD COLUMN " + KEY_CHAPTER_TYPE + " INTEGER"); + } + if (oldVersion <= 7) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " ADD COLUMN " + KEY_PLAYBACK_COMPLETION_DATE + + " INTEGER"); + } + if (oldVersion <= 8) { + final int KEY_ID_POSITION = 0; + final int KEY_MEDIA_POSITION = 1; + + // Add feeditem column to feedmedia table + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " ADD COLUMN " + KEY_FEEDITEM + + " INTEGER"); + Cursor feeditemCursor = db.query(PodDBAdapter.TABLE_NAME_FEED_ITEMS, + new String[]{KEY_ID, KEY_MEDIA}, "? > 0", + new String[]{KEY_MEDIA}, null, null, null); + if (feeditemCursor.moveToFirst()) { + db.beginTransaction(); + ContentValues contentValues = new ContentValues(); + do { + long mediaId = feeditemCursor.getLong(KEY_MEDIA_POSITION); + contentValues.put(KEY_FEEDITEM, feeditemCursor.getLong(KEY_ID_POSITION)); + db.update(PodDBAdapter.TABLE_NAME_FEED_MEDIA, contentValues, KEY_ID + "=?", new String[]{String.valueOf(mediaId)}); + contentValues.clear(); + } while (feeditemCursor.moveToNext()); + db.setTransactionSuccessful(); + db.endTransaction(); + } + feeditemCursor.close(); + } + if (oldVersion <= 9) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + KEY_AUTO_DOWNLOAD + + " INTEGER DEFAULT 1"); + } + if (oldVersion <= 10) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + KEY_FLATTR_STATUS + + " INTEGER"); + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + + " ADD COLUMN " + KEY_FLATTR_STATUS + + " INTEGER"); + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " ADD COLUMN " + KEY_PLAYED_DURATION + + " INTEGER"); + } + if (oldVersion <= 11) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + KEY_USERNAME + + " TEXT"); + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + KEY_PASSWORD + + " TEXT"); + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + + " ADD COLUMN " + KEY_IMAGE + + " INTEGER"); + } + if (oldVersion <= 12) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + KEY_IS_PAGED + " INTEGER DEFAULT 0"); + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + KEY_NEXT_PAGE_LINK + " TEXT"); + } + if (oldVersion <= 13) { + // remove duplicate rows in "Chapters" table that were created because of a bug. + db.execSQL(String.format("DELETE FROM %s WHERE %s NOT IN " + + "(SELECT MIN(%s) as %s FROM %s GROUP BY %s,%s,%s,%s,%s)", + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS, + KEY_ID, + KEY_ID, + KEY_ID, + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS, + KEY_TITLE, + KEY_START, + KEY_FEEDITEM, + KEY_LINK, + KEY_CHAPTER_TYPE)); + } + if(oldVersion <= 14) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + + " ADD COLUMN " + KEY_AUTO_DOWNLOAD + " INTEGER"); + db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + + " SET " + KEY_AUTO_DOWNLOAD + " = " + + "(SELECT " + KEY_AUTO_DOWNLOAD + + " FROM " + PodDBAdapter.TABLE_NAME_FEEDS + + " WHERE " + PodDBAdapter.TABLE_NAME_FEEDS + "." + KEY_ID + + " = " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + ")"); + + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + KEY_HIDE + " TEXT"); + + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0"); + + // create indexes + db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_FEED); + db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_IMAGE); + db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDMEDIA_FEEDITEM); + db.execSQL(PodDBAdapter.CREATE_INDEX_QUEUE_FEEDITEM); + db.execSQL(PodDBAdapter.CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM); + } + if(oldVersion <= 15) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " ADD COLUMN " + KEY_HAS_EMBEDDED_PICTURE + " INTEGER DEFAULT -1"); + db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " SET " + KEY_HAS_EMBEDDED_PICTURE + "=0" + + " WHERE " + KEY_DOWNLOADED + "=0"); + Cursor c = db.rawQuery("SELECT " + KEY_FILE_URL + + " FROM " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " WHERE " + KEY_DOWNLOADED + "=1 " + + " AND " + KEY_HAS_EMBEDDED_PICTURE + "=-1", null); + if(c.moveToFirst()) { + MediaMetadataRetriever mmr = new MediaMetadataRetriever(); + do { + String fileUrl = c.getString(0); + try { + mmr.setDataSource(fileUrl); + byte[] image = mmr.getEmbeddedPicture(); + if (image != null) { + db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " SET " + KEY_HAS_EMBEDDED_PICTURE + "=1" + + " WHERE " + KEY_FILE_URL + "='"+ fileUrl + "'"); + } else { + db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " SET " + KEY_HAS_EMBEDDED_PICTURE + "=0" + + " WHERE " + KEY_FILE_URL + "='"+ fileUrl + "'"); + } + } catch(Exception e) { + e.printStackTrace(); + } + } while(c.moveToNext()); + } + c.close(); + } + if(oldVersion <= 16) { + String selectNew = "SELECT " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID + + " FROM " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + + " INNER JOIN " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + " ON " + + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" + + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + + " LEFT OUTER JOIN " + PodDBAdapter.TABLE_NAME_QUEUE + " ON " + + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" + + PodDBAdapter.TABLE_NAME_QUEUE + "." + KEY_FEEDITEM + + " WHERE " + + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed + + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded + + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played + + PodDBAdapter.TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL"; // not in queue + String sql = "UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + + " SET " + KEY_READ + "=" + FeedItem.NEW + + " WHERE " + KEY_ID + " IN (" + selectNew + ")"; + Log.d("Migration", "SQL: " + sql); + db.execSQL(sql); + } EventBus.getDefault().post(ProgressEvent.end()); } } -- cgit v1.2.3 From dd898d1abe25853fedf16f1b955229671eda6ae6 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 2 Jul 2015 17:21:51 +0200 Subject: Call former indicator "counter" --- .../java/de/danoeh/antennapod/core/feed/FeedMedia.java | 6 ++++-- .../antennapod/core/preferences/UserPreferences.java | 18 +++++++++--------- .../de/danoeh/antennapod/core/storage/DBReader.java | 2 +- .../de/danoeh/antennapod/core/storage/DBWriter.java | 17 ++++++++++++++--- .../danoeh/antennapod/core/storage/PodDBAdapter.java | 8 ++++---- core/src/main/res/values/arrays.xml | 12 ++++++------ core/src/main/res/values/strings.xml | 12 ++++++------ 7 files changed, 44 insertions(+), 31 deletions(-) (limited to 'core/src') 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 bd5fc58b8..302e4e2dd 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 @@ -368,14 +368,16 @@ public class FeedMedia extends FeedFile implements Playable { @Override public void saveCurrentPosition(SharedPreferences pref, int newPosition) { - setPosition(newPosition); DBWriter.setFeedMediaPlaybackInformation(ClientConfig.applicationCallbacks.getApplicationInstance(), this); + if(item.isNew()) { + DBWriter.markItemRead(ClientConfig.applicationCallbacks.getApplicationInstance(), false, item.getId()); + } + setPosition(newPosition); } @Override public void onPlaybackStart() { } - @Override public void onPlaybackCompleted() { 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 573f01765..c9bfe2153 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 @@ -44,7 +44,7 @@ public class UserPreferences { public static final String PREF_THEME = "prefTheme"; public static final String PREF_HIDDEN_DRAWER_ITEMS = "prefHiddenDrawerItems"; public static final String PREF_DRAWER_FEED_ORDER = "prefDrawerFeedOrder"; - public static final String PREF_DRAWER_FEED_INDICATOR = "prefDrawerFeedIndicator"; + public static final String PREF_DRAWER_FEED_COUNTER = "prefDrawerFeedCounter"; public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify"; public static final String PREF_PERSISTENT_NOTIFICATION = "prefPersistNotify"; public static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport"; @@ -87,12 +87,12 @@ public class UserPreferences { // Constants private static int EPISODE_CACHE_SIZE_UNLIMITED = -1; - public static int ORDER_UNPLAYED_EPISODES = 0; - public static int ORDER_ALPHABETICAL = 1; - public static int SHOW_NEW_UNPLAYED_SUM = 0; - public static int SHOW_NEW = 1; - public static int SHOW_UNPLAYED = 2; - public static int SHOW_NONE= 3; + public static int FEED_ORDER_UNPLAYED_EPISODES = 0; + public static int FEED_ORDER_ALPHABETICAL = 1; + public static int FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM = 0; + public static int FEED_COUNTER_SHOW_NEW = 1; + public static int FEED_COUNTER_SHOW_UNPLAYED = 2; + public static int FEED_COUNTER_SHOW_NONE = 3; private static Context context; private static SharedPreferences prefs; @@ -141,8 +141,8 @@ public class UserPreferences { return Integer.valueOf(value); } - public static int getFeedIndicator() { - String value = prefs.getString(PREF_DRAWER_FEED_INDICATOR, "0"); + public static int getFeedCounter() { + String value = prefs.getString(PREF_DRAWER_FEED_COUNTER, "0"); return Integer.valueOf(value); } 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 3b33c28df..93aec54c8 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 @@ -1144,7 +1144,7 @@ public final class DBReader { Comparator comparator; int feedOrder = UserPreferences.getFeedOrder(); - if(feedOrder == UserPreferences.ORDER_UNPLAYED_EPISODES) { + if(feedOrder == UserPreferences.FEED_ORDER_UNPLAYED_EPISODES) { comparator = new Comparator() { @Override public int compare(Feed lhs, Feed rhs) { 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 d0da0b194..216d1bde2 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 @@ -360,6 +360,10 @@ public class DBWriter { queue.add(index, item); adapter.setQueue(queue); EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED, item, index)); + if(item.isNew()) { + adapter.setFeedItemRead(FeedItem.UNPLAYED, item.getId()); + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + } } } } @@ -379,7 +383,6 @@ public class DBWriter { return addQueueItem(context, false, itemIds); } - /** * Appends FeedItem objects to the end of the queue. The 'read'-attribute of all items will be set to true. * If a FeedItem is already in the queue, the FeedItem will not change its position in the queue. @@ -397,11 +400,11 @@ public class DBWriter { if (itemIds.length > 0) { final PodDBAdapter adapter = new PodDBAdapter(context); adapter.open(); - final List queue = DBReader.getQueue(context, - adapter); + final List queue = DBReader.getQueue(context, adapter); if (queue != null) { boolean queueModified = false; + LongList markAsUnplayedIds = new LongList(); for (int i = 0; i < itemIds.length; i++) { if (!itemListContains(queue, itemIds[i])) { final FeedItem item = DBReader.getFeedItem(context, itemIds[i]); @@ -415,12 +418,20 @@ public class DBWriter { queue.add(item); } queueModified = true; + if(item.isNew()) { + markAsUnplayedIds.add(item.getId()); + } } } } if (queueModified) { adapter.setQueue(queue); EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED_ITEMS, queue)); + Log.d(TAG, "# mark as unplayed: " + markAsUnplayedIds.size()); + if(markAsUnplayedIds.size() > 0) { + adapter.setFeedItemRead(FeedItem.UNPLAYED, markAsUnplayedIds.toArray()); + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + } } } adapter.close(); 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 c3466c621..91a8e2ed0 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 @@ -1295,14 +1295,14 @@ public class PodDBAdapter { } public final LongIntMap getFeedCounters(long... feedIds) { - int indicator = UserPreferences.getFeedIndicator(); + int counter = UserPreferences.getFeedCounter(); String whereRead; - if(indicator == UserPreferences.SHOW_NEW_UNPLAYED_SUM) { + if(counter == UserPreferences.FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM) { whereRead = "(" + KEY_READ + "=" + FeedItem.NEW + " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")"; - } else if(indicator == UserPreferences.SHOW_NEW) { + } else if(counter == UserPreferences.FEED_COUNTER_SHOW_NEW) { whereRead = KEY_READ + "=" + FeedItem.NEW; - } else if(indicator == UserPreferences.SHOW_UNPLAYED) { + } else if(counter == UserPreferences.FEED_COUNTER_SHOW_UNPLAYED) { whereRead = KEY_READ + "=" + FeedItem.UNPLAYED; } else { return new LongIntMap(0); diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 82596e970..5fe5f24e8 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -135,13 +135,13 @@ 1 - - @string/drawer_feed_indicator_new_unplayed - @string/drawer_feed_indicator_new - @string/drawer_feed_indicator_unplayed - @string/drawer_feed_indicator_none + + @string/drawer_feed_counter_new_unplayed + @string/drawer_feed_counter_new + @string/drawer_feed_counter_unplayed + @string/drawer_feed_counter_none - + 0 1 2 diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 9cebfa26e..d2c0844aa 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -35,10 +35,10 @@ Drawer Preferences Sort by counter Sort alphabetically - Number of new and unplayed episodes - Number of new episodes - Number of unplayed episodes - None + Number of new and unplayed episodes + Number of new episodes + Number of unplayed episodes + None Open in Browser @@ -292,8 +292,8 @@ Change which items appear in the navigation drawer. Set Subscription Order Change the order of your subscriptions - Set Subscription Counter - Change the information displayed by the subscription counter + Set Subscription Counter + Change the information displayed by the subscription counter Change the appearance of AntennaPod. Automatic Download Configure the automatic download of episodes. -- cgit v1.2.3 From 8538f7b9f29bfceaa3f2d29f6f4bd71f428188f9 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 2 Jul 2015 18:50:10 +0200 Subject: Fix DB problem --- core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java | 7 ++----- .../main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 4 ---- 2 files changed, 2 insertions(+), 9 deletions(-) (limited to 'core/src') 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 216d1bde2..d1f67cd29 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 @@ -361,8 +361,7 @@ public class DBWriter { adapter.setQueue(queue); EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED, item, index)); if(item.isNew()) { - adapter.setFeedItemRead(FeedItem.UNPLAYED, item.getId()); - EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + DBWriter.markItemRead(context, false, item.getId()); } } } @@ -427,10 +426,8 @@ public class DBWriter { if (queueModified) { adapter.setQueue(queue); EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED_ITEMS, queue)); - Log.d(TAG, "# mark as unplayed: " + markAsUnplayedIds.size()); if(markAsUnplayedIds.size() > 0) { - adapter.setFeedItemRead(FeedItem.UNPLAYED, markAsUnplayedIds.toArray()); - EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + DBWriter.markItemRead(context, false, markAsUnplayedIds.toArray()); } } } 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 91a8e2ed0..8f09ff3c2 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 @@ -890,10 +890,6 @@ public class PodDBAdapter { } db.setTransactionSuccessful(); db.endTransaction(); - db.execSQL("UPDATE " + TABLE_NAME_FEED_ITEMS - + " SET " + KEY_READ + "=" + FeedItem.UNPLAYED - + " WHERE " + KEY_ID + " IN(" + TextUtils.join(",", Arrays.asList(ids)) + ")" - + " AND " + KEY_READ + "=" + FeedItem.NEW); } public void clearQueue() { -- cgit v1.2.3 From 6427a40da2406290bc854b25b0e0a9217b627dcb Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 2 Jul 2015 20:16:12 +0200 Subject: Fix tests --- core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java index e93aea9ac..96a6c2ba1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java @@ -113,7 +113,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr /** * This constructor should be used for creating test objects involving chapter marks. */ - public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, int read, Feed feed, boolean hasChapters) { + public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, int state, Feed feed, boolean hasChapters) { this.id = id; this.title = title; this.itemIdentifier = itemIdentifier; -- cgit v1.2.3 From bcff6277f2c3a82ee0a934fd2b985227a00ba224 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 4 Jul 2015 15:38:16 +0200 Subject: Tell Queue fragment to refresh --- .../main/java/de/danoeh/antennapod/core/feed/QueueEvent.java | 2 +- .../main/java/de/danoeh/antennapod/core/storage/DBWriter.java | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java b/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java index c8497f509..97d086e5b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java @@ -8,7 +8,7 @@ import java.util.List; public class QueueEvent { public enum Action { - ADDED, ADDED_ITEMS, REMOVED, CLEARED, DELETED_MEDIA, SORTED, MOVED + ADDED, ADDED_ITEMS, REMOVED, IRREVERSIBLE_REMOVED, CLEARED, DELETED_MEDIA, SORTED, MOVED } public final Action action; 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 d1f67cd29..acdcf5f85 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 @@ -13,6 +13,7 @@ import org.shredzone.flattr4j.model.Flattr; import java.io.File; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; +import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; @@ -184,13 +185,15 @@ public class DBWriter { } // delete stored media files and mark them as read List queue = DBReader.getQueue(context); - boolean queueWasModified = false; + List removed = new ArrayList<>(); if (feed.getItems() == null) { DBReader.getFeedItemList(context, feed); } for (FeedItem item : feed.getItems()) { - queueWasModified |= queue.remove(item); + if(queue.remove(item)) { + removed.add(item); + } if (item.getMedia() != null && item.getMedia().isDownloaded()) { File mediaFile = new File(item.getMedia() @@ -213,8 +216,10 @@ public class DBWriter { } PodDBAdapter adapter = new PodDBAdapter(context); adapter.open(); - if (queueWasModified) { + if (removed.size() > 0) { adapter.setQueue(queue); + EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.IRREVERSIBLE_REMOVED, + removed)); } adapter.removeFeed(feed); adapter.close(); -- cgit v1.2.3 From a9de7631fd4e4de3ca94bbb2775dbd4c1eb900e5 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 4 Jul 2015 17:33:35 +0200 Subject: Fix button moving and icon being cut --- core/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 00d7ed1bd..94c02a2d2 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -20,7 +20,7 @@ Running Completed Log - Cancel Download + Cancel\nDownload Playback History gpodder.net gpodder.net Login -- cgit v1.2.3 From 9cae7c5bfbe252158ddfa6195519db2dbb0a950e Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 5 Jul 2015 15:28:30 +0200 Subject: Small fixes. --- core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java | 2 +- core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'core/src') 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 302e4e2dd..33dd9d636 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 @@ -186,7 +186,7 @@ public class FeedMedia extends FeedFile implements Playable { public void setPosition(int position) { this.position = position; - if(position > 0) { + if(position > 0 && item.isNew()) { this.item.setPlayed(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 8f09ff3c2..2be53047d 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 @@ -877,12 +877,10 @@ public class PodDBAdapter { public void setQueue(List queue) { ContentValues values = new ContentValues(); - long[] ids = new long[queue.size()]; db.beginTransaction(); db.delete(TABLE_NAME_QUEUE, null, null); for (int i = 0; i < queue.size(); i++) { FeedItem item = queue.get(i); - ids[i] = item.getId(); values.put(KEY_ID, i); values.put(KEY_FEEDITEM, item.getId()); values.put(KEY_FEED, item.getFeed().getId()); -- cgit v1.2.3 From 0314d0f95d86752d2d5a6d506153d2b8087d95e4 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 7 Jul 2015 19:51:48 -0400 Subject: setRepeating is setInexactRepeating on API 19+, that means we can go as long as interval*2 before updates. Switched to use 'set()' instead to get behavior that matches what users expect. --- .../core/preferences/UserPreferences.java | 27 +++++++++++++--------- .../core/receiver/AlarmUpdateReceiver.java | 2 +- .../core/receiver/FeedUpdateReceiver.java | 2 ++ 3 files changed, 19 insertions(+), 12 deletions(-) (limited to 'core/src') 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 c9bfe2153..c1b913c27 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 @@ -343,23 +343,25 @@ public class UserPreferences { } /** - * Sets the update interval value. Should only be used for testing purposes! + * Sets the update interval value. */ public static void setUpdateInterval(long hours) { prefs.edit() .putString(PREF_UPDATE_INTERVAL, String.valueOf(hours)) .apply(); - restartUpdateAlarm(); + // when updating with an interval, we assume the user wants + // to update *now* and then every 'hours' interval thereafter. + restartUpdateAlarm(true); } /** - * Sets the update interval value. Should only be used for testing purposes! + * Sets the update interval value. */ public static void setUpdateTimeOfDay(int hourOfDay, int minute) { prefs.edit() .putString(PREF_UPDATE_INTERVAL, hourOfDay + ":" + minute) .apply(); - restartUpdateAlarm(); + restartUpdateAlarm(false); } /** @@ -538,13 +540,18 @@ public class UserPreferences { } } - public static void restartUpdateAlarm() { + public static void restartUpdateAlarm(boolean now) { int[] timeOfDay = getUpdateTimeOfDay(); + Log.d(TAG, "timeOfDay: " + Arrays.toString(timeOfDay)); if (timeOfDay.length == 2) { restartUpdateTimeOfDayAlarm(timeOfDay[0], timeOfDay[1]); } else { long hours = getUpdateInterval(); - restartUpdateIntervalAlarm(TimeUnit.SECONDS.toMillis(10), hours); + long startTrigger = hours; + if (now) { + startTrigger = TimeUnit.SECONDS.toMillis(10); + } + restartUpdateIntervalAlarm(startTrigger, hours); } } @@ -558,9 +565,8 @@ public class UserPreferences { new Intent(ClientConfig.applicationCallbacks.getApplicationInstance(), FeedUpdateReceiver.class), 0); alarmManager.cancel(updateIntent); if (intervalMillis > 0) { - alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, + alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + triggerAtMillis, - intervalMillis, updateIntent); Log.d(TAG, "Changed alarm to new interval " + TimeUnit.MILLISECONDS.toHours(intervalMillis) + " h"); } else { @@ -585,10 +591,9 @@ public class UserPreferences { if(alarm.before(now)) { alarm.add(Calendar.DATE, 1); } - - alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, + Log.d(TAG, "Alarm set for: " + alarm.toString() + " : " + alarm.getTimeInMillis()); + alarmManager.set(AlarmManager.RTC_WAKEUP, alarm.getTimeInMillis(), - AlarmManager.INTERVAL_DAY, updateIntent); Log.d(TAG, "Changed alarm to new time of day " + hoursOfDay + ":" + minute); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java b/core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java index ec3e9d9ea..7fa92f30c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java +++ b/core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java @@ -25,7 +25,7 @@ public class AlarmUpdateReceiver extends BroadcastReceiver { } PlaybackPreferences.init(context); UserPreferences.init(context); - UserPreferences.restartUpdateAlarm(); + UserPreferences.restartUpdateAlarm(false); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java index d37f97a5f..d98086003 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java +++ b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java @@ -5,6 +5,7 @@ import android.content.Context; import android.content.Intent; import android.util.Log; +import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.util.NetworkUtils; @@ -23,6 +24,7 @@ public class FeedUpdateReceiver extends BroadcastReceiver { } else { Log.d(TAG, "Blocking automatic update: no wifi available / no mobile updates allowed"); } + UserPreferences.restartUpdateAlarm(false); } } -- cgit v1.2.3 From 85598f64a9169042742344ff4d6724119303e3d9 Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Wed, 24 Jun 2015 23:13:44 +0300 Subject: Added new per-feed auto download override flag. --- .../java/de/danoeh/antennapod/core/feed/Feed.java | 2 +- .../antennapod/core/feed/FeedPreferences.java | 35 ++++++++++++++++++++-- .../core/service/download/DownloadService.java | 2 +- .../core/service/playback/PlaybackService.java | 2 +- .../playback/PlaybackServiceMediaPlayer.java | 2 +- .../danoeh/antennapod/core/storage/DBReader.java | 2 +- .../antennapod/core/storage/PodDBAdapter.java | 7 ++++- core/src/main/res/values-iw-rIL/strings.xml | 1 + core/src/main/res/values/arrays.xml | 6 ++++ core/src/main/res/values/strings.xml | 1 + 10 files changed, 51 insertions(+), 9 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java index 25b3a9ae6..f6322d6f4 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java @@ -167,7 +167,7 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource */ public Feed(String url, Date lastUpdate, String title, String username, String password) { this(url, lastUpdate, title); - preferences = new FeedPreferences(0, true, username, password); + preferences = new FeedPreferences(0, true, FeedPreferences.AutoDeleteAction.GLOBAL, username, password); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java index 2f0304182..cb264db03 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java @@ -11,19 +11,26 @@ public class FeedPreferences { private long feedID; private boolean autoDownload; + public enum AutoDeleteAction { + GLOBAL, + YES, + NO + } + private AutoDeleteAction auto_delete_action; private String username; private String password; - public FeedPreferences(long feedID, boolean autoDownload, String username, String password) { + public FeedPreferences(long feedID, boolean autoDownload, AutoDeleteAction auto_delete_action, String username, String password) { this.feedID = feedID; this.autoDownload = autoDownload; + this.auto_delete_action = auto_delete_action; this.username = username; this.password = password; } /** - * Compare another FeedPreferences with this one. The feedID and autoDownload attribute are excluded from the + * Compare another FeedPreferences with this one. The feedID, autoDownload and AutoDeleteAction attribute are excluded from the * comparison. * * @return True if the two objects are different. @@ -41,7 +48,7 @@ public class FeedPreferences { } /** - * Update this FeedPreferences object from another one. The feedID and autoDownload attributes are excluded + * Update this FeedPreferences object from another one. The feedID, autoDownload and AutoDeleteAction attributes are excluded * from the update. */ public void updateFromOther(FeedPreferences other) { @@ -67,6 +74,28 @@ public class FeedPreferences { this.autoDownload = autoDownload; } + public AutoDeleteAction getAutoDeleteAction() { + return auto_delete_action; + } + + public void setAutoDeleteAction(AutoDeleteAction auto_delete_action) { + this.auto_delete_action = auto_delete_action; + } + + public boolean getCurrentAutoDelete(boolean isAutoDelete) { + switch (auto_delete_action) { + case GLOBAL: + return isAutoDelete; + + case YES: + return true; + + case NO: + return false; + } + return false; // TODO - add exceptions here + } + public void save(Context context) { DBWriter.setFeedPreferences(context, this); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 7fb878680..578bce854 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -891,7 +891,7 @@ public class DownloadService extends Service { feed.setFile_url(request.getDestination()); feed.setId(request.getFeedfileId()); feed.setDownloaded(true); - feed.setPreferences(new FeedPreferences(0, true, + feed.setPreferences(new FeedPreferences(0, true, FeedPreferences.AutoDeleteAction.GLOBAL, request.getUsername(), request.getPassword())); feed.setPageNr(request.getArguments().getInt(DownloadRequester.REQUEST_ARG_PAGE_NR, 0)); 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 9ab3d93a1..6db77540f 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 @@ -584,7 +584,7 @@ public class PlaybackService extends Service { } // Delete episode if enabled - if(UserPreferences.isAutoDelete()) { + if(item.getFeed().getPreferences().getCurrentAutoDelete(UserPreferences.isAutoDelete())) { DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId()); Log.d(TAG, "Episode Deleted"); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index d4b63fdb1..76ecf09b6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -196,7 +196,7 @@ public class PlaybackServiceMediaPlayer { DBWriter.markItemRead(context, item, true, false); DBWriter.removeQueueItem(context, item, false); DBWriter.addItemToPlaybackHistory(context, oldMedia); - if (UserPreferences.isAutoDelete()) { + if (item.getFeed().getPreferences().getCurrentAutoDelete(UserPreferences.isAutoDelete())) { Log.d(TAG, "Delete " + oldMedia.toString()); DBWriter.deleteFeedMediaOfItem(context, oldMedia.getId()); } 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 93aec54c8..634563099 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 @@ -338,9 +338,9 @@ public final class DBReader { if (image != null) { image.setOwner(feed); } - FeedPreferences preferences = new FeedPreferences(cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_ID), cursor.getInt(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_AUTO_DOWNLOAD) > 0, + FeedPreferences.AutoDeleteAction.values()[cursor.getInt(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_AUTO_DELETE_ACTION)], cursor.getString(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_USERNAME), cursor.getString(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_PASSWORD)); 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 2be53047d..d6740212e 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 @@ -150,6 +150,7 @@ public class PodDBAdapter { public static final String KEY_CHAPTER_TYPE = "type"; public static final String KEY_PLAYBACK_COMPLETION_DATE = "playback_completion_date"; public static final String KEY_AUTO_DOWNLOAD = "auto_download"; + public static final String KEY_AUTO_DELETE_ACTION = "auto_delete_action"; public static final String KEY_PLAYED_DURATION = "played_duration"; public static final String KEY_USERNAME = "username"; public static final String KEY_PASSWORD = "password"; @@ -187,7 +188,8 @@ public class PodDBAdapter { + KEY_IS_PAGED + " INTEGER DEFAULT 0," + KEY_NEXT_PAGE_LINK + " TEXT," + KEY_HIDE + " TEXT," - + KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0)"; + + KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0," + + KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0)"; public static final String CREATE_TABLE_FEED_ITEMS = "CREATE TABLE " + TABLE_NAME_FEED_ITEMS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE @@ -283,6 +285,7 @@ public class PodDBAdapter { TABLE_NAME_FEEDS + "." + KEY_PASSWORD, TABLE_NAME_FEEDS + "." + KEY_HIDE, TABLE_NAME_FEEDS + "." + KEY_LAST_UPDATE_FAILED, + TABLE_NAME_FEEDS + "." + KEY_AUTO_DELETE_ACTION, }; // column indices for FEED_SEL_STD @@ -306,6 +309,7 @@ public class PodDBAdapter { public static final int IDX_FEED_SEL_STD_NEXT_PAGE_LINK = 17; public static final int IDX_FEED_SEL_PREFERENCES_USERNAME = 18; public static final int IDX_FEED_SEL_PREFERENCES_PASSWORD = 19; + public static final int IDX_FEED_SEL_PREFERENCES_AUTO_DELETE_ACTION = 22; /** * Select all columns from the feeditems-table except description and @@ -461,6 +465,7 @@ public class PodDBAdapter { } ContentValues values = new ContentValues(); values.put(KEY_AUTO_DOWNLOAD, prefs.getAutoDownload()); + values.put(KEY_AUTO_DELETE_ACTION,prefs.getAutoDeleteAction().ordinal()); values.put(KEY_USERNAME, prefs.getUsername()); values.put(KEY_PASSWORD, prefs.getPassword()); db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(prefs.getFeedID())}); diff --git a/core/src/main/res/values-iw-rIL/strings.xml b/core/src/main/res/values-iw-rIL/strings.xml index 9e9c0e6bc..321d0dab6 100644 --- a/core/src/main/res/values-iw-rIL/strings.xml +++ b/core/src/main/res/values-iw-rIL/strings.xml @@ -58,6 +58,7 @@ סגור נסה שוב כלול בהורדות אוטומטיות + מחק לאחר ההשמעה (גובר על ההגדרה הגלובלית) \u0020הורדות במקביל כתובת הזנה diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 5fe5f24e8..6b45d1aef 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -1,6 +1,12 @@ + + Global + Always + Never + + 0 15 diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 232ba238e..b0888111d 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -75,6 +75,7 @@ Close Retry Include in auto downloads + Auto Delete Episode\n(override global default) \u0020parallel downloads -- cgit v1.2.3 From 48bfdaa2b32b81492b8e8ad57a8feab29656689d Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Mon, 6 Jul 2015 23:41:02 +0300 Subject: Spinner items now taken from the string resources and can be localized. Also fixed the TextView Hebrew string (break into 2 lines). --- core/src/main/res/values-iw-rIL/strings.xml | 5 ++++- core/src/main/res/values/arrays.xml | 6 +++--- core/src/main/res/values/strings.xml | 3 +++ 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'core/src') diff --git a/core/src/main/res/values-iw-rIL/strings.xml b/core/src/main/res/values-iw-rIL/strings.xml index 321d0dab6..20ddd6d71 100644 --- a/core/src/main/res/values-iw-rIL/strings.xml +++ b/core/src/main/res/values-iw-rIL/strings.xml @@ -58,8 +58,11 @@ סגור נסה שוב כלול בהורדות אוטומטיות - מחק לאחר ההשמעה (גובר על ההגדרה הגלובלית) + מחק לאחר ההשמעה\n(גובר על ההגדרה הגלובלית) \u0020הורדות במקביל + לפי הגדרה גלובלית + תמיד + אף פעם כתובת הזנה כתובת של הזנה או אתר אינטרנט diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 6b45d1aef..3c852360c 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -2,9 +2,9 @@ - Global - Always - Never + @string/feed_auto_download_global + @string/feed_auto_download_always + @string/feed_auto_download_never diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index b0888111d..5079950fa 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -77,6 +77,9 @@ Include in auto downloads Auto Delete Episode\n(override global default) \u0020parallel downloads + Global + Always + Never Feed URL -- cgit v1.2.3 From a22fa8660bccae0f9e740bcf09d00006e878c5d5 Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Tue, 7 Jul 2015 22:13:32 +0300 Subject: FeedPreferences.getCurrentAutoDelete() now calls UserPreferences.isAutoDelete() by itself, instead of receiving it as a parameter. --- .../main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java | 5 +++-- .../de/danoeh/antennapod/core/service/playback/PlaybackService.java | 2 +- .../antennapod/core/service/playback/PlaybackServiceMediaPlayer.java | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java index cb264db03..88da865cc 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod.core.feed; import android.content.Context; import de.danoeh.antennapod.core.storage.DBWriter; import org.apache.commons.lang3.StringUtils; +import de.danoeh.antennapod.core.preferences.UserPreferences; /** * Contains preferences for a single feed. @@ -82,10 +83,10 @@ public class FeedPreferences { this.auto_delete_action = auto_delete_action; } - public boolean getCurrentAutoDelete(boolean isAutoDelete) { + public boolean getCurrentAutoDelete() { switch (auto_delete_action) { case GLOBAL: - return isAutoDelete; + return UserPreferences.isAutoDelete(); case YES: return true; 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 6db77540f..737f0aefd 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 @@ -584,7 +584,7 @@ public class PlaybackService extends Service { } // Delete episode if enabled - if(item.getFeed().getPreferences().getCurrentAutoDelete(UserPreferences.isAutoDelete())) { + if(item.getFeed().getPreferences().getCurrentAutoDelete()) { DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId()); Log.d(TAG, "Episode Deleted"); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 76ecf09b6..835a8c1d1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -196,7 +196,7 @@ public class PlaybackServiceMediaPlayer { DBWriter.markItemRead(context, item, true, false); DBWriter.removeQueueItem(context, item, false); DBWriter.addItemToPlaybackHistory(context, oldMedia); - if (item.getFeed().getPreferences().getCurrentAutoDelete(UserPreferences.isAutoDelete())) { + if (item.getFeed().getPreferences().getCurrentAutoDelete()) { Log.d(TAG, "Delete " + oldMedia.toString()); DBWriter.deleteFeedMediaOfItem(context, oldMedia.getId()); } -- cgit v1.2.3 From cbbed8933ebd46ddfa54a85dcff544ed87f94342 Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Thu, 9 Jul 2015 01:50:27 +0300 Subject: Fix DB to version 18 --- .../main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'core/src') 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 d6740212e..c4b879091 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 @@ -1477,7 +1477,7 @@ public class PodDBAdapter { */ private static class PodDBHelper extends SQLiteOpenHelper { - private final static int VERSION = 17; + private final static int VERSION = 18; private Context context; @@ -1698,6 +1698,10 @@ public class PodDBAdapter { Log.d("Migration", "SQL: " + sql); db.execSQL(sql); } + if(oldVersion <= 17) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0"); + } EventBus.getDefault().post(ProgressEvent.end()); } } -- cgit v1.2.3 From 4f84ceff734889748dc9d846bdf117db5fac4dce Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 3 Jul 2015 18:21:20 +0200 Subject: Determine media file size if feed doesn't report it correctly --- core/src/main/AndroidManifest.xml | 3 ++ .../core/service/FeedMediaSizeService.java | 47 ++++++++++++++++++++++ .../danoeh/antennapod/core/storage/DBReader.java | 22 ++++++++++ .../de/danoeh/antennapod/core/storage/DBTasks.java | 10 ++++- .../antennapod/core/storage/PodDBAdapter.java | 7 ++++ 5 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java (limited to 'core/src') diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index 3ec519844..17dcb4ad8 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -23,6 +23,9 @@ + list = DBReader.getFeedMediaUnknownSize(this); + for (FeedMedia media : list) { + long size = -1; + try { + URL url = new URL(media.getDownload_url()); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + size = conn.getContentLength(); + conn.disconnect(); + } catch (IOException e) { + e.printStackTrace(); + } + media.setSize(size); + DBWriter.setFeedMedia(this, media); + } + } + +} 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 93aec54c8..1af0fa0a9 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 @@ -550,6 +550,28 @@ public final class DBReader { return itemIds; } + /** + * Loads the IDs of the FeedItems whose 'read'-attribute is set to false. + * + * @param context A context that is used for opening a database connection. + * @return A list of IDs of the FeedItems whose 'read'-attribute is set to false. This method should be preferred + * over {@link #getUnreadItemsList(android.content.Context)} if the FeedItems in the UnreadItems list are not used. + */ + public static List getFeedMediaUnknownSize(Context context) { + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + Cursor cursor = adapter.getFeedMediaUnknownSizeCursor(); + List result = new ArrayList<>(cursor.getCount()); + if (cursor.moveToFirst()) { + do { + FeedMedia media = extractFeedMediaFromCursorRow(cursor); + result.add(media); + } while (cursor.moveToNext()); + } + cursor.close(); + return result; + } + /** * Loads a list of FeedItems sorted by pubDate in descending order. 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 9273cf11e..1f6d0abd8 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 @@ -5,6 +5,9 @@ import android.content.Intent; import android.database.Cursor; import android.util.Log; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -29,6 +32,7 @@ import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.service.FeedMediaSizeService; import de.danoeh.antennapod.core.service.GpodnetSyncService; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.service.playback.PlaybackService; @@ -595,15 +599,15 @@ public final class DBTasks { item.getIdentifyingValue()); if (oldItem == null) { // item is new - final int i = idx; item.setFeed(savedFeed); item.setAutoDownload(savedFeed.getPreferences().getAutoDownload()); - savedFeed.getItems().add(i, item); + savedFeed.getItems().add(item); if (markNewItems) { item.setNew(); } } else { oldItem.updateFromOther(item); + savedFeed.getItems().add(oldItem); } } // update attributes @@ -629,6 +633,8 @@ public final class DBTasks { EventDistributor.getInstance().sendFeedUpdateBroadcast(); + context.startService(new Intent(context, FeedMediaSizeService.class)); + return resultFeeds; } 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 2be53047d..d42b67459 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 @@ -1105,6 +1105,13 @@ public class PodDBAdapter { return db.rawQuery(query, null); } + public final Cursor getFeedMediaUnknownSizeCursor() { + final String query = "SELECT * " + + " FROM " + TABLE_NAME_FEED_MEDIA + + " WHERE " + KEY_SIZE + "=0"; + return db.rawQuery(query, null); + } + /** * Returns a cursor which contains all items of a feed that are considered new. * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection. -- cgit v1.2.3 From 23a3e7c766a4dfbba9101672d8628b65ad16c855 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 3 Jul 2015 23:59:40 +0200 Subject: Check network for every media file, manually check suspiciously low file sizes --- .../de/danoeh/antennapod/core/service/FeedMediaSizeService.java | 9 ++++++++- .../main/java/de/danoeh/antennapod/core/storage/DBReader.java | 6 +++--- .../java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 2 +- .../de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java | 4 ++++ 4 files changed, 16 insertions(+), 5 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index b4542aae8..1f7dfa386 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -30,13 +30,20 @@ public class FeedMediaSizeService extends IntentService { } List list = DBReader.getFeedMediaUnknownSize(this); for (FeedMedia media : list) { - long size = -1; + if(false == NetworkUtils.networkAvailable(this)) { + return; + } + long size = Integer.MIN_VALUE; + Log.d(TAG, media.getDownload_url()); try { URL url = new URL(media.getDownload_url()); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestProperty( "Accept-Encoding", "" ); + conn.setRequestMethod("HEAD"); size = conn.getContentLength(); conn.disconnect(); } catch (IOException e) { + Log.d(TAG, media.getDownload_url()); e.printStackTrace(); } media.setSize(size); 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 1af0fa0a9..26a974616 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 @@ -551,11 +551,11 @@ public final class DBReader { } /** - * Loads the IDs of the FeedItems whose 'read'-attribute is set to false. + * Loads FeedMedia whose file size is unknown * * @param context A context that is used for opening a database connection. - * @return A list of IDs of the FeedItems whose 'read'-attribute is set to false. This method should be preferred - * over {@link #getUnreadItemsList(android.content.Context)} if the FeedItems in the UnreadItems list are not used. + * @return A list of FeedMedia items whose size is 0 (unknown and never tried to + * determine the correct size) */ public static List getFeedMediaUnknownSize(Context context) { PodDBAdapter adapter = new PodDBAdapter(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 d42b67459..319987cb2 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 @@ -1108,7 +1108,7 @@ public class PodDBAdapter { public final Cursor getFeedMediaUnknownSizeCursor() { final String query = "SELECT * " + " FROM " + TABLE_NAME_FEED_MEDIA - + " WHERE " + KEY_SIZE + "=0"; + + " WHERE " + KEY_SIZE + ">" + Integer.MIN_VALUE; return db.rawQuery(query, null); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java index 6455332be..31eb2efd6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java @@ -57,6 +57,10 @@ public class NSRSS20 extends Namespace { long size = 0; try { size = Long.parseLong(attributes.getValue(ENC_LEN)); + if(size < 16384) { + // less than 16kb is suspicious, check manually + size = 0; + } } catch (NumberFormatException e) { if (BuildConfig.DEBUG) Log.d(TAG, "Length attribute could not be parsed."); -- cgit v1.2.3 From be1fde6f8e416cd6ddc4be9d7b01de0e718fed55 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 4 Jul 2015 11:31:32 +0200 Subject: Post FeedMedia event --- .../antennapod/core/event/FeedMediaEvent.java | 24 ++++++++++++++++++++++ .../core/service/FeedMediaSizeService.java | 3 +++ 2 files changed, 27 insertions(+) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java new file mode 100644 index 000000000..94e186b7a --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java @@ -0,0 +1,24 @@ +package de.danoeh.antennapod.core.event; + +import de.danoeh.antennapod.core.feed.FeedMedia; + +public class FeedMediaEvent { + + public enum Action { + UPDATE + } + + public final Action action; + public final FeedMedia media; + + private FeedMediaEvent(Action action, FeedMedia media) { + this.action = action; + this.media = media; + } + + public static FeedMediaEvent update(FeedMedia media) { + return new FeedMediaEvent(Action.UPDATE, media); + } + + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index 1f7dfa386..ad047f10a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -9,10 +9,12 @@ import java.net.HttpURLConnection; import java.net.URL; import java.util.List; +import de.danoeh.antennapod.core.event.FeedMediaEvent; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.NetworkUtils; +import de.greenrobot.event.EventBus; public class FeedMediaSizeService extends IntentService { @@ -48,6 +50,7 @@ public class FeedMediaSizeService extends IntentService { } media.setSize(size); DBWriter.setFeedMedia(this, media); + EventBus.getDefault().post(FeedMediaEvent.update(media)); } } -- cgit v1.2.3 From 5608d228be2da4e06cfc07d9a133235298da8a68 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 5 Jul 2015 15:33:10 +0200 Subject: Close URL connection --- .../de/danoeh/antennapod/core/service/FeedMediaSizeService.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index ad047f10a..d6a1ce62c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -36,10 +36,10 @@ public class FeedMediaSizeService extends IntentService { return; } long size = Integer.MIN_VALUE; - Log.d(TAG, media.getDownload_url()); + HttpURLConnection conn = null; try { URL url = new URL(media.getDownload_url()); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn = (HttpURLConnection) url.openConnection(); conn.setRequestProperty( "Accept-Encoding", "" ); conn.setRequestMethod("HEAD"); size = conn.getContentLength(); @@ -47,6 +47,10 @@ public class FeedMediaSizeService extends IntentService { } catch (IOException e) { Log.d(TAG, media.getDownload_url()); e.printStackTrace(); + } finally { + if(conn != null) { + conn.disconnect(); + } } media.setSize(size); DBWriter.setFeedMedia(this, media); -- cgit v1.2.3 From 65611129e15f6a8b8f1a260f373bb6e89fc0c3ea Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 12 Jul 2015 21:17:22 +0200 Subject: Use local file size if episode is downloaded --- .../core/service/FeedMediaSizeService.java | 34 +++++++++++++--------- 1 file changed, 21 insertions(+), 13 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index d6a1ce62c..e64a38901 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -4,6 +4,7 @@ import android.app.IntentService; import android.content.Intent; import android.util.Log; +import java.io.File; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; @@ -36,20 +37,27 @@ public class FeedMediaSizeService extends IntentService { return; } long size = Integer.MIN_VALUE; - HttpURLConnection conn = null; - try { - URL url = new URL(media.getDownload_url()); - conn = (HttpURLConnection) url.openConnection(); - conn.setRequestProperty( "Accept-Encoding", "" ); - conn.setRequestMethod("HEAD"); - size = conn.getContentLength(); - conn.disconnect(); - } catch (IOException e) { - Log.d(TAG, media.getDownload_url()); - e.printStackTrace(); - } finally { - if(conn != null) { + if(media.isDownloaded()) { + File mediaFile = new File(media.getLocalMediaUrl()); + if(mediaFile.exists()) { + size = mediaFile.length(); + } + } else { + HttpURLConnection conn = null; + try { + URL url = new URL(media.getDownload_url()); + conn = (HttpURLConnection) url.openConnection(); + conn.setRequestProperty("Accept-Encoding", ""); + conn.setRequestMethod("HEAD"); + size = conn.getContentLength(); conn.disconnect(); + } catch (IOException e) { + Log.d(TAG, media.getDownload_url()); + e.printStackTrace(); + } finally { + if (conn != null) { + conn.disconnect(); + } } } media.setSize(size); -- cgit v1.2.3 From 97827cde2d822fca93f6900527e3bda56076a0d5 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 12 Jul 2015 22:07:45 +0200 Subject: Fixed tests and bug --- core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'core/src') 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 1f6d0abd8..a90df433e 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 @@ -601,13 +601,12 @@ public final class DBTasks { // item is new item.setFeed(savedFeed); item.setAutoDownload(savedFeed.getPreferences().getAutoDownload()); - savedFeed.getItems().add(item); + savedFeed.getItems().add(idx, item); if (markNewItems) { item.setNew(); } } else { oldItem.updateFromOther(item); - savedFeed.getItems().add(oldItem); } } // update attributes -- cgit v1.2.3 From 76393e1e7c029ff5837b2210a9ef891b897df1b8 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 19 Jul 2015 10:35:28 +0200 Subject: Info text has smaller font, conversion moved utility class --- .../de/danoeh/antennapod/core/util/Converter.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java b/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java index a0b514bd6..917f99564 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java @@ -1,7 +1,10 @@ package de.danoeh.antennapod.core.util; +import android.content.Context; import android.util.Log; +import de.danoeh.antennapod.core.R; + /** Provides methods for converting various units. */ public final class Converter { /** Class shall not be instantiated. */ @@ -99,5 +102,21 @@ public final class Converter { return Integer.valueOf(parts[0]) * 3600 * 1000 + Integer.valueOf(parts[1]) * 1000 * 60; } + + /** Converts milliseconds to a localized string containing hours and minutes */ + public static String getDurationStringLocalized(Context context, int duration) { + int h = duration / HOURS_MIL; + int rest = duration - h * HOURS_MIL; + int m = rest / MINUTES_MIL; + + String result = ""; + if(h > 0) { + String hours = context.getString(R.string.time_unit_hours); + result += h + " " + hours + " "; + } + String minutes = context.getString(R.string.time_unit_minutes); + result += m + " " + minutes; + return result; + } } -- cgit v1.2.3 From 9fb4b790f37cc297a50130f5afda3e77a774ee4e Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 19 Jul 2015 22:28:20 -0400 Subject: * DB qeury only returns items with size <= 0 * We only check for size if download is allowed (maybe we don't need to do this) * If we check using the network and fail we don't check again * removed an unneeded conn.disconnect() (it's handled in the 'finally' block) fixes AntennaPod/AntennaPod#1026 --- .../de/danoeh/antennapod/core/feed/FeedMedia.java | 21 +++++++++++++++++++++ .../core/service/FeedMediaSizeService.java | 16 +++++++++++----- .../antennapod/core/storage/PodDBAdapter.java | 2 +- 3 files changed, 33 insertions(+), 6 deletions(-) (limited to 'core/src') 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 33dd9d636..55ab46335 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 @@ -28,6 +28,15 @@ public class FeedMedia extends FeedFile implements Playable { public static final String PREF_MEDIA_ID = "FeedMedia.PrefMediaId"; public static final String PREF_FEED_ID = "FeedMedia.PrefFeedId"; + /** + * Indicates we've checked on the size of the item via the network + * and got an invalid response. Using Integer.MIN_VALUE because + * 1) we'll still check on it in case it gets downloaded (it's <= 0) + * 2) By default all FeedMedia have a size of 0 if we don't know it, + * so this won't conflict with existing practice. + */ + private static final int CHECKED_ON_SIZE = Integer.MIN_VALUE; + private int duration; private int position; // Current position in file private int played_duration; // How many ms of this file have been played (for autoflattring) @@ -199,6 +208,18 @@ public class FeedMedia extends FeedFile implements Playable { this.size = size; } + /** + * Indicates we asked the service what the size was, but didn't + * get a valid answer and we shoudln't check using the network again. + */ + public void setCheckedOnSize() { + this.size = CHECKED_ON_SIZE; + } + + public boolean checkedOnSize() { + return (CHECKED_ON_SIZE == this.size); + } + public String getMime_type() { return mime_type; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index e64a38901..9a98093ba 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -28,21 +28,23 @@ public class FeedMediaSizeService extends IntentService { @Override protected void onHandleIntent(Intent intent) { Log.d(TAG, "onHandleIntent()"); - if(false == NetworkUtils.networkAvailable(this)) { + if(false == NetworkUtils.isDownloadAllowed(this)) { return; } List list = DBReader.getFeedMediaUnknownSize(this); for (FeedMedia media : list) { - if(false == NetworkUtils.networkAvailable(this)) { + Log.d(TAG, "Getting size currently " + media.getSize() + " for " + media.getDownload_url()); + if(false == NetworkUtils.isDownloadAllowed(this)) { return; } long size = Integer.MIN_VALUE; - if(media.isDownloaded()) { + if (media.isDownloaded()) { File mediaFile = new File(media.getLocalMediaUrl()); if(mediaFile.exists()) { size = mediaFile.length(); } - } else { + } else if (false == media.checkedOnSize()) { + // only query the network if we haven't already checked HttpURLConnection conn = null; try { URL url = new URL(media.getDownload_url()); @@ -50,7 +52,6 @@ public class FeedMediaSizeService extends IntentService { conn.setRequestProperty("Accept-Encoding", ""); conn.setRequestMethod("HEAD"); size = conn.getContentLength(); - conn.disconnect(); } catch (IOException e) { Log.d(TAG, media.getDownload_url()); e.printStackTrace(); @@ -60,7 +61,12 @@ public class FeedMediaSizeService extends IntentService { } } } + if (size <= 0) { + // they didn't tell us the size, but we don't want to keep querying on it + media.setCheckedOnSize(); + } media.setSize(size); + Log.d(TAG, "Size now: " + media.getSize()); DBWriter.setFeedMedia(this, media); EventBus.getDefault().post(FeedMediaEvent.update(media)); } 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 15f35d644..0153cbc8c 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 @@ -1113,7 +1113,7 @@ public class PodDBAdapter { public final Cursor getFeedMediaUnknownSizeCursor() { final String query = "SELECT * " + " FROM " + TABLE_NAME_FEED_MEDIA - + " WHERE " + KEY_SIZE + ">" + Integer.MIN_VALUE; + + " WHERE " + KEY_SIZE + "<= 0"; return db.rawQuery(query, null); } -- cgit v1.2.3 From 36626bbdb9be7b700e64cebced8d3986c06cdfd6 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 19 Jul 2015 22:35:28 -0400 Subject: fix setting of size so it doesn't override everything we just did --- .../java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index 9a98093ba..2882039c0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -64,8 +64,9 @@ public class FeedMediaSizeService extends IntentService { if (size <= 0) { // they didn't tell us the size, but we don't want to keep querying on it media.setCheckedOnSize(); + } else { + media.setSize(size); } - media.setSize(size); Log.d(TAG, "Size now: " + media.getSize()); DBWriter.setFeedMedia(this, media); EventBus.getDefault().post(FeedMediaEvent.update(media)); -- cgit v1.2.3 From 0dbdbdd1ed9201b55ce0f654889944a76723e6de Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Mon, 20 Jul 2015 19:55:17 -0400 Subject: renamed checkedonSize --- .../main/java/de/danoeh/antennapod/core/feed/FeedMedia.java | 10 +++++----- .../danoeh/antennapod/core/service/FeedMediaSizeService.java | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'core/src') 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 55ab46335..9dbf6cc61 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 @@ -35,7 +35,7 @@ public class FeedMedia extends FeedFile implements Playable { * 2) By default all FeedMedia have a size of 0 if we don't know it, * so this won't conflict with existing practice. */ - private static final int CHECKED_ON_SIZE = Integer.MIN_VALUE; + private static final int CHECKED_ON_SIZE_BUT_UNKNOWN = Integer.MIN_VALUE; private int duration; private int position; // Current position in file @@ -212,12 +212,12 @@ public class FeedMedia extends FeedFile implements Playable { * Indicates we asked the service what the size was, but didn't * get a valid answer and we shoudln't check using the network again. */ - public void setCheckedOnSize() { - this.size = CHECKED_ON_SIZE; + public void setCheckedOnSizeButUnknown() { + this.size = CHECKED_ON_SIZE_BUT_UNKNOWN; } - public boolean checkedOnSize() { - return (CHECKED_ON_SIZE == this.size); + public boolean checkedOnSizeButUnknown() { + return (CHECKED_ON_SIZE_BUT_UNKNOWN == this.size); } public String getMime_type() { diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index 2882039c0..44fb14f0c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -43,7 +43,7 @@ public class FeedMediaSizeService extends IntentService { if(mediaFile.exists()) { size = mediaFile.length(); } - } else if (false == media.checkedOnSize()) { + } else if (false == media.checkedOnSizeButUnknown()) { // only query the network if we haven't already checked HttpURLConnection conn = null; try { @@ -63,7 +63,7 @@ public class FeedMediaSizeService extends IntentService { } if (size <= 0) { // they didn't tell us the size, but we don't want to keep querying on it - media.setCheckedOnSize(); + media.setCheckedOnSizeButUnknown(); } else { media.setSize(size); } -- cgit v1.2.3 From 71a7f09d410e95951ed4d7eec5df8864cfdf13d1 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 26 Jul 2015 15:36:25 -0400 Subject: prevent multiple refreshes due to time of day alarm --- .../java/de/danoeh/antennapod/core/preferences/UserPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src') 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 c1b913c27..9f6b144ef 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 @@ -588,7 +588,7 @@ public class UserPreferences { Calendar alarm = (Calendar)now.clone(); alarm.set(Calendar.HOUR_OF_DAY, hoursOfDay); alarm.set(Calendar.MINUTE, minute); - if(alarm.before(now)) { + if (alarm.before(now) || alarm.equals(now)) { alarm.add(Calendar.DATE, 1); } Log.d(TAG, "Alarm set for: " + alarm.toString() + " : " + alarm.getTimeInMillis()); -- cgit v1.2.3 From c4e909e2916605a615c35f7f745f01335065c6b2 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 26 Jul 2015 16:25:56 -0400 Subject: expired feeds weren't implemented properly and were probably a bad idea. now refreshing all feeds on the schedule. --- .../core/receiver/FeedUpdateReceiver.java | 2 +- .../core/service/download/DownloadService.java | 1 + .../danoeh/antennapod/core/storage/DBReader.java | 29 ---------------- .../de/danoeh/antennapod/core/storage/DBTasks.java | 40 ++-------------------- .../antennapod/core/storage/PodDBAdapter.java | 7 ---- 5 files changed, 4 insertions(+), 75 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java index d98086003..0045f1eb0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java +++ b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java @@ -20,7 +20,7 @@ public class FeedUpdateReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { Log.d(TAG, "Received intent"); if (NetworkUtils.isDownloadAllowed(context)) { - DBTasks.refreshExpiredFeeds(context); + DBTasks.refreshAllFeeds(context, null); } else { Log.d(TAG, "Blocking automatic update: no wifi available / no mobile updates allowed"); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 578bce854..3df305027 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -326,6 +326,7 @@ public class DownloadService extends Service { unregisterReceiver(cancelDownloadReceiver); if (!newMediaFiles.isEmpty()) { + Log.d(TAG, "newMediaFiles exist, autodownload them"); DBTasks.autodownloadUndownloadedItems(getApplicationContext(), ArrayUtils.toPrimitive(newMediaFiles.toArray(new Long[newMediaFiles.size()]))); } 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 53fd8c24b..cfbfd152b 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 @@ -114,35 +114,6 @@ public final class DBReader { return result; } - /** - * Returns a list of 'expired Feeds', i.e. Feeds that have not been updated for a certain amount of time. - * - * @param context A context that is used for opening a database connection. - * @param expirationTime Time that is used for determining whether a feed is outdated or not. - * A Feed is considered expired if 'lastUpdate < (currentTime - expirationTime)' evaluates to true. - * @return A list of Feeds, sorted alphabetically by their title. A Feed-object - * of the returned list does NOT have its list of FeedItems yet. The FeedItem-list - * can be loaded separately with {@link #getFeedItemList(android.content.Context, de.danoeh.antennapod.core.feed.Feed)}. - */ - public static List getExpiredFeedsList(final Context context, final long expirationTime) { - Log.d(TAG, String.format("getExpiredFeedsList(%d)", expirationTime)); - - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - - Cursor feedlistCursor = adapter.getExpiredFeedsCursor(expirationTime); - List feeds = new ArrayList(feedlistCursor.getCount()); - - if (feedlistCursor.moveToFirst()) { - do { - Feed feed = extractFeedFromCursorRow(adapter, feedlistCursor); - feeds.add(feed); - } while (feedlistCursor.moveToNext()); - } - feedlistCursor.close(); - return feeds; - } - /** * Takes a list of FeedItems and loads their corresponding Feed-objects from the database. * The feedID-attribute of a FeedItem must be set to the ID of its feed or the method will 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 a90df433e..b08013c65 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 @@ -184,6 +184,7 @@ public final class DBTasks { if (ClientConfig.gpodnetCallbacks.gpodnetEnabled()) { GpodnetSyncService.sendSyncIntent(context); } + Log.d(TAG, "refreshAllFeeds autodownload"); autodownloadUndownloadedItems(context); } }.start(); @@ -192,44 +193,6 @@ public final class DBTasks { } } - /** - * Used by refreshExpiredFeeds to determine which feeds should be refreshed. - * This method will use the value specified in the UserPreferences as the - * expiration time. - * - * @param context Used for DB access. - * @return A list of expired feeds. An empty list will be returned if there - * are no expired feeds. - */ - public static List getExpiredFeeds(final Context context) { - long millis = UserPreferences.getUpdateInterval(); - if (millis > 0) { - List feedList = DBReader.getExpiredFeedsList(context, millis); - if (feedList.size() > 0) { - refreshFeeds(context, feedList); - } - return feedList; - } else { - return new ArrayList(); - } - } - - /** - * Refreshes expired Feeds in the list returned by the getExpiredFeedsList(Context, long) method in DBReader. - * The expiration date parameter is determined by the update interval specified in {@link UserPreferences}. - * - * @param context Used for DB access. - */ - public static void refreshExpiredFeeds(final Context context) { - Log.d(TAG, "Refreshing expired feeds"); - - new Thread() { - public void run() { - refreshFeeds(context, getExpiredFeeds(context)); - } - }.start(); - } - private static void refreshFeeds(final Context context, final List feedList) { @@ -440,6 +403,7 @@ public final class DBTasks { * @return A Future that can be used for waiting for the methods completion. */ public static Future autodownloadUndownloadedItems(final Context context, final long... mediaIds) { + Log.d(TAG, "autodownloadUndownloadedItems"); return autodownloadExec.submit(ClientConfig.dbTasksCallbacks.getAutomaticDownloadAlgorithm() .autoDownloadUndownloadedItems(context, mediaIds)); 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 0153cbc8c..d0402710c 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 @@ -981,13 +981,6 @@ public class PodDBAdapter { return db.query(TABLE_NAME_FEEDS, new String[]{KEY_ID, KEY_DOWNLOAD_URL}, null, null, null, null, null); } - public final Cursor getExpiredFeedsCursor(long expirationTime) { - Cursor c = db.query(TABLE_NAME_FEEDS, FEED_SEL_STD, KEY_LASTUPDATE + " < " + String.valueOf(System.currentTimeMillis() - expirationTime), - null, null, null, - null); - return c; - } - /** * Returns a cursor with all FeedItems of a Feed. Uses FEEDITEM_SEL_FI_SMALL * -- cgit v1.2.3 From b0c464d6ba2f0ed57a8255d7ae1999ef0f2e2acc Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Mon, 27 Jul 2015 19:46:29 -0400 Subject: share titles with the URL. fixes AntennaPod/AntennaPod#905 --- .../de/danoeh/antennapod/core/util/ShareUtils.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java index c065a62c3..35916a604 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java @@ -21,11 +21,11 @@ public class ShareUtils { } public static void shareFeedlink(Context context, Feed feed) { - shareLink(context, feed.getLink()); + shareLink(context, feed.getTitle() + ": " + feed.getLink()); } public static void shareFeedDownloadLink(Context context, Feed feed) { - shareLink(context, feed.getDownload_url()); + shareLink(context, feed.getTitle() + ": " + feed.getDownload_url()); } public static void shareFeedItemLink(Context context, FeedItem item) { @@ -36,24 +36,24 @@ public class ShareUtils { shareFeedItemDownloadLink(context, item, false); } + private static String getItemShareText(FeedItem item) { + return item.getFeed().getTitle() + ": " + item.getTitle(); + } + public static void shareFeedItemLink(Context context, FeedItem item, boolean withPosition) { - String text; + String text = getItemShareText(item) + " " + item.getLink(); if(withPosition) { int pos = item.getMedia().getPosition(); text = item.getLink() + " [" + Converter.getDurationStringLong(pos) + "]"; - } else { - text = item.getLink(); } shareLink(context, text); } public static void shareFeedItemDownloadLink(Context context, FeedItem item, boolean withPosition) { - String text; + String text = getItemShareText(item) + " " + item.getMedia().getDownload_url(); if(withPosition) { int pos = item.getMedia().getPosition(); - text = item.getMedia().getDownload_url() + " [" + Converter.getDurationStringLong(pos) + "]"; - } else { - text = item.getMedia().getDownload_url(); + text += " [" + Converter.getDurationStringLong(pos) + "]"; } shareLink(context, text); } -- cgit v1.2.3 From d45b7c7b6d66b448366538ad67de31a644f49d16 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 28 Jul 2015 17:26:02 -0400 Subject: * fix ConcurrentModificationException in Gpodder * removed 'About' tests (they take too long) --- .../core/preferences/GpodnetPreferences.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java index c3c6ce8c5..1401d5f39 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java @@ -8,7 +8,6 @@ import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -217,26 +216,36 @@ public class GpodnetPreferences { public static void removeRemovedFeeds(Collection removed) { ensurePreferencesLoaded(); + feedListLock.lock(); removedFeeds.removeAll(removed); writePreference(PREF_SYNC_REMOVED, removedFeeds); + feedListLock.unlock(); } - public static synchronized void enqueueEpisodeAction(GpodnetEpisodeAction action) { + public static void enqueueEpisodeAction(GpodnetEpisodeAction action) { ensurePreferencesLoaded(); + feedListLock.lock(); queuedEpisodeActions.add(action); writePreference(PREF_SYNC_EPISODE_ACTIONS, writeEpisodeActionsToString(queuedEpisodeActions)); + feedListLock.unlock(); GpodnetSyncService.sendSyncActionsIntent(ClientConfig.applicationCallbacks.getApplicationInstance()); } public static List getQueuedEpisodeActions() { ensurePreferencesLoaded(); - return Collections.unmodifiableList(queuedEpisodeActions); + List copy = new ArrayList(); + feedListLock.lock(); + copy.addAll(queuedEpisodeActions); + feedListLock.unlock(); + return copy; } - public static synchronized void removeQueuedEpisodeActions(Collection queued) { + public static void removeQueuedEpisodeActions(Collection queued) { ensurePreferencesLoaded(); + feedListLock.lock(); queuedEpisodeActions.removeAll(queued); writePreference(PREF_SYNC_EPISODE_ACTIONS, writeEpisodeActionsToString(queuedEpisodeActions)); + feedListLock.unlock(); } /** @@ -252,12 +261,14 @@ public class GpodnetPreferences { setUsername(null); setPassword(null); setDeviceID(null); + feedListLock.lock(); addedFeeds.clear(); writePreference(PREF_SYNC_ADDED, addedFeeds); removedFeeds.clear(); writePreference(PREF_SYNC_REMOVED, removedFeeds); queuedEpisodeActions.clear(); writePreference(PREF_SYNC_EPISODE_ACTIONS, writeEpisodeActionsToString(queuedEpisodeActions)); + feedListLock.unlock(); setLastSubscriptionSyncTimestamp(0); } -- cgit v1.2.3 From d13885944a550922ce80f93119d2e6f9ca899291 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 28 Jul 2015 17:52:38 -0400 Subject: Added Norweign Also updated some other strings. fixes AntennaPod/AntennaPod#1038 --- core/src/main/res/values-it-rIT/strings.xml | 1 + core/src/main/res/values-no/strings.xml | 30 ++++++++++++++++++ core/src/main/res/values-tr/strings.xml | 48 +++++++++++++++++++++++------ 3 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 core/src/main/res/values-no/strings.xml (limited to 'core/src') diff --git a/core/src/main/res/values-it-rIT/strings.xml b/core/src/main/res/values-it-rIT/strings.xml index b81e3f2ce..82c7395ff 100644 --- a/core/src/main/res/values-it-rIT/strings.xml +++ b/core/src/main/res/values-it-rIT/strings.xml @@ -126,6 +126,7 @@ Errore di autenticazione Annulla tutti i download Download annullato + Download completato con un errore (o errori) Rapporto del downoad URL malformato Errore IO diff --git a/core/src/main/res/values-no/strings.xml b/core/src/main/res/values-no/strings.xml new file mode 100644 index 000000000..16639048b --- /dev/null +++ b/core/src/main/res/values-no/strings.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/src/main/res/values-tr/strings.xml b/core/src/main/res/values-tr/strings.xml index e83c9b48e..9f80f8532 100644 --- a/core/src/main/res/values-tr/strings.xml +++ b/core/src/main/res/values-tr/strings.xml @@ -26,6 +26,7 @@ Münüyü aç Menüyü kapat + Çekmece Seçenekleri Tarayıcıda aç URL\'yi kopyala @@ -39,6 +40,7 @@ İptal Yayıncı Dil + URL Ayarlar Resim Hata @@ -67,10 +69,10 @@ gdpodder.net dizininde yeni cep yayınlarını isme, kategoriye veya popülerliğe göre arayabilirsiniz veya iTunes mağazasında arama yapabilirsiniz. gpodder.net\'e gözat - Hepsini okundu olarak işaretle - Tüm bölümler okundu olarak işaretlendi - Lütfen tüm bölümleri okundu olarak işaretlemek istediğinizi onaylayın. - Lütfen bu besleme içindeki tüm bölümleri okundu olarak işaretlemek istediğinizi onaylayın. + Hepsini oynatıldı olarak işaretle + Tüm bölümleri oynatıldı olarak işaretle + Lütfen tüm bölümleri oynatıldı olarak işaretlemek istediğinizi onaylayın. + Lütfen bu besleme içindeki tüm bölümleri oynatıldı olarak işaretlemek istediğinizi onaylayın. Bilgiyi göster Cep yayını kaldır Web sayfası bağlantısı paylaş @@ -78,6 +80,16 @@ Lütfen bu beslemeyi ve bu beslemeye ait indirilmiş BÜTÜN bölümleri silme isteğinizi onaylayın. Besleme kaldırılıyor Tüm beslemeyi yenile + Bölümleri gizle + Oynatılmadı + Duraklatıldı + Oynatıldı + Kuyrukta + Kuyrukta değil + İndirildi + İndirilmedi + Filtrelendi + {fa-exclamation-circle} Son yenileme başarısız oldu İndir Oynat @@ -86,16 +98,20 @@ Akış Kaldır Bölümü kaldır - Okundu olarak işaretle - Okunmadı olarak işaretle - Okundu olarak işaretlendi + Oynatıldı olarak işaretle + Oynatılmadı olarak işaretle + Oynatıldı olarak işaretlendi Kuyruğa Ekle + Kuyruğa Eklendi Kuyruktan Kaldır Siteyi Ziyaret Et Flattr ile destekle Hepsini kuyruğa ekle Hepsini indir Bölümü atla + Otomatik indirmeyi etkinleştir + Otomatik indirmeyi devre dışı bırak + Çalme konumunu sıfırla başarılı başarısız @@ -113,7 +129,9 @@ Yetkilendirme hatası Bütün indirmeleri iptal et İndirme iptal edildi - İndirme tamamlandı + İndirme iptal edildi\nBu öğe için Otomatik İndirme devre dışı + İndirme hata(lar) ile tamamlandı + İndirme raporu Bozuk URL G/Ç Hatası İstek hatası @@ -129,6 +147,11 @@ Dosyayı indirmeye çalışırken bir hata oluştu:\u0020 Yetkilendirme gerekiyor İstediğiniz kaynak kullanıcı adı ve şifre istiyor + Mobil İndirmeyi Onaylayın + Mobil veri ile indirme ayarlarda devre dışıdır.\n\nGeçici olarak açılsın mı yoksa sadece kuyruğa mı eklensin?\n\nBu tercihiniz 10 dakika boyunca hatırlanacak. + Mobil veri ile indirme ayarlarda devre dışıdır.\n\nGeçici olarak açılsın mı?\n\nBu tercihiniz 10 dakika boyunca hatırlanacak. + Sadece Kuyruğa ekle + Geçici olarak aç Hata! Çalınan medya yok @@ -143,6 +166,8 @@ Cep yayını çalınıyor AntennaPod - Bilinmeyen medya anahtarı: %1$d + Kuyruğu kilitle + Kuyruğun kilidini aç Kuyruğu temizle Geri al Öge kaldırıldı @@ -246,8 +271,8 @@ gpodder.net hesabınız için giriş bilgisini değiştirin. Çalma hızları Değişken hızlı ses yürütmesi için kullanılabilir hızları özelleştirin - Arama zamanı - Geri veya ileri sararken bu kadar saniye atla + İleri sarma süresi + Geri sarma süresi Sunucu ismini ayarla Varsayılan sunucuyu kullan Bildirimi Genişlet @@ -257,6 +282,7 @@ Android 4.1 öncesi sürümler genişletilmiş bildirimleri desteklememektedir. Yeni bölümleri kuyruğun önüne ekle. Kuyruğun önüne ekle. + Devre dışı Otomatik Flattr\'lamayı etkinleştir Bölümün yüzde %d kısmı oynatıldığında Flattr\'la @@ -341,6 +367,8 @@ Vaysayılan dizini seç Başka bir uygulama ses çalmak istediğinde sesi kısmak yerine yürütmeyi duraklat Kesintiler için duraklat + Bir telefon konuşması tamamlandıktan sonra çalmaya kaldığı yerden devam et + Konuşmadan sonra devam et Üye ol Üye olundu -- cgit v1.2.3 From af2ded8fe01a0589dc0030c4f981f6924765ef49 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Tue, 21 Jul 2015 20:04:39 +0200 Subject: Replace Picasso with Glide --- .../antennapod/core/asynctask/ImageResource.java | 37 ++ .../core/asynctask/PicassoImageResource.java | 37 -- .../antennapod/core/asynctask/PicassoProvider.java | 533 --------------------- .../java/de/danoeh/antennapod/core/feed/Feed.java | 4 +- .../de/danoeh/antennapod/core/feed/FeedImage.java | 4 +- .../de/danoeh/antennapod/core/feed/FeedItem.java | 6 +- .../antennapod/core/glide/ApGlideModule.java | 33 ++ .../core/glide/ApOkHttpStreamFetcher.java | 80 ++++ .../antennapod/core/glide/ApOkHttpUrlLoader.java | 124 +++++ .../core/glide/FastBlurTransformation.java | 277 +++++++++++ .../core/preferences/UserPreferences.java | 8 +- .../core/service/download/DownloadService.java | 34 -- .../core/service/playback/PlaybackService.java | 27 +- .../danoeh/antennapod/core/storage/DBReader.java | 6 +- .../de/danoeh/antennapod/core/storage/DBTasks.java | 18 - .../antennapod/core/storage/DownloadRequester.java | 24 - .../antennapod/core/util/playback/Playable.java | 4 +- core/src/main/res/values/arrays.xml | 16 + core/src/main/res/values/colors.xml | 1 + core/src/main/res/values/strings.xml | 6 +- core/src/main/res/values/styles.xml | 4 +- 21 files changed, 612 insertions(+), 671 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/asynctask/ImageResource.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoImageResource.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpStreamFetcher.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/ImageResource.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/ImageResource.java new file mode 100644 index 000000000..edd69f15b --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/ImageResource.java @@ -0,0 +1,37 @@ +package de.danoeh.antennapod.core.asynctask; + +import android.net.Uri; + +/** + * Classes that implement this interface provide access to an image resource that can + * be loaded by the Picasso library. + */ +public interface ImageResource { + + /** + * This scheme should be used by PicassoImageResources to + * indicate that the image Uri points to a file that is not an image + * (e.g. a media file). This workaround is needed so that the Picasso library + * loads these Uri with a Downloader instead of trying to load it directly. + *

+ * For example implementations, see FeedMedia or ExternalMedia. + */ + public static final String SCHEME_MEDIA = "media"; + + + /** + * Parameter key for an encoded fallback Uri. This Uri MUST point to a local image file + */ + public static final String PARAM_FALLBACK = "fallback"; + + /** + * Returns a Uri to the image or null if no image is available. + *

+ * The Uri can either be an HTTP-URL, a URL pointing to a local image file or + * a non-image file (see SCHEME_MEDIA for more details). + *

+ * The Uri can also have an optional fallback-URL if loading the default URL + * failed (see PARAM_FALLBACK). + */ + public Uri getImageUri(); +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoImageResource.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoImageResource.java deleted file mode 100644 index c0d8049db..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoImageResource.java +++ /dev/null @@ -1,37 +0,0 @@ -package de.danoeh.antennapod.core.asynctask; - -import android.net.Uri; - -/** - * Classes that implement this interface provide access to an image resource that can - * be loaded by the Picasso library. - */ -public interface PicassoImageResource { - - /** - * This scheme should be used by PicassoImageResources to - * indicate that the image Uri points to a file that is not an image - * (e.g. a media file). This workaround is needed so that the Picasso library - * loads these Uri with a Downloader instead of trying to load it directly. - *

- * For example implementations, see FeedMedia or ExternalMedia. - */ - public static final String SCHEME_MEDIA = "media"; - - - /** - * Parameter key for an encoded fallback Uri. This Uri MUST point to a local image file - */ - public static final String PARAM_FALLBACK = "fallback"; - - /** - * Returns a Uri to the image or null if no image is available. - *

- * The Uri can either be an HTTP-URL, a URL pointing to a local image file or - * a non-image file (see SCHEME_MEDIA for more details). - *

- * The Uri can also have an optional fallback-URL if loading the default URL - * failed (see PARAM_FALLBACK). - */ - public Uri getImageUri(); -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java deleted file mode 100644 index 8e47a5b71..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java +++ /dev/null @@ -1,533 +0,0 @@ -package de.danoeh.antennapod.core.asynctask; - -import android.content.ContentResolver; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.media.MediaMetadataRetriever; -import android.net.Uri; -import android.text.TextUtils; -import android.util.Log; - -import com.squareup.okhttp.Interceptor; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Response; -import com.squareup.picasso.Cache; -import com.squareup.picasso.LruCache; -import com.squareup.picasso.OkHttpDownloader; -import com.squareup.picasso.Picasso; -import com.squareup.picasso.Request; -import com.squareup.picasso.RequestHandler; -import com.squareup.picasso.Transformation; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import de.danoeh.antennapod.core.service.download.HttpDownloader; -import de.danoeh.antennapod.core.storage.DBReader; - -/** - * Provides access to Picasso instances. - */ -public class PicassoProvider { - - private static final String TAG = "PicassoProvider"; - - private static final boolean DEBUG = false; - - private static ExecutorService executorService; - private static Cache memoryCache; - - private static synchronized ExecutorService getExecutorService() { - if (executorService == null) { - executorService = Executors.newFixedThreadPool(3); - } - return executorService; - } - - private static synchronized Cache getMemoryCache(Context context) { - if (memoryCache == null) { - memoryCache = new LruCache(context); - } - return memoryCache; - } - - private static volatile boolean picassoSetup = false; - - public static synchronized void setupPicassoInstance(Context appContext) { - if (picassoSetup) { - return; - } - OkHttpClient client = new OkHttpClient(); - client.interceptors().add(new BasicAuthenticationInterceptor(appContext)); - Picasso picasso = new Picasso.Builder(appContext) - .indicatorsEnabled(DEBUG) - .loggingEnabled(DEBUG) - .downloader(new OkHttpDownloader(client)) - .addRequestHandler(new MediaRequestHandler(appContext)) - .executor(getExecutorService()) - .memoryCache(getMemoryCache(appContext)) - .listener(new Picasso.Listener() { - @Override - public void onImageLoadFailed(Picasso picasso, Uri uri, Exception e) { - Log.e(TAG, "Failed to load Uri:" + uri.toString()); - e.printStackTrace(); - } - }) - .build(); - Picasso.setSingletonInstance(picasso); - picassoSetup = true; - } - - private static class BasicAuthenticationInterceptor implements Interceptor { - - private final Context context; - - public BasicAuthenticationInterceptor(Context context) { - this.context = context; - } - - @Override - public Response intercept(Chain chain) throws IOException { - com.squareup.okhttp.Request request = chain.request(); - String url = request.urlString(); - String authentication = DBReader.getImageAuthentication(context, url); - - if(TextUtils.isEmpty(authentication)) { - Log.d(TAG, "no credentials for '" + url + "'"); - return chain.proceed(request); - } - - // add authentication - String[] auth = authentication.split(":"); - String credentials = HttpDownloader.encodeCredentials(auth[0], auth[1], "ISO-8859-1"); - com.squareup.okhttp.Request newRequest = request - .newBuilder() - .addHeader("Authorization", credentials) - .build(); - Log.d(TAG, "Basic authentication with ISO-8859-1 encoding"); - Response response = chain.proceed(newRequest); - if (!response.isSuccessful() && response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) { - credentials = HttpDownloader.encodeCredentials(auth[0], auth[1], "UTF-8"); - newRequest = request - .newBuilder() - .addHeader("Authorization", credentials) - .build(); - Log.d(TAG, "Basic authentication with UTF-8 encoding"); - return chain.proceed(newRequest); - } else { - return response; - } - } - } - - private static class MediaRequestHandler extends RequestHandler { - - final Context context; - - public MediaRequestHandler(Context context) { - super(); - this.context = context; - } - - @Override - public boolean canHandleRequest(Request data) { - return StringUtils.equals(data.uri.getScheme(), PicassoImageResource.SCHEME_MEDIA); - } - - @Override - public Result load(Request data, int networkPolicy) throws IOException { - Bitmap bitmap = null; - MediaMetadataRetriever mmr = null; - try { - mmr = new MediaMetadataRetriever(); - mmr.setDataSource(data.uri.getPath()); - byte[] image = mmr.getEmbeddedPicture(); - if (image != null) { - bitmap = decodeStreamFromByteArray(data, image); - } - } catch (RuntimeException e) { - Log.e(TAG, "Failed to decode image in media file", e); - } finally { - if (mmr != null) { - mmr.release(); - } - } - - if (bitmap == null) { - // this should never, happen, but sometimes it does, so fallback - // check for fallback Uri - String fallbackParam = data.uri.getQueryParameter(PicassoImageResource.PARAM_FALLBACK); - if (fallbackParam != null) { - Uri fallback = Uri.parse(fallbackParam); - bitmap = decodeStreamFromFile(data, fallback); - } - } - - if (bitmap == null) { - Log.e(TAG, "Could not load media"); - return null; - } - - return new Result(bitmap, Picasso.LoadedFrom.DISK); - - } - - /* Copied/Adapted from Picasso RequestHandler classes */ - - private Bitmap decodeStreamFromByteArray(Request data, byte[] bytes) throws IOException { - - final BitmapFactory.Options options = createBitmapOptions(data); - final ByteArrayInputStream in = new ByteArrayInputStream(bytes); - in.mark(0); - if (requiresInSampleSize(options)) { - try { - BitmapFactory.decodeStream(in, null, options); - } finally { - in.reset(); - } - calculateInSampleSize(data.targetWidth, data.targetHeight, options, data); - } - try { - return BitmapFactory.decodeStream(in, null, options); - } finally { - IOUtils.closeQuietly(in); - } - } - - private Bitmap decodeStreamFromFile(Request data, Uri uri) throws IOException { - ContentResolver contentResolver = context.getContentResolver(); - final BitmapFactory.Options options = createBitmapOptions(data); - if (requiresInSampleSize(options)) { - InputStream is = null; - try { - is = contentResolver.openInputStream(uri); - BitmapFactory.decodeStream(is, null, options); - } finally { - IOUtils.closeQuietly(is); - } - calculateInSampleSize(data.targetWidth, data.targetHeight, options, data); - } - InputStream is = contentResolver.openInputStream(uri); - try { - return BitmapFactory.decodeStream(is, null, options); - } finally { - IOUtils.closeQuietly(is); - } - } - - private BitmapFactory.Options createBitmapOptions(Request data) { - final boolean justBounds = data.hasSize(); - final boolean hasConfig = data.config != null; - BitmapFactory.Options options = null; - if (justBounds || hasConfig) { - options = new BitmapFactory.Options(); - options.inJustDecodeBounds = justBounds; - if (hasConfig) { - options.inPreferredConfig = data.config; - } - } - return options; - } - - private static boolean requiresInSampleSize(BitmapFactory.Options options) { - return options != null && options.inJustDecodeBounds; - } - - private static void calculateInSampleSize(int reqWidth, int reqHeight, BitmapFactory.Options options, - Request request) { - calculateInSampleSize(reqWidth, reqHeight, options.outWidth, options.outHeight, options, - request); - } - - private static void calculateInSampleSize(int reqWidth, int reqHeight, int width, int height, - BitmapFactory.Options options, Request request) { - int sampleSize = 1; - if (height > reqHeight || width > reqWidth) { - final int heightRatio; - final int widthRatio; - if (reqHeight == 0) { - sampleSize = (int) Math.floor((float) width / (float) reqWidth); - } else if (reqWidth == 0) { - sampleSize = (int) Math.floor((float) height / (float) reqHeight); - } else { - heightRatio = (int) Math.floor((float) height / (float) reqHeight); - widthRatio = (int) Math.floor((float) width / (float) reqWidth); - sampleSize = request.centerInside - ? Math.max(heightRatio, widthRatio) - : Math.min(heightRatio, widthRatio); - } - } - options.inSampleSize = sampleSize; - options.inJustDecodeBounds = false; - } - } - - public static final int BLUR_RADIUS = 1; - public static final int BLUR_IMAGE_SIZE = 100; - public static final String BLUR_KEY = "blur"; - - public static final Transformation blurTransformation = new Transformation() { - @Override - public Bitmap transform(Bitmap source) { - Bitmap result = fastblur(source, BLUR_RADIUS); - if (result == null) { - // just return the original - // for some reason we couldn't transform it. - return source; - } - source.recycle(); - return result; - } - - @Override - public String key() { - return BLUR_KEY; - } - }; - - public static Bitmap fastblur(Bitmap sentBitmap, int radius) { - - // Stack Blur v1.0 from - // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html - // - // Java Author: Mario Klingemann - // http://incubator.quasimondo.com - // created Feburary 29, 2004 - // Android port : Yahel Bouaziz - // http://www.kayenko.com - // ported april 5th, 2012 - - // This is a compromise between Gaussian Blur and Box blur - // It creates much better looking blurs than Box Blur, but is - // 7x faster than my Gaussian Blur implementation. - // - // I called it Stack Blur because this describes best how this - // filter works internally: it creates a kind of moving stack - // of colors whilst scanning through the image. Thereby it - // just has to add one new block of color to the right side - // of the stack and remove the leftmost color. The remaining - // colors on the topmost layer of the stack are either added on - // or reduced by one, depending on if they are on the right or - // on the left side of the stack. - // - // If you are using this algorithm in your code please add - // the following line: - // - // Stack Blur Algorithm by Mario Klingemann - Bitmap.Config config = sentBitmap.getConfig(); - if (config == null) { - // Sometimes the config can be null, in those cases - // we don't do a transform. - return null; - } - - Bitmap bitmap = sentBitmap.copy(config, true); - - if (radius < 1) { - return (null); - } - - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - - int[] pix = new int[w * h]; - Log.e("pix", w + " " + h + " " + pix.length); - bitmap.getPixels(pix, 0, w, 0, 0, w, h); - - int wm = w - 1; - int hm = h - 1; - int wh = w * h; - int div = radius + radius + 1; - - int r[] = new int[wh]; - int g[] = new int[wh]; - int b[] = new int[wh]; - int rsum, gsum, bsum, x, y, i, p, yp, yi, yw; - int vmin[] = new int[Math.max(w, h)]; - - int divsum = (div + 1) >> 1; - divsum *= divsum; - int dv[] = new int[256 * divsum]; - for (i = 0; i < 256 * divsum; i++) { - dv[i] = (i / divsum); - } - - yw = yi = 0; - - int[][] stack = new int[div][3]; - int stackpointer; - int stackstart; - int[] sir; - int rbs; - int r1 = radius + 1; - int routsum, goutsum, boutsum; - int rinsum, ginsum, binsum; - - for (y = 0; y < h; y++) { - rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; - for (i = -radius; i <= radius; i++) { - p = pix[yi + Math.min(wm, Math.max(i, 0))]; - sir = stack[i + radius]; - sir[0] = (p & 0xff0000) >> 16; - sir[1] = (p & 0x00ff00) >> 8; - sir[2] = (p & 0x0000ff); - rbs = r1 - Math.abs(i); - rsum += sir[0] * rbs; - gsum += sir[1] * rbs; - bsum += sir[2] * rbs; - if (i > 0) { - rinsum += sir[0]; - ginsum += sir[1]; - binsum += sir[2]; - } else { - routsum += sir[0]; - goutsum += sir[1]; - boutsum += sir[2]; - } - } - stackpointer = radius; - - for (x = 0; x < w; x++) { - - r[yi] = dv[rsum]; - g[yi] = dv[gsum]; - b[yi] = dv[bsum]; - - rsum -= routsum; - gsum -= goutsum; - bsum -= boutsum; - - stackstart = stackpointer - radius + div; - sir = stack[stackstart % div]; - - routsum -= sir[0]; - goutsum -= sir[1]; - boutsum -= sir[2]; - - if (y == 0) { - vmin[x] = Math.min(x + radius + 1, wm); - } - p = pix[yw + vmin[x]]; - - sir[0] = (p & 0xff0000) >> 16; - sir[1] = (p & 0x00ff00) >> 8; - sir[2] = (p & 0x0000ff); - - rinsum += sir[0]; - ginsum += sir[1]; - binsum += sir[2]; - - rsum += rinsum; - gsum += ginsum; - bsum += binsum; - - stackpointer = (stackpointer + 1) % div; - sir = stack[(stackpointer) % div]; - - routsum += sir[0]; - goutsum += sir[1]; - boutsum += sir[2]; - - rinsum -= sir[0]; - ginsum -= sir[1]; - binsum -= sir[2]; - - yi++; - } - yw += w; - } - for (x = 0; x < w; x++) { - rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; - yp = -radius * w; - for (i = -radius; i <= radius; i++) { - yi = Math.max(0, yp) + x; - - sir = stack[i + radius]; - - sir[0] = r[yi]; - sir[1] = g[yi]; - sir[2] = b[yi]; - - rbs = r1 - Math.abs(i); - - rsum += r[yi] * rbs; - gsum += g[yi] * rbs; - bsum += b[yi] * rbs; - - if (i > 0) { - rinsum += sir[0]; - ginsum += sir[1]; - binsum += sir[2]; - } else { - routsum += sir[0]; - goutsum += sir[1]; - boutsum += sir[2]; - } - - if (i < hm) { - yp += w; - } - } - yi = x; - stackpointer = radius; - for (y = 0; y < h; y++) { - // Preserve alpha channel: ( 0xff000000 & pix[yi] ) - pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum]; - - rsum -= routsum; - gsum -= goutsum; - bsum -= boutsum; - - stackstart = stackpointer - radius + div; - sir = stack[stackstart % div]; - - routsum -= sir[0]; - goutsum -= sir[1]; - boutsum -= sir[2]; - - if (x == 0) { - vmin[y] = Math.min(y + r1, hm) * w; - } - p = x + vmin[y]; - - sir[0] = r[p]; - sir[1] = g[p]; - sir[2] = b[p]; - - rinsum += sir[0]; - ginsum += sir[1]; - binsum += sir[2]; - - rsum += rinsum; - gsum += ginsum; - bsum += binsum; - - stackpointer = (stackpointer + 1) % div; - sir = stack[stackpointer]; - - routsum += sir[0]; - goutsum += sir[1]; - boutsum += sir[2]; - - rinsum -= sir[0]; - ginsum -= sir[1]; - binsum -= sir[2]; - - yi += w; - } - } - - Log.e("pix", w + " " + h + " " + pix.length); - bitmap.setPixels(pix, 0, w, 0, 0, w, h); - - return (bitmap); - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java index f6322d6f4..2a483ca9b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java @@ -10,7 +10,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; -import de.danoeh.antennapod.core.asynctask.PicassoImageResource; +import de.danoeh.antennapod.core.asynctask.ImageResource; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.flattr.FlattrStatus; import de.danoeh.antennapod.core.util.flattr.FlattrThing; @@ -20,7 +20,7 @@ import de.danoeh.antennapod.core.util.flattr.FlattrThing; * * @author daniel */ -public class Feed extends FeedFile implements FlattrThing, PicassoImageResource { +public class Feed extends FeedFile implements FlattrThing, ImageResource { public static final int FEEDFILETYPE_FEED = 0; public static final String TYPE_RSS2 = "rss"; public static final String TYPE_RSS091 = "rss"; diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java index c6f24367e..f77a78721 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java @@ -4,10 +4,10 @@ import android.net.Uri; import java.io.File; -import de.danoeh.antennapod.core.asynctask.PicassoImageResource; +import de.danoeh.antennapod.core.asynctask.ImageResource; -public class FeedImage extends FeedFile implements PicassoImageResource { +public class FeedImage extends FeedFile implements ImageResource { public static final int FEEDFILETYPE_FEEDIMAGE = 1; protected String title; diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java index 96a6c2ba1..c0af126f7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java @@ -10,7 +10,7 @@ import java.util.List; import java.util.concurrent.Callable; import de.danoeh.antennapod.core.ClientConfig; -import de.danoeh.antennapod.core.asynctask.PicassoImageResource; +import de.danoeh.antennapod.core.asynctask.ImageResource; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.util.ShownotesProvider; import de.danoeh.antennapod.core.util.flattr.FlattrStatus; @@ -21,7 +21,7 @@ import de.danoeh.antennapod.core.util.flattr.FlattrThing; * * @author daniel */ -public class FeedItem extends FeedComponent implements ShownotesProvider, FlattrThing, PicassoImageResource { +public class FeedItem extends FeedComponent implements ShownotesProvider, FlattrThing, ImageResource { /** * The id/guid that can be found in the rss/atom feed. Might not be set. @@ -337,7 +337,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr public Uri getImageUri() { if(media != null && media.hasEmbeddedPicture()) { return media.getImageUri(); - } else if (hasItemImageDownloaded()) { + } else if (image != null) { return image.getImageUri(); } else if (feed != null) { return feed.getImageUri(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java new file mode 100644 index 000000000..0baff9723 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java @@ -0,0 +1,33 @@ +package de.danoeh.antennapod.core.glide; + +import android.content.Context; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.GlideBuilder; +import com.bumptech.glide.load.DecodeFormat; +import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory; +import com.bumptech.glide.load.model.GlideUrl; +import com.bumptech.glide.module.GlideModule; + +import java.io.InputStream; + +import de.danoeh.antennapod.core.preferences.UserPreferences; + +/** + * {@see com.bumptech.glide.integration.okhttp.OkHttpGlideModule} + */ +public class ApGlideModule implements GlideModule { + + @Override + public void applyOptions(Context context, GlideBuilder builder) { + builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888); + builder.setDiskCache(new InternalCacheDiskCacheFactory(context, + UserPreferences.getImageCacheSize())); + } + + @Override + public void registerComponents(Context context, Glide glide) { + glide.register(GlideUrl.class, InputStream.class, new ApOkHttpUrlLoader.Factory()); + } + +} \ No newline at end of file diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpStreamFetcher.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpStreamFetcher.java new file mode 100644 index 000000000..13a148d1e --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpStreamFetcher.java @@ -0,0 +1,80 @@ +package de.danoeh.antennapod.core.glide; + +import com.bumptech.glide.Priority; +import com.bumptech.glide.load.data.DataFetcher; +import com.bumptech.glide.load.model.GlideUrl; +import com.bumptech.glide.util.ContentLengthInputStream; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; +import com.squareup.okhttp.ResponseBody; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +/** + * @see com.bumptech.glide.integration.okhttp.OkHttpStreamFetcher + */ +public class ApOkHttpStreamFetcher implements DataFetcher { + private final OkHttpClient client; + private final GlideUrl url; + private InputStream stream; + private ResponseBody responseBody; + + public ApOkHttpStreamFetcher(OkHttpClient client, GlideUrl url) { + this.client = client; + this.url = url; + } + + @Override + public InputStream loadData(Priority priority) throws Exception { + Request.Builder requestBuilder = new Request.Builder() + .url(url.toStringUrl()); + + for (Map.Entry headerEntry : url.getHeaders().entrySet()) { + String key = headerEntry.getKey(); + requestBuilder.addHeader(key, headerEntry.getValue()); + } + + Request request = requestBuilder.build(); + + Response response = client.newCall(request).execute(); + responseBody = response.body(); + if (!response.isSuccessful()) { + throw new IOException("Request failed with code: " + response.code()); + } + + long contentLength = responseBody.contentLength(); + stream = ContentLengthInputStream.obtain(responseBody.byteStream(), contentLength); + return stream; + } + + @Override + public void cleanup() { + if (stream != null) { + try { + stream.close(); + } catch (IOException e) { + // Ignored + } + } + if (responseBody != null) { + try { + responseBody.close(); + } catch (IOException e) { + // Ignored. + } + } + } + + @Override + public String getId() { + return url.getCacheKey(); + } + + @Override + public void cancel() { + // TODO: call cancel on the client when this method is called on a background thread. See #257 + } +} \ No newline at end of file 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 new file mode 100644 index 000000000..33290723b --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java @@ -0,0 +1,124 @@ +package de.danoeh.antennapod.core.glide; + +import android.content.Context; +import android.text.TextUtils; +import android.util.Log; + +import com.bumptech.glide.integration.okhttp.OkHttpStreamFetcher; +import com.bumptech.glide.load.data.DataFetcher; +import com.bumptech.glide.load.model.GenericLoaderFactory; +import com.bumptech.glide.load.model.GlideUrl; +import com.bumptech.glide.load.model.ModelLoader; +import com.bumptech.glide.load.model.ModelLoaderFactory; +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Response; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; + +import de.danoeh.antennapod.core.ClientConfig; +import de.danoeh.antennapod.core.service.download.HttpDownloader; +import de.danoeh.antennapod.core.storage.DBReader; + +/** + * @see com.bumptech.glide.integration.okhttp.OkHttpUrlLoader + */ +public class ApOkHttpUrlLoader implements ModelLoader { + + private static final String TAG = "ApOkHttpUrlLoader"; + + /** + * The default factory for {@link ApOkHttpUrlLoader}s. + */ + public static class Factory implements ModelLoaderFactory { + private static volatile OkHttpClient internalClient; + private OkHttpClient client; + + private static OkHttpClient getInternalClient() { + if (internalClient == null) { + synchronized (Factory.class) { + if (internalClient == null) { + internalClient = new OkHttpClient(); + internalClient.interceptors().add(new BasicAuthenticationInterceptor()); + } + } + } + return internalClient; + } + + /** + * Constructor for a new Factory that runs requests using a static singleton client. + */ + public Factory() { + this(getInternalClient()); + } + + /** + * Constructor for a new Factory that runs requests using given client. + */ + public Factory(OkHttpClient client) { + this.client = client; + } + + @Override + public ModelLoader build(Context context, GenericLoaderFactory factories) { + return new ApOkHttpUrlLoader(client); + } + + @Override + public void teardown() { + // Do nothing, this instance doesn't own the client. + } + } + + private final OkHttpClient client; + + public ApOkHttpUrlLoader(OkHttpClient client) { + this.client = client; + } + + @Override + public DataFetcher getResourceFetcher(GlideUrl model, int width, int height) { + return new OkHttpStreamFetcher(client, model); + } + + private static class BasicAuthenticationInterceptor implements Interceptor { + + @Override + public Response intercept(Chain chain) throws IOException { + com.squareup.okhttp.Request request = chain.request(); + String url = request.urlString(); + Context context = ClientConfig.applicationCallbacks.getApplicationInstance(); + String authentication = DBReader.getImageAuthentication(context, url); + + if(TextUtils.isEmpty(authentication)) { + Log.d(TAG, "no credentials for '" + url + "'"); + return chain.proceed(request); + } + + // add authentication + String[] auth = authentication.split(":"); + String credentials = HttpDownloader.encodeCredentials(auth[0], auth[1], "ISO-8859-1"); + com.squareup.okhttp.Request newRequest = request + .newBuilder() + .addHeader("Authorization", credentials) + .build(); + Log.d(TAG, "Basic authentication with ISO-8859-1 encoding"); + Response response = chain.proceed(newRequest); + if (!response.isSuccessful() && response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) { + credentials = HttpDownloader.encodeCredentials(auth[0], auth[1], "UTF-8"); + newRequest = request + .newBuilder() + .addHeader("Authorization", credentials) + .build(); + Log.d(TAG, "Basic authentication with UTF-8 encoding"); + return chain.proceed(newRequest); + } else { + return response; + } + } + } + +} \ No newline at end of file diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java new file mode 100644 index 000000000..f5e645535 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java @@ -0,0 +1,277 @@ +package de.danoeh.antennapod.core.glide; + +import android.content.Context; +import android.graphics.Bitmap; +import android.util.Log; + +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; + +public class FastBlurTransformation extends BitmapTransformation { + + private static final String TAG = "BlurTransformation"; + + private static final int RADIUS = 1; + private static final int IMAGE_SIZE = 192; + + public FastBlurTransformation(Context context) { + super(context); + } + + @Override + protected Bitmap transform(BitmapPool pool, Bitmap toTransform, + int outWidth, int outHeight) { + Bitmap resizedBitmap = Bitmap.createScaledBitmap(toTransform, IMAGE_SIZE, IMAGE_SIZE, true); + Bitmap transformed = fastBlur(resizedBitmap, RADIUS); + if (transformed == null) { + Log.w(TAG, "transformed was null"); + return toTransform; + } + return transformed; + } + + @Override + public String getId() { + return "FastBlurTransformation-" + IMAGE_SIZE + "x" + IMAGE_SIZE + "-" + RADIUS; + } + + private static Bitmap fastBlur(Bitmap original, int radius) { + + // Stack Blur v1.0 from + // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html + // + // Java Author: Mario Klingemann + // http://incubator.quasimondo.com + // created Feburary 29, 2004 + // Android port : Yahel Bouaziz + // http://www.kayenko.com + // ported april 5th, 2012 + + // This is a compromise between Gaussian Blur and Box blur + // It creates much better looking blurs than Box Blur, but is + // 7x faster than my Gaussian Blur implementation. + // + // I called it Stack Blur because this describes best how this + // filter works internally: it creates a kind of moving stack + // of colors whilst scanning through the image. Thereby it + // just has to add one new block of color to the right side + // of the stack and remove the leftmost color. The remaining + // colors on the topmost layer of the stack are either added on + // or reduced by one, depending on if they are on the right or + // on the left side of the stack. + // + // If you are using this algorithm in your code please add + // the following line: + // + // Stack Blur Algorithm by Mario Klingemann + + Bitmap.Config config = original.getConfig(); + if (config == null) { + // Sometimes the config can be null, in those cases + // we don't do a transform. + return null; + } + + Bitmap bitmap = original.copy(config, true); + + if (radius < 1) { + return null; + } + + int w = bitmap.getWidth(); + int h = bitmap.getHeight(); + + int[] pix = new int[w * h]; + Log.e("pix", w + " " + h + " " + pix.length); + bitmap.getPixels(pix, 0, w, 0, 0, w, h); + + int wm = w - 1; + int hm = h - 1; + int wh = w * h; + int div = radius + radius + 1; + + int r[] = new int[wh]; + int g[] = new int[wh]; + int b[] = new int[wh]; + int rsum, gsum, bsum, x, y, i, p, yp, yi, yw; + int vmin[] = new int[Math.max(w, h)]; + + int divsum = (div + 1) >> 1; + divsum *= divsum; + int dv[] = new int[256 * divsum]; + for (i = 0; i < 256 * divsum; i++) { + dv[i] = (i / divsum); + } + + yw = yi = 0; + + int[][] stack = new int[div][3]; + int stackpointer; + int stackstart; + int[] sir; + int rbs; + int r1 = radius + 1; + int routsum, goutsum, boutsum; + int rinsum, ginsum, binsum; + + for (y = 0; y < h; y++) { + rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; + for (i = -radius; i <= radius; i++) { + p = pix[yi + Math.min(wm, Math.max(i, 0))]; + sir = stack[i + radius]; + sir[0] = (p & 0xff0000) >> 16; + sir[1] = (p & 0x00ff00) >> 8; + sir[2] = (p & 0x0000ff); + rbs = r1 - Math.abs(i); + rsum += sir[0] * rbs; + gsum += sir[1] * rbs; + bsum += sir[2] * rbs; + if (i > 0) { + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + } else { + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + } + } + stackpointer = radius; + + for (x = 0; x < w; x++) { + + r[yi] = dv[rsum]; + g[yi] = dv[gsum]; + b[yi] = dv[bsum]; + + rsum -= routsum; + gsum -= goutsum; + bsum -= boutsum; + + stackstart = stackpointer - radius + div; + sir = stack[stackstart % div]; + + routsum -= sir[0]; + goutsum -= sir[1]; + boutsum -= sir[2]; + + if (y == 0) { + vmin[x] = Math.min(x + radius + 1, wm); + } + p = pix[yw + vmin[x]]; + + sir[0] = (p & 0xff0000) >> 16; + sir[1] = (p & 0x00ff00) >> 8; + sir[2] = (p & 0x0000ff); + + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + + rsum += rinsum; + gsum += ginsum; + bsum += binsum; + + stackpointer = (stackpointer + 1) % div; + sir = stack[(stackpointer) % div]; + + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + + rinsum -= sir[0]; + ginsum -= sir[1]; + binsum -= sir[2]; + + yi++; + } + yw += w; + } + for (x = 0; x < w; x++) { + rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; + yp = -radius * w; + for (i = -radius; i <= radius; i++) { + yi = Math.max(0, yp) + x; + + sir = stack[i + radius]; + + sir[0] = r[yi]; + sir[1] = g[yi]; + sir[2] = b[yi]; + + rbs = r1 - Math.abs(i); + + rsum += r[yi] * rbs; + gsum += g[yi] * rbs; + bsum += b[yi] * rbs; + + if (i > 0) { + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + } else { + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + } + + if (i < hm) { + yp += w; + } + } + yi = x; + stackpointer = radius; + for (y = 0; y < h; y++) { + // Preserve alpha channel: ( 0xff000000 & pix[yi] ) + pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum]; + + rsum -= routsum; + gsum -= goutsum; + bsum -= boutsum; + + stackstart = stackpointer - radius + div; + sir = stack[stackstart % div]; + + routsum -= sir[0]; + goutsum -= sir[1]; + boutsum -= sir[2]; + + if (x == 0) { + vmin[y] = Math.min(y + r1, hm) * w; + } + p = x + vmin[y]; + + sir[0] = r[p]; + sir[1] = g[p]; + sir[2] = b[p]; + + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + + rsum += rinsum; + gsum += ginsum; + bsum += binsum; + + stackpointer = (stackpointer + 1) % div; + sir = stack[stackpointer]; + + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + + rinsum -= sir[0]; + ginsum -= sir[1]; + binsum -= sir[2]; + + yi += w; + } + } + + Log.e("pix", w + " " + h + " " + pix.length); + bitmap.setPixels(pix, 0, w, 0, 0, w, h); + + return bitmap; + } + +} \ No newline at end of file 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 9f6b144ef..789a2366e 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 @@ -78,6 +78,7 @@ public class UserPreferences { // Other public static final String PREF_DATA_FOLDER = "prefDataFolder"; + public static final String PREF_IMAGE_CACHE_SIZE = "prefImageCacheSize"; // Mediaplayer public static final String PREF_PLAYBACK_SPEED = "prefPlaybackSpeed"; @@ -213,7 +214,6 @@ public class UserPreferences { public static String getPlaybackSpeed() { return prefs.getString(PREF_PLAYBACK_SPEED, "1.0"); - } public static String[] getPlaybackSpeedArray() { @@ -278,6 +278,12 @@ public class UserPreferences { return prefs.getBoolean(PREF_ENABLE_AUTODL_WIFI_FILTER, false); } + public static int getImageCacheSize() { + String cacheSizeString = prefs.getString(PREF_IMAGE_CACHE_SIZE, "100"); + int cacheSize = Integer.valueOf(cacheSizeString) * 1024 * 1024; + return cacheSize; + } + public static int getFastFowardSecs() { return prefs.getInt(PREF_FAST_FORWARD_SECS, 30); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 3df305027..19a710d24 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -777,52 +777,18 @@ public class DownloadService extends Service { for (int i = 0; i < savedFeeds.length; i++) { Feed savedFeed = savedFeeds[i]; - // Download Feed Image if provided and not downloaded - if (savedFeed.getImage() != null - && savedFeed.getImage().isDownloaded() == false) { - Log.d(TAG, "Feed has image; Downloading...."); - savedFeed.getImage().setOwner(savedFeed); - final Feed savedFeedRef = savedFeed; - try { - requester.downloadImage(DownloadService.this, - savedFeedRef.getImage()); - } catch (DownloadRequestException e) { - e.printStackTrace(); - DBWriter.addDownloadStatus( - DownloadService.this, - new DownloadStatus( - savedFeedRef.getImage(), - savedFeedRef - .getImage() - .getHumanReadableIdentifier(), - DownloadError.ERROR_REQUEST_ERROR, - false, e.getMessage() - ) - ); - } - } // queue new media files for automatic download for (FeedItem item : savedFeed.getItems()) { if(item.getPubDate() == null) { Log.d(TAG, item.toString()); } - if(item.getImage() != null && item.getImage().isDownloaded() == false) { - item.getImage().setOwner(item); - try { - requester.downloadImage(DownloadService.this, - item.getImage()); - } catch (DownloadRequestException e) { - e.printStackTrace(); - } - } if (!item.isPlayed() && item.hasMedia() && !item.getMedia().isDownloaded()) { newMediaFiles.add(item.getMedia().getId()); } } // If loadAllPages=true, check if another page is available and queue it for download - final boolean loadAllPages = results.get(i).first.getArguments().getBoolean(DownloadRequester.REQUEST_ARG_LOAD_ALL_PAGES); final Feed feed = results.get(i).second.feed; if (loadAllPages && feed.getNextPageLink() != null) { 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 737f0aefd..fd8608d88 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 @@ -29,7 +29,10 @@ import android.view.KeyEvent; import android.view.SurfaceHolder; import android.widget.Toast; -import com.squareup.picasso.Picasso; +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.request.animation.GlideAnimation; +import com.bumptech.glide.request.target.SimpleTarget; import org.apache.commons.lang3.StringUtils; @@ -791,16 +794,18 @@ public class PlaybackService extends Service { Log.d(TAG, "Starting background work"); if (android.os.Build.VERSION.SDK_INT >= 11) { if (info.playable != null) { - try { - int iconSize = getResources().getDimensionPixelSize( - android.R.dimen.notification_large_icon_width); - icon = Picasso.with(PlaybackService.this) - .load(info.playable.getImageUri()) - .resize(iconSize, iconSize) - .get(); - } catch (IOException e) { - e.printStackTrace(); - } + int iconSize = getResources().getDimensionPixelSize( + android.R.dimen.notification_large_icon_width); + Glide.with(PlaybackService.this) + .load(info.playable.getImageUri()) + .asBitmap() + .diskCacheStrategy(DiskCacheStrategy.SOURCE) + .into(new SimpleTarget(iconSize, iconSize) { + @Override + public void onResourceReady(Bitmap bitmap, GlideAnimation anim) { + icon = bitmap; + } + }); } } 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 cfbfd152b..5ed0a6ee3 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 @@ -871,7 +871,11 @@ public final class DBReader { if (cursor.moveToFirst()) { String username = cursor.getString(0); String password = cursor.getString(1); - return username + ":" + password; + if(username != null && password != null) { + return username + ":" + password; + } else { + return ""; + } } return ""; } finally { 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 b08013c65..770c4f7d7 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 @@ -283,24 +283,6 @@ public final class DBTasks { DownloadRequester.getInstance().downloadFeed(context, f, loadAllPages); } - /** - * Notifies the database about a missing FeedImage file. This method will attempt to re-download the file. - * - * @param context Used for requesting the download. - * @param image The FeedImage object. - */ - public static void notifyInvalidImageFile(final Context context, - final FeedImage image) { - Log.i(TAG, - "The DB was notified about an invalid image download. It will now try to re-download the image file"); - try { - DownloadRequester.getInstance().downloadImage(context, image); - } catch (DownloadRequestException e) { - e.printStackTrace(); - Log.w(TAG, "Failed to download invalid feed image"); - } - } - /** * Notifies the database about a missing FeedMedia file. This method will correct the FeedMedia object's values in the * DB and send a FeedUpdateBroadcast. diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java index ca6aa0178..74dce17f4 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java @@ -18,7 +18,6 @@ import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedFile; -import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.DownloadRequest; @@ -186,15 +185,6 @@ public class DownloadRequester { downloadFeed(context, feed, false); } - public synchronized void downloadImage(Context context, FeedImage image) - throws DownloadRequestException { - if (feedFileValid(image)) { - FeedFile container = (image.getOwner() instanceof FeedFile) ? (FeedFile) image.getOwner() : null; - download(context, image, container, new File(getImagefilePath(context), - getImagefileName(image)), false, null, null, 0, false, null); - } - } - public synchronized void downloadMedia(Context context, FeedMedia feedmedia) throws DownloadRequestException { if (feedFileValid(feedmedia)) { @@ -332,20 +322,6 @@ public class DownloadRequester { return "feed-" + FileNameGenerator.generateFileName(filename); } - public synchronized String getImagefilePath(Context context) - throws DownloadRequestException { - return getExternalFilesDirOrThrowException(context, IMAGE_DOWNLOADPATH) - .toString() + "/"; - } - - public synchronized String getImagefileName(FeedImage image) { - String filename = image.getDownload_url(); - if (image.getOwner() != null && image.getOwner().getHumanReadableIdentifier() != null) { - filename = image.getOwner().getHumanReadableIdentifier(); - } - return "image-" + FileNameGenerator.generateFileName(filename); - } - public synchronized String getMediafilePath(Context context, FeedMedia media) throws DownloadRequestException { File externalStorage = getExternalFilesDirOrThrowException( diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java index 7ebd580f7..752e95985 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java @@ -7,7 +7,7 @@ import android.util.Log; import java.util.List; -import de.danoeh.antennapod.core.asynctask.PicassoImageResource; +import de.danoeh.antennapod.core.asynctask.ImageResource; import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; @@ -18,7 +18,7 @@ import de.danoeh.antennapod.core.util.ShownotesProvider; * Interface for objects that can be played by the PlaybackService. */ public interface Playable extends Parcelable, - ShownotesProvider, PicassoImageResource { + ShownotesProvider, ImageResource { /** * Save information about the playable in a preference so that it can be diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 3c852360c..f2a80cd38 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -174,4 +174,20 @@ not_downloaded + + 20 MiB + 50 MiB + 100 MiB + 250 MiB + 500 MiB + + + + 20 + 50 + 100 + 250 + 500 + + diff --git a/core/src/main/res/values/colors.xml b/core/src/main/res/values/colors.xml index e558a5c4e..bc0521dcd 100644 --- a/core/src/main/res/values/colors.xml +++ b/core/src/main/res/values/colors.xml @@ -3,6 +3,7 @@ #FFFFFF #808080 + #bfbfbf #000000 #33B5E5 #858585 diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 5079950fa..e91030e93 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -331,12 +331,12 @@ Keep notification and lockscreen controls when playback is paused. Show Download Report If downloads fail, generate a report that shows the details of the failure. - Android versions before 4.1 do not support expanded notifications. Add new episodes to the front of the queue. Enqueue at Front Disabled - + Image Cache Size + Size of the disk cache for images. Enable automatic flattring @@ -431,6 +431,7 @@ Pause for Interruptions Resume playback after a phone call completes Resume after Call + AnntennaPod has to be restarted for this change to take effect. Subscribe @@ -464,6 +465,7 @@ Upgrading the database + Clearing old image cache diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index 8619869c8..85c908f64 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -263,7 +263,9 @@ -- cgit v1.2.3 From 66e5c4fdf1325758e03a6146703ae2fd2c68f3db Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Wed, 29 Jul 2015 18:30:29 +0200 Subject: Improve datetime parser --- .../antennapod/core/tests/util/DateUtilsTest.java | 19 +++++++++++++++ .../de/danoeh/antennapod/core/util/DateUtils.java | 28 ++++++++++++++++++---- 2 files changed, 42 insertions(+), 5 deletions(-) (limited to 'core/src') diff --git a/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java b/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java index 7429b50b3..2727b1447 100644 --- a/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java +++ b/core/src/androidTest/java/de/danoeh/antennapod/core/tests/util/DateUtilsTest.java @@ -13,6 +13,7 @@ public class DateUtilsTest extends AndroidTestCase { public void testParseDateWithMicroseconds() throws Exception { GregorianCalendar exp = new GregorianCalendar(2015, 2, 28, 13, 31, 4); + exp.setTimeZone(TimeZone.getTimeZone("UTC")); Date expected = new Date(exp.getTimeInMillis() + 963); Date actual = DateUtils.parse("2015-03-28T13:31:04.963870"); assertEquals(expected, actual); @@ -20,6 +21,7 @@ public class DateUtilsTest extends AndroidTestCase { public void testParseDateWithCentiseconds() throws Exception { GregorianCalendar exp = new GregorianCalendar(2015, 2, 28, 13, 31, 4); + exp.setTimeZone(TimeZone.getTimeZone("UTC")); Date expected = new Date(exp.getTimeInMillis() + 960); Date actual = DateUtils.parse("2015-03-28T13:31:04.96"); assertEquals(expected, actual); @@ -27,6 +29,7 @@ public class DateUtilsTest extends AndroidTestCase { public void testParseDateWithDeciseconds() throws Exception { GregorianCalendar exp = new GregorianCalendar(2015, 2, 28, 13, 31, 4); + exp.setTimeZone(TimeZone.getTimeZone("UTC")); Date expected = new Date(exp.getTimeInMillis() + 900); Date actual = DateUtils.parse("2015-03-28T13:31:04.9"); assertEquals(expected.getTime()/1000, actual.getTime()/1000); @@ -82,4 +85,20 @@ public class DateUtilsTest extends AndroidTestCase { assertEquals(expected, actual); } + public void testAsctime() throws Exception { + GregorianCalendar exp = new GregorianCalendar(2011, 4, 25, 12, 33, 00); + exp.setTimeZone(TimeZone.getTimeZone("UTC")); + Date expected = new Date(exp.getTimeInMillis()); + Date actual = DateUtils.parse("Wed, 25 May 2011 12:33:00"); + assertEquals(expected, actual); + } + + public void testMultipleConsecutiveSpaces() throws Exception { + GregorianCalendar exp = new GregorianCalendar(2010, 2, 23, 6, 6, 26); + exp.setTimeZone(TimeZone.getTimeZone("UTC")); + Date expected = new Date(exp.getTimeInMillis()); + Date actual = DateUtils.parse("Tue, 23 Mar 2010 01:06:26 -0500"); + assertEquals(expected, actual); + } + } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java index 7b06128f9..c0233f684 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java @@ -8,6 +8,7 @@ import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; +import java.util.TimeZone; /** * Parses several date formats. @@ -17,50 +18,66 @@ public class DateUtils { private static final String TAG = "DateUtils"; private static final SimpleDateFormat parser = new SimpleDateFormat("", Locale.US); + private static final TimeZone defaultTimezone = TimeZone.getTimeZone("GMT"); + static { parser.setLenient(false); + parser.setTimeZone(defaultTimezone); } public static Date parse(final String input) { if(input == null) { - throw new IllegalArgumentException("Date most not be null"); + throw new IllegalArgumentException("Date must not be null"); } - String date = input.replace('/', '-'); + String date = input.trim().replace('/', '-').replaceAll("( ){2,}+", " "); + + // if datetime is more precise than seconds, make sure the value is in ms if(date.contains(".")) { int start = date.indexOf('.'); int current = start+1; while(current < date.length() && Character.isDigit(date.charAt(current))) { current++; } + // even more precise than microseconds: discard further decimal places if(current - start > 4) { if(current < date.length()-1) { date = date.substring(0, start + 4) + date.substring(current); } else { date = date.substring(0, start + 4); } + // less than 4 decimal places: pad to have a consistent format for the parser } else if(current - start < 4) { if(current < date.length()-1) { date = date.substring(0, current) + StringUtils.repeat("0", 4-(current-start)) + date.substring(current); } else { date = date.substring(0, current) + StringUtils.repeat("0", 4-(current-start)); } - } } String[] patterns = { "dd MMM yy HH:mm:ss Z", "dd MMM yy HH:mm Z", "EEE, dd MMM yyyy HH:mm:ss Z", + "EEE, dd MMM yyyy HH:mm:ss", "EEE, dd MMMM yyyy HH:mm:ss Z", + "EEE, dd MMMM yyyy HH:mm:ss", + "EEEE, dd MMM yyyy HH:mm:ss Z", "EEEE, dd MMM yy HH:mm:ss Z", + "EEEE, dd MMM yyyy HH:mm:ss", + "EEEE, dd MMM yy HH:mm:ss", "EEE MMM d HH:mm:ss yyyy", "EEE, dd MMM yyyy HH:mm Z", + "EEE, dd MMM yyyy HH:mm", "EEE, dd MMMM yyyy HH:mm Z", + "EEE, dd MMMM yyyy HH:mm", + "EEEE, dd MMM yyyy HH:mm Z", "EEEE, dd MMM yy HH:mm Z", + "EEEE, dd MMM yyyy HH:mm", + "EEEE, dd MMM yy HH:mm", "EEE MMM d HH:mm yyyy", "yyyy-MM-dd'T'HH:mm:ss", - "yyyy-MM-dd'T'HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ss.SSS Z", + "yyyy-MM-dd'T'HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ssZ", "yyyy-MM-dd'T'HH:mm:ss'Z'", "yyyy-MM-ddZ", @@ -77,7 +94,7 @@ public class DateUtils { } } - Log.d(TAG, "Could not parse date string \"" + input + "\""); + Log.d(TAG, "Could not parse date string \"" + input + "\" [" + date + "]"); return null; } @@ -117,6 +134,7 @@ public class DateUtils { public static String formatRFC3339UTC(Date date) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); + format.setTimeZone(defaultTimezone); return format.format(date); } } -- cgit v1.2.3 From 5f41d422aa4b68ebf853101d4c3488f5c711540e Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Wed, 29 Jul 2015 20:36:27 +0200 Subject: Retro-actively disable auto download for episodes that were downloaded, were partially or completely played and are not queued currently --- .../main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'core/src') 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 d0402710c..c7eadcbb6 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 @@ -1477,7 +1477,7 @@ public class PodDBAdapter { */ private static class PodDBHelper extends SQLiteOpenHelper { - private final static int VERSION = 18; + private final static int VERSION = 1030002; private Context context; @@ -1702,6 +1702,11 @@ public class PodDBAdapter { db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0"); } + if(oldVersion < 1030002) { + db.execSQL("UPDATE FeedItems SET auto_download=0 WHERE " + + "(read=1 OR id IN (SELECT id FROM FeedMedia WHERE position>0 OR downloaded=1)) " + + "AND id NOT IN (SELECT feeditem FROM Queue)"); + } EventBus.getDefault().post(ProgressEvent.end()); } } -- cgit v1.2.3 From 4f7566ddfca14754ebe28cd49e63a1db0c992d78 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 31 Jul 2015 10:50:38 +0200 Subject: Improved blurring --- .../core/glide/FastBlurTransformation.java | 40 ++++++++-------------- core/src/main/res/values/strings.xml | 1 - 2 files changed, 15 insertions(+), 26 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java index f5e645535..ee58c2f39 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java @@ -2,6 +2,7 @@ package de.danoeh.antennapod.core.glide; import android.content.Context; import android.graphics.Bitmap; +import android.media.ThumbnailUtils; import android.util.Log; import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; @@ -9,33 +10,35 @@ import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; public class FastBlurTransformation extends BitmapTransformation { - private static final String TAG = "BlurTransformation"; + private static final String TAG = FastBlurTransformation.class.getSimpleName(); - private static final int RADIUS = 1; - private static final int IMAGE_SIZE = 192; + private static final int STACK_BLUR_RADIUS = 1; + private static final int BLUR_IMAGE_WIDTH = 150; public FastBlurTransformation(Context context) { super(context); } @Override - protected Bitmap transform(BitmapPool pool, Bitmap toTransform, + protected Bitmap transform(BitmapPool pool, Bitmap source, int outWidth, int outHeight) { - Bitmap resizedBitmap = Bitmap.createScaledBitmap(toTransform, IMAGE_SIZE, IMAGE_SIZE, true); - Bitmap transformed = fastBlur(resizedBitmap, RADIUS); - if (transformed == null) { - Log.w(TAG, "transformed was null"); - return toTransform; + int targetWidth = BLUR_IMAGE_WIDTH; + int targetHeight = (int) (1.0 * outHeight * targetWidth / outWidth); + Bitmap resized = ThumbnailUtils.extractThumbnail(source, targetWidth, targetHeight); + Bitmap result = fastBlur(resized, STACK_BLUR_RADIUS); + if (result == null) { + Log.w(TAG, "result was null"); + return source; } - return transformed; + return result; } @Override public String getId() { - return "FastBlurTransformation-" + IMAGE_SIZE + "x" + IMAGE_SIZE + "-" + RADIUS; + return "FastBlurTransformation[width=" + BLUR_IMAGE_WIDTH + "px,radius=" + STACK_BLUR_RADIUS +"]"; } - private static Bitmap fastBlur(Bitmap original, int radius) { + private static Bitmap fastBlur(Bitmap bitmap, int radius) { // Stack Blur v1.0 from // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html @@ -65,15 +68,6 @@ public class FastBlurTransformation extends BitmapTransformation { // // Stack Blur Algorithm by Mario Klingemann - Bitmap.Config config = original.getConfig(); - if (config == null) { - // Sometimes the config can be null, in those cases - // we don't do a transform. - return null; - } - - Bitmap bitmap = original.copy(config, true); - if (radius < 1) { return null; } @@ -82,7 +76,6 @@ public class FastBlurTransformation extends BitmapTransformation { int h = bitmap.getHeight(); int[] pix = new int[w * h]; - Log.e("pix", w + " " + h + " " + pix.length); bitmap.getPixels(pix, 0, w, 0, 0, w, h); int wm = w - 1; @@ -267,10 +260,7 @@ public class FastBlurTransformation extends BitmapTransformation { yi += w; } } - - Log.e("pix", w + " " + h + " " + pix.length); bitmap.setPixels(pix, 0, w, 0, 0, w, h); - return bitmap; } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index e91030e93..21a35cdb7 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -465,7 +465,6 @@ Upgrading the database - Clearing old image cache -- cgit v1.2.3 From cf519ca0aa1637c716a780b9a2f855a83fb1d6af Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 1 Aug 2015 12:17:50 +0200 Subject: Dialog when podcast's auto download preference is changed When the user changes a podcast's auto download setting, ask if this new setting should be applied to the podcast's episodes --- .../antennapod/core/dialog/ConfirmationDialog.java | 10 ++++----- .../danoeh/antennapod/core/storage/DBWriter.java | 25 ++++++++++++++++++++++ .../antennapod/core/storage/PodDBAdapter.java | 7 ++++++ core/src/main/res/values/strings.xml | 2 ++ 4 files changed, 39 insertions(+), 5 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java b/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java index ba1add895..ffaed084a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java +++ b/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java @@ -4,7 +4,7 @@ import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.util.Log; -import de.danoeh.antennapod.core.BuildConfig; + import de.danoeh.antennapod.core.R; /** @@ -12,9 +12,10 @@ import de.danoeh.antennapod.core.R; * classes can handle events like confirmation or cancellation. */ public abstract class ConfirmationDialog { - private static final String TAG = "ConfirmationDialog"; - Context context; + private static final String TAG = ConfirmationDialog.class.getSimpleName(); + + protected Context context; int titleId; int messageId; @@ -25,8 +26,7 @@ public abstract class ConfirmationDialog { } public void onCancelButtonPressed(DialogInterface dialog) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Dialog was cancelled"); + Log.d(TAG, "Dialog was cancelled"); dialog.dismiss(); } 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 acdcf5f85..12bc208a6 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 @@ -1110,9 +1110,34 @@ public class DBWriter { EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); } }); + } + + /** + * Sets the 'auto_download'-attribute of specific FeedItem. + * + * @param context A context that is used for opening a database connection. + * @param feed This feed's episodes will be processed. + * @param autoDownload If true, auto download will be enabled for the feed's episodes. Else, + * it will be disabled. + */ + public static Future setFeedsItemsAutoDownload(final Context context, final Feed feed, + final boolean autoDownload) { + Log.d(TAG, (autoDownload ? "Enabling" : "Disabling") + " auto download for items of feed " + feed.getId()); + return dbExec.submit(new Runnable() { + @Override + public void run() { + final PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + adapter.setFeedsItemsAutoDownload(feed, autoDownload); + adapter.close(); + + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + } + }); } + /** * Set filter of the feed * 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 d0402710c..a1f11a1b6 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 @@ -861,6 +861,13 @@ public class PodDBAdapter { new String[]{String.valueOf(feedItem.getId())}); } + public void setFeedsItemsAutoDownload(Feed feed, boolean autoDownload) { + final String sql = "UPDATE " + TABLE_NAME_FEED_ITEMS + + " SET " + KEY_AUTO_DOWNLOAD + "="+ (autoDownload ? "1" : "0") + + " WHERE " + KEY_FEED + "=" + feed.getId(); + db.execSQL(sql); + } + public long getDownloadLogSize() { final String query = String.format("SELECT COUNT(%s) FROM %s", KEY_ID, TABLE_NAME_DOWNLOAD_LOG); Cursor result = db.rawQuery(query, null); diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 5079950fa..3a9e30ea6 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -75,6 +75,8 @@ Close Retry Include in auto downloads + Apply Setting to Episodes + Do you want to apply the podcast\'s new Auto Download setting to all of its episodes? Auto Delete Episode\n(override global default) \u0020parallel downloads Global -- cgit v1.2.3 From d9f8dc53a6bd5b812f27656faea00de5d2f71b5f Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 28 Jun 2015 21:55:38 -0400 Subject: removed flattr this app button --- .../main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java | 2 -- 1 file changed, 2 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java index 50792ae26..502b23a89 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java @@ -42,8 +42,6 @@ public class FlattrUtils { private static final String PREF_ACCESS_TOKEN = "de.danoeh.antennapod.preference.flattrAccessToken"; - // Flattr URL for this app. - public static final String APP_URL = "http://antennapod.com"; // Human-readable flattr-page. public static final String APP_LINK = "https://flattr.com/thing/745609/"; public static final String APP_THING_ID = "745609"; -- cgit v1.2.3 From 8cb5f68dd7f0b050e8d51f4b5f3320c6bad8c9f4 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 1 Aug 2015 10:49:18 -0400 Subject: removed unused code. fixes AntennaPod/AntennaPod#935 --- .../antennapod/core/util/flattr/FlattrUtils.java | 47 ---------------------- 1 file changed, 47 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java index 502b23a89..3b9e6120c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java @@ -42,10 +42,6 @@ public class FlattrUtils { private static final String PREF_ACCESS_TOKEN = "de.danoeh.antennapod.preference.flattrAccessToken"; - // Human-readable flattr-page. - public static final String APP_LINK = "https://flattr.com/thing/745609/"; - public static final String APP_THING_ID = "745609"; - private static volatile AccessToken cachedToken; private static AndroidAuthenticator createAuthenticator() { @@ -108,18 +104,6 @@ public class FlattrUtils { storeToken(null); } - public static Thing getAppThing(Context context) { - FlattrService fs = FlattrServiceCreator.getService(retrieveToken()); - try { - Thing thing = fs.getThing(Thing.withId(APP_THING_ID)); - return thing; - } catch (FlattrException e) { - e.printStackTrace(); - showErrorDialog(context, e.getMessage()); - return null; - } - } - public static void clickUrl(Context context, String url) throws FlattrException { if (hasToken()) { @@ -243,37 +227,6 @@ public class FlattrUtils { } } - public static void showForbiddenDialog(final Context context, - final String url) { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(R.string.action_forbidden_title); - builder.setMessage(R.string.action_forbidden_msg); - builder.setPositiveButton(R.string.authenticate_now_label, - new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - context.startActivity( - ClientConfig.flattrCallbacks.getFlattrAuthenticationActivityIntent(context)); - } - - } - ); - builder.setNegativeButton(R.string.visit_website_label, - new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - Uri uri = Uri.parse(url); - context.startActivity(new Intent(Intent.ACTION_VIEW, - uri)); - } - - } - ); - builder.create().show(); - } - public static void showErrorDialog(final Context context, final String msg) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.error_label); -- cgit v1.2.3 From a9d353ea2bd35c582f52b8ec37a4c10a9c35e98e Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 1 Aug 2015 11:07:46 -0400 Subject: removed unused method --- core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java index 96a6c2ba1..12b9a7db5 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java @@ -274,11 +274,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr public void setContentEncoded(String contentEncoded) { this.contentEncoded = contentEncoded; } - - public void setFlattrStatus(FlattrStatus status) { - this.flattrStatus = status; - } - + public FlattrStatus getFlattrStatus() { return flattrStatus; } -- cgit v1.2.3 From a3ea16b90c7a9183e1fc856e44f9e5970ab4d196 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 1 Aug 2015 17:53:06 +0200 Subject: Made dialog better, not to say awesome --- .../antennapod/core/dialog/ConfirmationDialog.java | 16 ++++++++++++++-- core/src/main/res/values/strings.xml | 6 ++++-- 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java b/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java index ffaed084a..fea2bbb2b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java +++ b/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java @@ -19,6 +19,9 @@ public abstract class ConfirmationDialog { int titleId; int messageId; + int positiveText; + int negativeText; + public ConfirmationDialog(Context context, int titleId, int messageId) { this.context = context; this.titleId = titleId; @@ -30,13 +33,22 @@ public abstract class ConfirmationDialog { dialog.dismiss(); } + public void setPositiveText(int id) { + this.positiveText = id; + } + + public void setNegativeText(int id) { + this.negativeText = id; + } + + public abstract void onConfirmButtonPressed(DialogInterface dialog); public final AlertDialog createNewDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(titleId); builder.setMessage(messageId); - builder.setPositiveButton(R.string.confirm_label, + builder.setPositiveButton(positiveText != 0 ? positiveText : R.string.confirm_label, new DialogInterface.OnClickListener() { @Override @@ -44,7 +56,7 @@ public abstract class ConfirmationDialog { onConfirmButtonPressed(dialog); } }); - builder.setNegativeButton(R.string.cancel_label, + builder.setNegativeButton(negativeText != 0 ? negativeText : R.string.cancel_label, new DialogInterface.OnClickListener() { @Override diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 3a9e30ea6..a692dbc73 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -53,6 +53,8 @@ Confirm Cancel + Yes + No Author Language URL @@ -75,8 +77,8 @@ Close Retry Include in auto downloads - Apply Setting to Episodes - Do you want to apply the podcast\'s new Auto Download setting to all of its episodes? + Apply to Previous Episodes + The new Auto Download setting will automatically be applied to new episodes.\nDo you also want to apply it to previous episodes? Auto Delete Episode\n(override global default) \u0020parallel downloads Global -- cgit v1.2.3 From 65d470043baf7f3f7d7009d16255e33b68af3650 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 2 Aug 2015 17:43:41 +0200 Subject: Fix duration overflow and time unit plurals --- .../java/de/danoeh/antennapod/core/util/Converter.java | 16 ++++++++-------- core/src/main/res/values/strings.xml | 15 ++++++++++++--- 2 files changed, 20 insertions(+), 11 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java b/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java index 917f99564..2bf88b3f3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java @@ -26,7 +26,7 @@ public final class Converter { /** Determines the length of the number for best readability.*/ private static final int NUM_LENGTH = 1024; - + private static final int DAYS_MIL = 86400000; private static final int HOURS_MIL = 3600000; private static final int MINUTES_MIL = 60000; private static final int SECONDS_MIL = 1000; @@ -104,18 +104,18 @@ public final class Converter { } /** Converts milliseconds to a localized string containing hours and minutes */ - public static String getDurationStringLocalized(Context context, int duration) { - int h = duration / HOURS_MIL; - int rest = duration - h * HOURS_MIL; + public static String getDurationStringLocalized(Context context, long duration) { + int h = (int)(duration / HOURS_MIL); + int rest = (int)(duration - h * HOURS_MIL); int m = rest / MINUTES_MIL; String result = ""; if(h > 0) { - String hours = context.getString(R.string.time_unit_hours); - result += h + " " + hours + " "; + String hours = context.getResources().getQuantityString(R.plurals.time_unit_hours, h, h); + result += hours + " "; } - String minutes = context.getString(R.string.time_unit_minutes); - result += m + " " + minutes; + String minutes = context.getResources().getQuantityString(R.plurals.time_unit_minutes, m, m); + result += minutes; return result; } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 21a35cdb7..eca366a2d 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -380,9 +380,18 @@ Sleep timer Time left:\u0020 Invalid input, time has to be an integer - seconds - minutes - hours + + 1 second + %d seconds + + + 1 minute + %d minutes + + + 1 hour + %d hours + CATEGORIES -- cgit v1.2.3 From ab116ee6be1c268787cc3496ae257990ec42a560 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 2 Aug 2015 17:48:08 +0200 Subject: Initialize NetworkUtils, set context once Had some issues with the new NetworkAllowanceInterceptor. When I gave it a constructor that would hold the context (to use it with NetworkUtils), the whole Glide image loading process would not work. --- .../core/asynctask/FlattrClickWorker.java | 2 +- .../core/receiver/FeedUpdateReceiver.java | 2 +- .../core/service/FeedMediaSizeService.java | 4 +-- .../core/service/GpodnetSyncService.java | 2 +- .../core/storage/APDownloadAlgorithm.java | 2 +- .../danoeh/antennapod/core/util/NetworkUtils.java | 31 ++++++++++------------ 6 files changed, 20 insertions(+), 23 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java index 5d2d5d441..f91d4557e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java @@ -90,7 +90,7 @@ public class FlattrClickWorker extends AsyncTask list = DBReader.getFeedMediaUnknownSize(this); for (FeedMedia media : list) { Log.d(TAG, "Getting size currently " + media.getSize() + " for " + media.getDownload_url()); - if(false == NetworkUtils.isDownloadAllowed(this)) { + if(false == NetworkUtils.isDownloadAllowed()) { return; } long size = Integer.MIN_VALUE; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java index 3f2222f42..b80b4303f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java @@ -108,7 +108,7 @@ public class GpodnetSyncService extends Service { private synchronized void sync() { - if (GpodnetPreferences.loggedIn() == false || NetworkUtils.networkAvailable(this) == false) { + if (GpodnetPreferences.loggedIn() == false || NetworkUtils.networkAvailable() == false) { stopSelf(); return; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java index 92de1eee7..0e6b23696 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java @@ -40,7 +40,7 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm { public void run() { // true if we should auto download based on network status - boolean networkShouldAutoDl = NetworkUtils.autodownloadNetworkAvailable(context) + boolean networkShouldAutoDl = NetworkUtils.autodownloadNetworkAvailable() && UserPreferences.isEnableAutodownload(); // true if we should auto download based on power status diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java index 3a349e221..9296039f0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java @@ -10,14 +10,16 @@ import android.util.Log; import java.util.Arrays; import java.util.List; -import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.preferences.UserPreferences; public class NetworkUtils { - private static final String TAG = "NetworkUtils"; - private NetworkUtils() { + private static final String TAG = NetworkUtils.class.getSimpleName(); + private static Context context; + + public static void init(Context context) { + NetworkUtils.context = context; } /** @@ -26,18 +28,16 @@ public class NetworkUtils { * network that is on the 'selected networks' list of the Wi-Fi filter for * automatic downloads and false otherwise. * */ - public static boolean autodownloadNetworkAvailable(Context context) { + public static boolean autodownloadNetworkAvailable() { ConnectivityManager cm = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = cm.getActiveNetworkInfo(); if (networkInfo != null) { if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Device is connected to Wi-Fi"); + Log.d(TAG, "Device is connected to Wi-Fi"); if (networkInfo.isConnected()) { if (!UserPreferences.isEnableAutodownloadWifiFilter()) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Auto-dl filter is disabled"); + Log.d(TAG, "Auto-dl filter is disabled"); return true; } else { WifiManager wm = (WifiManager) context @@ -48,31 +48,28 @@ public class NetworkUtils { .getAutodownloadSelectedNetworks()); if (selectedNetworks.contains(Integer.toString(wifiInfo .getNetworkId()))) { - if (BuildConfig.DEBUG) - Log.d(TAG, - "Current network is on the selected networks list"); + Log.d(TAG, "Current network is on the selected networks list"); return true; } } } } } - if (BuildConfig.DEBUG) - Log.d(TAG, "Network for auto-dl is not available"); + Log.d(TAG, "Network for auto-dl is not available"); return false; } - public static boolean networkAvailable(Context context) { + public static boolean networkAvailable() { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo info = cm.getActiveNetworkInfo(); return info != null && info.isConnected(); } - public static boolean isDownloadAllowed(Context context) { - return UserPreferences.isAllowMobileUpdate() || NetworkUtils.connectedToWifi(context); + public static boolean isDownloadAllowed() { + return UserPreferences.isAllowMobileUpdate() || NetworkUtils.connectedToWifi(); } - public static boolean connectedToWifi(Context context) { + public static boolean connectedToWifi() { ConnectivityManager connManager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo mWifi = connManager -- cgit v1.2.3 From 0824af6325e18d9b3c10d43807b94ba3f6ad88da Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 2 Aug 2015 17:49:52 +0200 Subject: Fix loading the notification image --- .../core/service/playback/PlaybackService.java | 56 +++++++++------------- 1 file changed, 23 insertions(+), 33 deletions(-) (limited to 'core/src') 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 fd8608d88..aa1816e1c 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 @@ -38,6 +38,7 @@ import org.apache.commons.lang3.StringUtils; import java.io.IOException; import java.util.List; +import java.util.concurrent.ExecutionException; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.R; @@ -772,7 +773,7 @@ public class PlaybackService extends Service { /** * Used by setupNotification to load notification data in another thread. */ - private AsyncTask notificationSetupTask; + private Thread notificationSetupThread; /** * Prepares notification and starts the service in the foreground. @@ -783,52 +784,47 @@ public class PlaybackService extends Service { PlaybackService.getPlayerActivityIntent(this), PendingIntent.FLAG_UPDATE_CURRENT); - if (notificationSetupTask != null) { - notificationSetupTask.cancel(true); + if (notificationSetupThread != null) { + notificationSetupThread.interrupt(); } - notificationSetupTask = new AsyncTask() { + Runnable notificationSetupTask = new Runnable() { Bitmap icon = null; @Override - protected Void doInBackground(Void... params) { + public void run() { Log.d(TAG, "Starting background work"); if (android.os.Build.VERSION.SDK_INT >= 11) { if (info.playable != null) { int iconSize = getResources().getDimensionPixelSize( android.R.dimen.notification_large_icon_width); - Glide.with(PlaybackService.this) - .load(info.playable.getImageUri()) - .asBitmap() - .diskCacheStrategy(DiskCacheStrategy.SOURCE) - .into(new SimpleTarget(iconSize, iconSize) { - @Override - public void onResourceReady(Bitmap bitmap, GlideAnimation anim) { - icon = bitmap; - } - }); + try { + icon = Glide.with(PlaybackService.this) + .load(info.playable.getImageUri()) + .asBitmap() + .diskCacheStrategy(DiskCacheStrategy.SOURCE) + .into(-1, -1) // this resizing would not be exact, so we have + // scale the bitmap ourselves + .get(); + icon = Bitmap.createScaledBitmap(icon, iconSize, iconSize, true); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } } - } if (icon == null) { icon = BitmapFactory.decodeResource(getApplicationContext().getResources(), ClientConfig.playbackServiceCallbacks.getNotificationIconResource(getApplicationContext())); } - return null; - } - - @Override - protected void onPostExecute(Void result) { - super.onPostExecute(result); if (mediaPlayer == null) { return; } PlayerStatus playerStatus = mediaPlayer.getPlayerStatus(); final int smallIcon = ClientConfig.playbackServiceCallbacks.getNotificationIconResource(getApplicationContext()); - if (!isCancelled() && - started && - info.playable != null) { + if (!Thread.currentThread().isInterrupted() && started && info.playable != null) { String contentText = info.playable.getFeedTitle(); String contentTitle = info.playable.getEpisodeTitle(); Notification notification = null; @@ -906,15 +902,9 @@ public class PlaybackService extends Service { Log.d(TAG, "Notification set up"); } } - }; - if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) { - notificationSetupTask - .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } else { - notificationSetupTask.execute(); - } - + notificationSetupThread = new Thread(notificationSetupTask); + notificationSetupThread.start(); } /** -- cgit v1.2.3 From 4165d848d8d8956c4fa14002920ec17729551b34 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 2 Aug 2015 17:51:33 +0200 Subject: Respect the mobile download settings --- .../antennapod/core/glide/ApOkHttpUrlLoader.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'core/src') 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 33290723b..433ba8db4 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 @@ -21,18 +21,20 @@ import java.net.HttpURLConnection; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.service.download.HttpDownloader; import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.core.util.NetworkUtils; /** * @see com.bumptech.glide.integration.okhttp.OkHttpUrlLoader */ public class ApOkHttpUrlLoader implements ModelLoader { - private static final String TAG = "ApOkHttpUrlLoader"; + private static final String TAG = ApOkHttpUrlLoader.class.getSimpleName(); /** * The default factory for {@link ApOkHttpUrlLoader}s. */ public static class Factory implements ModelLoaderFactory { + private static volatile OkHttpClient internalClient; private OkHttpClient client; @@ -41,6 +43,7 @@ public class ApOkHttpUrlLoader implements ModelLoader { synchronized (Factory.class) { if (internalClient == null) { internalClient = new OkHttpClient(); + internalClient.interceptors().add(new NetworkAllowanceInterceptor()); internalClient.interceptors().add(new BasicAuthenticationInterceptor()); } } @@ -84,6 +87,19 @@ public class ApOkHttpUrlLoader implements ModelLoader { return new OkHttpStreamFetcher(client, model); } + private static class NetworkAllowanceInterceptor implements Interceptor { + + @Override + public Response intercept(Chain chain) throws IOException { + if (NetworkUtils.isDownloadAllowed()) { + return chain.proceed(chain.request()); + } else { + return null; + } + } + + } + private static class BasicAuthenticationInterceptor implements Interceptor { @Override -- cgit v1.2.3 From 6c82db167588579c78c9bc273cd4b78ae2786ca2 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 2 Aug 2015 17:51:44 +0200 Subject: Remove unused class --- .../core/glide/ApOkHttpStreamFetcher.java | 80 ---------------------- 1 file changed, 80 deletions(-) delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpStreamFetcher.java (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpStreamFetcher.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpStreamFetcher.java deleted file mode 100644 index 13a148d1e..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpStreamFetcher.java +++ /dev/null @@ -1,80 +0,0 @@ -package de.danoeh.antennapod.core.glide; - -import com.bumptech.glide.Priority; -import com.bumptech.glide.load.data.DataFetcher; -import com.bumptech.glide.load.model.GlideUrl; -import com.bumptech.glide.util.ContentLengthInputStream; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; -import com.squareup.okhttp.ResponseBody; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Map; - -/** - * @see com.bumptech.glide.integration.okhttp.OkHttpStreamFetcher - */ -public class ApOkHttpStreamFetcher implements DataFetcher { - private final OkHttpClient client; - private final GlideUrl url; - private InputStream stream; - private ResponseBody responseBody; - - public ApOkHttpStreamFetcher(OkHttpClient client, GlideUrl url) { - this.client = client; - this.url = url; - } - - @Override - public InputStream loadData(Priority priority) throws Exception { - Request.Builder requestBuilder = new Request.Builder() - .url(url.toStringUrl()); - - for (Map.Entry headerEntry : url.getHeaders().entrySet()) { - String key = headerEntry.getKey(); - requestBuilder.addHeader(key, headerEntry.getValue()); - } - - Request request = requestBuilder.build(); - - Response response = client.newCall(request).execute(); - responseBody = response.body(); - if (!response.isSuccessful()) { - throw new IOException("Request failed with code: " + response.code()); - } - - long contentLength = responseBody.contentLength(); - stream = ContentLengthInputStream.obtain(responseBody.byteStream(), contentLength); - return stream; - } - - @Override - public void cleanup() { - if (stream != null) { - try { - stream.close(); - } catch (IOException e) { - // Ignored - } - } - if (responseBody != null) { - try { - responseBody.close(); - } catch (IOException e) { - // Ignored. - } - } - } - - @Override - public String getId() { - return url.getCacheKey(); - } - - @Override - public void cancel() { - // TODO: call cancel on the client when this method is called on a background thread. See #257 - } -} \ No newline at end of file -- cgit v1.2.3 From dfc97dcd62f30ebbb56dc87afc55bfc21c13148e Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 2 Aug 2015 14:14:44 -0400 Subject: merged 1.2.2 changes to develop --- .../main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java index 74dce17f4..bc34523cc 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java @@ -170,7 +170,7 @@ public class DownloadRequester { if (feedFileValid(feed)) { String username = (feed.getPreferences() != null) ? feed.getPreferences().getUsername() : null; String password = (feed.getPreferences() != null) ? feed.getPreferences().getPassword() : null; - long ifModifiedSince = feed.getLastUpdate().getTime(); + long ifModifiedSince = feed.isPaged() ? 0 : feed.getLastUpdate().getTime(); Bundle args = new Bundle(); args.putInt(REQUEST_ARG_PAGE_NR, feed.getPageNr()); -- cgit v1.2.3 From 744f3d6442d04428f9b74206c8aaae972d99727a Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 2 Aug 2015 14:45:22 -0400 Subject: fixed typo --- core/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 23c58d16f..7ec9bd508 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -444,7 +444,7 @@ Pause for Interruptions Resume playback after a phone call completes Resume after Call - AnntennaPod has to be restarted for this change to take effect. + AntennaPod has to be restarted for this change to take effect. Subscribe -- cgit v1.2.3 From 6c4afc4711e1c4e7eac9528fa9582b0106456656 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 2 Aug 2015 16:39:04 -0400 Subject: we can have both strings and plurals with the same name. fixes AntennaPod/AntennaPod#1050 --- core/src/main/res/values/strings.xml | 3 +++ 1 file changed, 3 insertions(+) (limited to 'core/src') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 23c58d16f..c36cde6f7 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -384,6 +384,9 @@ Sleep timer Time left:\u0020 Invalid input, time has to be an integer + seconds + minutes + hours 1 second %d seconds -- cgit v1.2.3 From dbaae4aa69b20ab6a650be73aeb944157ad8b43f Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 2 Aug 2015 18:19:38 -0400 Subject: Fixes pictures disappearing in some cases * Default value for the image cache size should be > 0 * If the image cache size is too small we force it back to default * We should only have once instance of the HTTP client fixes AntennaPod/AntennaPod/#1053 --- .../danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java | 3 ++- .../antennapod/core/preferences/UserPreferences.java | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'core/src') 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 433ba8db4..c7ac146b5 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 @@ -19,6 +19,7 @@ import java.io.InputStream; import java.net.HttpURLConnection; import de.danoeh.antennapod.core.ClientConfig; +import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.service.download.HttpDownloader; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.util.NetworkUtils; @@ -42,7 +43,7 @@ public class ApOkHttpUrlLoader implements ModelLoader { if (internalClient == null) { synchronized (Factory.class) { if (internalClient == null) { - internalClient = new OkHttpClient(); + internalClient = AntennapodHttpClient.getHttpClient(); internalClient.interceptors().add(new NetworkAllowanceInterceptor()); internalClient.interceptors().add(new BasicAuthenticationInterceptor()); } 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 789a2366e..0eae8b837 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 @@ -85,6 +85,8 @@ public class UserPreferences { private static final String PREF_FAST_FORWARD_SECS = "prefFastForwardSecs"; private static final String PREF_REWIND_SECS = "prefRewindSecs"; public static final String PREF_QUEUE_LOCKED = "prefQueueLocked"; + public static final String IMAGE_CACHE_DEFAULT_VALUE = "100"; + public static final int IMAGE_CACHE_SIZE_MINIMUM = 20; // Constants private static int EPISODE_CACHE_SIZE_UNLIMITED = -1; @@ -279,9 +281,16 @@ public class UserPreferences { } public static int getImageCacheSize() { - String cacheSizeString = prefs.getString(PREF_IMAGE_CACHE_SIZE, "100"); - int cacheSize = Integer.valueOf(cacheSizeString) * 1024 * 1024; - return cacheSize; + String cacheSizeString = prefs.getString(PREF_IMAGE_CACHE_SIZE, IMAGE_CACHE_DEFAULT_VALUE); + int cacheSizeInt = Integer.valueOf(cacheSizeString); + // if the cache size is too small the user won't get any images at all + // that's bad, force it back to the default. + if (cacheSizeInt < IMAGE_CACHE_SIZE_MINIMUM) { + prefs.edit().putString(PREF_IMAGE_CACHE_SIZE, IMAGE_CACHE_DEFAULT_VALUE).commit(); + cacheSizeInt = Integer.valueOf(IMAGE_CACHE_DEFAULT_VALUE); + } + int cacheSizeMB = cacheSizeInt * 1024 * 1024; + return cacheSizeMB; } public static int getFastFowardSecs() { -- cgit v1.2.3 From f799ad5ed58391ff841b1c19366c6558e99411b4 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 2 Aug 2015 18:27:36 -0400 Subject: Changed string names relating to time units. Android can handle plurals and strings having the same names, but Transifex can't. Renamed the time_unit*'s to just time_ to make sure we got the correct translations. --- .../main/java/de/danoeh/antennapod/core/util/Converter.java | 4 ++-- core/src/main/res/values/strings.xml | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java b/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java index 2bf88b3f3..1b929b214 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java @@ -111,10 +111,10 @@ public final class Converter { String result = ""; if(h > 0) { - String hours = context.getResources().getQuantityString(R.plurals.time_unit_hours, h, h); + String hours = context.getResources().getQuantityString(R.plurals.time_hours_quantified, h, h); result += hours + " "; } - String minutes = context.getResources().getQuantityString(R.plurals.time_unit_minutes, m, m); + String minutes = context.getResources().getQuantityString(R.plurals.time_minutes_quantified, m, m); result += minutes; return result; } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 8db8f8d78..b0ebef3da 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -384,18 +384,18 @@ Sleep timer Time left:\u0020 Invalid input, time has to be an integer - seconds - minutes - hours - + seconds + minutes + hours + 1 second %d seconds - + 1 minute %d minutes - + 1 hour %d hours -- cgit v1.2.3 From 3174c338bdc38ddfbdfaf9b7c23ed16e85a7d3de Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 2 Aug 2015 21:09:52 -0400 Subject: Should call apply instead of commit since it is asynchronous. --- .../java/de/danoeh/antennapod/core/preferences/UserPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src') 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 0eae8b837..d56829c70 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 @@ -286,7 +286,7 @@ public class UserPreferences { // if the cache size is too small the user won't get any images at all // that's bad, force it back to the default. if (cacheSizeInt < IMAGE_CACHE_SIZE_MINIMUM) { - prefs.edit().putString(PREF_IMAGE_CACHE_SIZE, IMAGE_CACHE_DEFAULT_VALUE).commit(); + prefs.edit().putString(PREF_IMAGE_CACHE_SIZE, IMAGE_CACHE_DEFAULT_VALUE).apply(); cacheSizeInt = Integer.valueOf(IMAGE_CACHE_DEFAULT_VALUE); } int cacheSizeMB = cacheSizeInt * 1024 * 1024; -- cgit v1.2.3 From 008347313f0481e2096b70e2d494055d9e9ebb66 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 4 Aug 2015 21:09:55 -0400 Subject: 'feeditem' is the id of the FeedItem SQL statement previously used 'id' which was actually the id of the FeedMedia item and not the FeedItem --- core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src') 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 f9ac39349..904a416df 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 @@ -1711,7 +1711,7 @@ public class PodDBAdapter { } if(oldVersion < 1030002) { db.execSQL("UPDATE FeedItems SET auto_download=0 WHERE " + - "(read=1 OR id IN (SELECT id FROM FeedMedia WHERE position>0 OR downloaded=1)) " + + "(read=1 OR id IN (SELECT feeditem FROM FeedMedia WHERE position>0 OR downloaded=1)) " + "AND id NOT IN (SELECT feeditem FROM Queue)"); } EventBus.getDefault().post(ProgressEvent.end()); -- cgit v1.2.3 From fe6796f102bb8c126cfad80d957bffe0cb04fa34 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 4 Aug 2015 21:25:25 -0400 Subject: Updated version code for RC5 Also updated the oldVersion used by the UPDATE FeedItems sql statement. We don't want to run the 1030002 version ever, and the 1030005 version should fix any users that used the 1030002 version (with the possibility that some items that shouldn't have had auto_download set to 0 did have it set to 0, but accepting that that's not a terrible problem). --- core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src') 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 904a416df..edb7598ab 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 @@ -1709,7 +1709,7 @@ public class PodDBAdapter { db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0"); } - if(oldVersion < 1030002) { + if(oldVersion < 1030005) { db.execSQL("UPDATE FeedItems SET auto_download=0 WHERE " + "(read=1 OR id IN (SELECT feeditem FROM FeedMedia WHERE position>0 OR downloaded=1)) " + "AND id NOT IN (SELECT feeditem FROM Queue)"); -- cgit v1.2.3 From 224832300f4a8d0b42e257a23f0ae69957518a01 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 4 Aug 2015 22:09:53 -0400 Subject: only autodownload new items --- .../antennapod/core/service/download/DownloadService.java | 7 ++++++- .../danoeh/antennapod/core/storage/APDownloadAlgorithm.java | 12 ++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 19a710d24..4fdaf6843 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -325,6 +325,11 @@ public class DownloadService extends Service { cancelNotificationUpdater(); unregisterReceiver(cancelDownloadReceiver); + // TODO: I'm not sure this is actually needed. + // We could just invoke the autodownloadUndownloadeditems method + // and it would get everything it's supposed to. By sending it the + // items in newMediaFiles we're overriding the download algorithm, + // which is not something we should probably do. if (!newMediaFiles.isEmpty()) { Log.d(TAG, "newMediaFiles exist, autodownload them"); DBTasks.autodownloadUndownloadedItems(getApplicationContext(), @@ -783,7 +788,7 @@ public class DownloadService extends Service { if(item.getPubDate() == null) { Log.d(TAG, item.toString()); } - if (!item.isPlayed() && item.hasMedia() && !item.getMedia().isDownloaded()) { + if (item.isNew() && item.hasMedia() && !item.getMedia().isDownloaded()) { newMediaFiles.add(item.getMedia().getId()); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java index 0e6b23696..c2e971dce 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java @@ -22,7 +22,7 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm { private final APCleanupAlgorithm cleanupAlgorithm = new APCleanupAlgorithm(); /** - * Looks for undownloaded episodes in the queue or list of unread items and request a download if + * Looks for undownloaded episodes in the queue or list of new items and request a download if * 1. Network is available * 2. The device is charging or the user allows auto download on battery * 3. There is free space in the episode cache @@ -57,12 +57,12 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm { candidates = DBReader.getFeedItems(context, mediaIds); } else { final List queue = DBReader.getQueue(context); - final List unreadItems = DBReader.getUnreadItemsList(context); - candidates = new ArrayList(queue.size() + unreadItems.size()); + final List newItems = DBReader.getNewItemsList(context); + candidates = new ArrayList(queue.size() + newItems.size()); candidates.addAll(queue); - for(FeedItem unreadItem : unreadItems) { - if(candidates.contains(unreadItem) == false) { - candidates.add(unreadItem); + for(FeedItem newItem : newItems) { + if(candidates.contains(newItem) == false) { + candidates.add(newItem); } } } -- cgit v1.2.3 From c019f2cd3bf6791e6c9b1783816e369cb88e4363 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 4 Aug 2015 22:41:03 -0400 Subject: removed extra quote --- core/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index b0ebef3da..00bc077e8 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -271,7 +271,7 @@ Network Update Interval or Time of Day Specify an interval or a specific time of day to refresh the feeds automatically - You can set an interval like \"every 2 hours\", set a specific time of day like \"7:00 AM\" or disable automatic updates altogether.\n\nPlease note: Update times are inexact. You may encounter a short delay." + You can set an interval like \"every 2 hours\", set a specific time of day like \"7:00 AM\" or disable automatic updates altogether.\n\nPlease note: Update times are inexact. You may encounter a short delay. Disable Set Interval Set Time of Day -- cgit v1.2.3 From dbaa5a87e5445ced73fd001400451a21a4ca6c0b Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 8 Aug 2015 08:42:31 -0400 Subject: updated strings from transifex --- core/src/main/res/values-az/strings.xml | 4 +- core/src/main/res/values-ca/strings.xml | 9 +- core/src/main/res/values-cs-rCZ/strings.xml | 88 ++++++++++++- core/src/main/res/values-de/strings.xml | 68 +++++++++- core/src/main/res/values-es/strings.xml | 84 +++++++++++- core/src/main/res/values-fr/strings.xml | 9 +- core/src/main/res/values-it-rIT/strings.xml | 9 +- core/src/main/res/values-ja/strings.xml | 81 +++++++++++- core/src/main/res/values-ko/strings.xml | 9 +- core/src/main/res/values-nl/strings.xml | 4 +- core/src/main/res/values-no/strings.xml | 1 + core/src/main/res/values-pt-rBR/strings.xml | 4 +- core/src/main/res/values-pt/strings.xml | 172 +++++++++++++++++-------- core/src/main/res/values-ro-rRO/strings.xml | 4 +- core/src/main/res/values-ru/strings.xml | 9 +- core/src/main/res/values-sv-rSE/strings.xml | 190 +++++++++++++++++++--------- core/src/main/res/values-uk-rUA/strings.xml | 9 +- 17 files changed, 560 insertions(+), 194 deletions(-) (limited to 'core/src') diff --git a/core/src/main/res/values-az/strings.xml b/core/src/main/res/values-az/strings.xml index b52ecf4a4..3610f837e 100644 --- a/core/src/main/res/values-az/strings.xml +++ b/core/src/main/res/values-az/strings.xml @@ -46,7 +46,6 @@ Hamısını oxunmuş kimi işarələ Məlumatı göstər Web-səhifəyi paylaş - Kanalı paylaş Bütün kanallar və epizodlar silinəçək. Yüklə @@ -134,8 +133,6 @@ Oynatma başa çatanda növbədə irəlidəki epizodu oynat Oynatma Şəbəkə - Təzələmə intervalı - Kanalın avtomatik təzələməsinin intervalını seç ya da keçir onu Təkçə Wi-Fi vasitəsiilə yüklə Fasiləsiz oynatma Wi-Fi vasitəsiilə yükləmə @@ -210,5 +207,6 @@ Yükləmə... + diff --git a/core/src/main/res/values-ca/strings.xml b/core/src/main/res/values-ca/strings.xml index be7a73e6d..c4887e512 100644 --- a/core/src/main/res/values-ca/strings.xml +++ b/core/src/main/res/values-ca/strings.xml @@ -71,7 +71,6 @@ Mostra informació Esborra podcast Comparteix l\'enllaç de la plana - Comparteix l\'enllaç del canal Confirmeu que, efectivament, voleu suprimir aquest canal i tots els episodis que us n\'heu baixat. S\'està esborrant el canal S\'ha actualitzat el canal @@ -197,8 +196,6 @@ Esborrat automàtic Reproducció Xarxa - Interval d\'actualització - Especifiqueu l\'interval en què els canals s\'actualitzen de forma automàtica, o deshabiliteu la funcionalitat. Només baixa fitxers a través d\'una xarxa sense fils Reproducció continuada Baixa a través de xarxes sense fils @@ -240,8 +237,6 @@ Canvia les dades d\'inici de sessió del vostre compte de gpodder.net Velocitats de reproducció Personalitzeu les velocitats disponibles per a una velocitat de reproducció d\'àudio variable - Salta a l\'instant - Salta aquesta quantitat de segons en rebobinar o en avançar ràpidament Definex nom del servidor Utilitza el servidor per defecte Amplia la notificació @@ -283,9 +278,6 @@ Temporitzador Temps restant:\u0020 L\'entrada no és vàlida, ja que el temps ha de ser un nombre i no ho és - segons - minuts - hores CATEGORIES TOP PODCASTS @@ -354,6 +346,7 @@ Autenticació Canvieu el nom d\'usuari i contrasenya per a aquest podcast i els seus episodis. + S\'estan important les subscripcions des de les apps de propòsit únic... diff --git a/core/src/main/res/values-cs-rCZ/strings.xml b/core/src/main/res/values-cs-rCZ/strings.xml index 90304a404..4a89a7d8c 100644 --- a/core/src/main/res/values-cs-rCZ/strings.xml +++ b/core/src/main/res/values-cs-rCZ/strings.xml @@ -27,6 +27,12 @@ Otevřít menu Zavřít menu Nastavení panelu + Řadit dle počtu + Řadit abecedně + Počet nových a nepřehraných epizod + Počet nových epizod + Počet nepřehraných epizod + Žádné Otevřít v prohlížeči Kopírovat URL @@ -38,6 +44,9 @@ Potvrdit Zrušit + Ano + Ne + Autor Jazyk URL @@ -60,7 +69,13 @@ Zavřít Zkusit znovu Zahrnout do automaticky stahovaných + Použít na předchozí epizody + Nová funkce auto stahování bude automaticky použita na nové epizody.\nChcete ji také použít na předchozí epizody? + Automaticky smazat epizodu\n(přeskočit globální nastavení) \u0020paralelních stahování + Globální + Vždy + Nikdy URL kanálu URL nebo webová stránka kanálu @@ -73,14 +88,20 @@ Všechny epizody označeny jako poslechnuté Prosím potvrďte, že chcete označit všechny vybrané epizody jako poslechnuté. Prosím potvrďte, že chcete označit všechny epizody z tohoto zdroje jako poslechnuté. + Označit vše jako zobrazené Informace o zdroji Odstranit podcast + Sdílet... Sdílet odkaz - Sdílet adresu kanálu + Sdílet odkaz s pozicí + Sdílet URL kanálu + Sdílet URL epizody + Sdílet URL epizody s pozicí Prosím potvrďte, že chcete smazat tento kanál včetně všech stažených epizod. Odstranit kanál Obnovit kompletní kanál Skrýt epizody + Provést akce Neposlechnuté Pozastavené Poslechnuté @@ -99,8 +120,8 @@ Odstranit Odstranit epizodu Označit jako poslechnuté - Označit jako neposlechnuté Označeno jako poslechnuté + Označit jako neposlechnuté Přidat do fronty Přidáno do fronty Odebrat z fronty @@ -229,8 +250,12 @@ Chytré označování jako poslechnuté Přehrávání Síť - Interval aktualizace zdrojů - Udává interval, ve kterém se kanály automaticky aktualizují nebo tuto funkci deaktivuje + Aktualizovat interval nebo čas v průběhu dne + Udat interval nebo přesný čas v průběhu dne pro automatickou aktualizaci kanálů + Můžete nastavit interval jako třeba \"každé 2 hodiny\", nastavit specifický čas v průběhu dne jako \"7:00\" nebo úplně vypnout automatické aktualizace.\n\nMějte na paměti: Časy aktualizací nejsou přesné. Možná zaznamenáte krátká zpoždění. + Vypnout + Nastavit interval + Nastavit čas v průběhu dne Stahovat soubory pouze pomocí WiFi Kontinuální přehrávání WiFi stahování @@ -250,8 +275,14 @@ Nastavit automatické flattrování Uživatelské rozhraní Vybrat motiv + Upravit navigační panel + Upravit vzhled navigačního panelu. Změnit navigační panel Upravit zobrazení položek v navigačním panelu. + Nastavit pořadí sbírek + Upravit pořadí vašich sbírek + Nastavit počítadlo sbírek + Upravit informaci zobrazovanou počítadlem sbírek Změnit vzhled AntennaPod. Automatické stahování Nastavení automatického stahování epizod. @@ -283,10 +314,14 @@ Vždy zobrazovat tlačítka pro přehrávání v upozornění. Pevné ovládání přehrávání Zachovat upozornění a ovládání na obrazovce uzamčení i při pozastaveném přehrávání. + Zobrazit report stahování + Pokud selže stahování, vygenerovat report zobrazující detaily o chybě. Verze Androidu nižší než 4.1 nepodporují rozšířená upozornění. Přidávat nové epizody na začátek fronty. Přidat na začátek. Vypnuto + Velikost odkládací paměti obrázků + Velikost diskové paměti pro obrázky. Povolit automatické flattrování Flattrovat díl jakmile bude odehráno %d procent @@ -312,6 +347,7 @@ Adresář importu je prázdný. Označit vše Zrušit výběr + Vybrat ... Z místního souborového systému Použít externí aplikaci OPML export @@ -326,9 +362,24 @@ Časovač vypnutí Zbývající čas:\u0020 Neplatný vstup, musí být zadáno celé číslo - sekund - minut - hodin + sekund + minut + hodin + + 1 sekunda + %d sekundy + %d sekund + + + 1 minuta + %d minuty + %d minut + + + 1 hodina + %d hodiny + %d hodin + KATEGORIE TOP PODCASTY @@ -373,6 +424,7 @@ Automatické pozastavení přehrávání Pokračovat v přehrávání po ukončení telefonního hovoru Pokračovat po telefonátu + Pro aktivování změn nastavení bylo třeba restartovat aplikaci AntennaPod. Odebírat Odebíráno @@ -399,7 +451,29 @@ Ověření Změnit uživatelské jméno a heslo pro tento podcast a jeho epizody. + + Probíhá aktualizace databáze Importuji odběry z jednoúčelových aplikací... Prohledat iTunes + Vybrat ... + Vše + Vybrány všechny epizody + Žádné + Odebrány všechny epizody + Přehrány + Vybrány přehrané epizody + Nepřehrány + Odebrány nepřehrané epizody + Stažené + Vybrány stažené epizody + Nestažené + Vybrány nestažené epizody + Řadit podle ... + Názvu (A \u2192 Z) + Názvu (Z \u2192 A) + Data (Nové \u2192 Staré) + Data (Staré \u2192 Nové) + Délka (Krátké \u2192 Dlouhé) + Délka (Dlouhé \u2192 Krátké) diff --git a/core/src/main/res/values-de/strings.xml b/core/src/main/res/values-de/strings.xml index 93e52acb6..c6e7acbcc 100644 --- a/core/src/main/res/values-de/strings.xml +++ b/core/src/main/res/values-de/strings.xml @@ -27,6 +27,12 @@ Menü öffnen Menü schließen Seitenleisten-Einstellungen + Sortieren nach Zähler + Alphabetisch sortieren + Anzahl neuer und ungespielter Episoden + Anzahl neuer Episoden + Anzahl ungespielter Episoden + Keine Im Browser öffnen URL kopieren @@ -38,6 +44,8 @@ Bestätigen Abbrechen + Ja + Nein Autor Sprache URL @@ -60,7 +68,13 @@ Schließen Erneut versuchen Automatisch herunterladen + Auf bisherige Episoden anwenden + Die neue Einstellung zum Automatischen Download wird automatisch auf neue Episoden angewandt.\nMöchtest du sie auch auf die bisherige Episoden anwenden? + Episoden automatisch löschen\n(überschreibt globale Vorgabe) \u0020gleichzeitige Downloads + Global + Immer + Nie Feed URL URL des Feeds oder der Webseite @@ -73,14 +87,20 @@ Alle Episoden als gespielt markieren Bitte bestätige, dass alle Episoden als gespielt markiert werden sollen. Bitte bestätige, dass alle Episoden in diesem Feed als gespielt markiert werden sollen. + Alle als gesehen markieren Informationen anzeigen Podcast entfernen + Teile... Webseiten-Link teilen - Feed-Link teilen + Teile Link mit Zeitmarke + Teile URL des Podcasts + Teile URL der Episode + Teile URL der Episode mit Zeitmarke Bitte bestätige, dass du diesen Feed und ALLE heruntergeladenen Episoden dieses Feeds entfernen möchtest. Entferne Feed Kompletten Feed aktualisieren Episoden verbergen + Aktionen anwenden Ungespielt Pausiert Gespielt @@ -99,8 +119,8 @@ Entfernen Episode entfernen Als gespielt markieren - Als ungespielt markieren Als gespielt markiert + Als ungespielt markieren Zur Abspielliste hinzufügen Zur Abspielliste hinzugefügt Aus der Abspielliste entfernen @@ -229,8 +249,11 @@ Schlaues als gespielt markieren Wiedergabe Netzwerk - Aktualisierungsintervall - Lege ein Intervall fest, in dem Feeds automatisch aktualisiert werden oder deaktiviere es + Aktualisierungsintervall oder -tageszeit + Lege ein Intervall oder eine Tageszeit zur automatischen Aktualisierung der Podcasts fest + Deaktivieren + Intervall einstellen + Tageszeit festlegen Lade Mediendateien nur über WiFi Durchgehendes Abspielen WiFi Medien-Download @@ -250,8 +273,14 @@ Automatisches Flattrn konfigurieren Benutzeroberfläche Theme auswählen + Seitenleiste anpassen + Passe das Aussehen der Seitenleiste an. Seitenleiste ändern Ändere, welche Listen in der Seitenleiste erscheinen + Reihenfolge der Abonnements einstellen + Ändere die Reihenfolge deiner Abonnements + Abonnement-Zähler einstellen + Ändere, welche Information der Abonnement-Zähler anzeigt Ändere das Aussehen von AntennaPod. Automatisches Herunterladen Konfiguriere das automatische Herunterladen von Episoden. @@ -283,10 +312,14 @@ Erweiterte Wiedergabebenachrichtigung mit Abspiel-, Pause- und Stop-Knöpfen anzeigen. Persistente Wiedergabesteurung Zeige Wiedergabebedienelemente in der Benachrichtigung und im Lockscreen an, während die Wiedergabe pausiert ist. + Zeige Download-Bericht + Wenn Downloads fehlschlagen, erstelle einen Bericht, der die Details des Fehlschlages beschreibt. Android-Versionen vor 4.1 unterstützen keine erweiterten Benachrichtigungen. Fügen Sie neue Folgen auf den Anfang der Warteschlange. Vorne in Abspielliste einreihen Deaktiviert + Größe des Bilder-Zwischenspeichers + Größe des Zwischenspeichers für Bilder Automatisches Flattrn aktivieren Flattr eine Episode, sobald %d Prozent gespielt worden sind @@ -312,6 +345,7 @@ Der Import-Ordner ist leer. Alle auswählen Auswahl zurücksetzen + Wähle aus ... Vom lokalen Dateisystem Verwende externe Anwendung OPML Export @@ -326,9 +360,6 @@ Schlummerfunktion Zeit übrig:\u0020 Ungültige Eingabe, Zeit muss eine Ganzzahl sein - Sekunden - Minuten - Stunden KATEGORIEN BESTE PODCASTS @@ -373,6 +404,7 @@ Bei Unterbrechungen pausieren Wiedergabe fortsetzen, wenn Anruf beendet ist Nach Anruf fortsetzen + AntennaPod muss neu gestartet werden, damit die Änderungen wirksam werden. Abonnieren Abonniert @@ -399,7 +431,29 @@ Authentifizierung Ändere den Benutzernamen und das Passwort für diesen Podcast und dessen Episoden. + + Datenbank wird aktualisiert Importiere Abonnements aus Single-Purpose Apps iTunes durchsuchen + Wähle aus ... + Alle + Alle Episoden ausgewählt + Keine + Alle Episoden abgewählt + Gespielt + Gespielte Episoden ausgewählt + Ungespielt + Ungespielte Episoden ausgewählt + Heruntergeladen + Heruntergeladene Episoden ausgewählt + Nicht heruntergeladen + Nicht heruntergeladene Episoden ausgewählt + Sortieren nach ... + Titel (A \u2192 Z) + Titel (Z \u2192 A) + Datum (neu \u2192 alt) + Datum (alt \u2192 neu) + Dauer (kurz \u2192 lang) + Dauer (lang \u2192 kurz) diff --git a/core/src/main/res/values-es/strings.xml b/core/src/main/res/values-es/strings.xml index d5255a589..6670836db 100644 --- a/core/src/main/res/values-es/strings.xml +++ b/core/src/main/res/values-es/strings.xml @@ -27,6 +27,12 @@ Abrir menú Cerrar menú Preferencias del cajón + Ordenar por cuenta + Ordenar alfabéticamente + Cantidad de episodios nuevos y no escuchados + Cantidad de episodios nuevos + Cantidad de episodios no escuchados + Ninguno Abrir en el navegador Copiar URL @@ -38,6 +44,8 @@ Confirmar Cancelar + + No Autor Idioma URL @@ -60,7 +68,13 @@ Cerrar Reintentar Incluir en descargas automáticas + Aplicar a episodios anteriores + La nueva opción Auto Descarga se aplicará automáticamente a episodios nuevos.\n¿También desea aplicarlo a episodios anteriores? + Auto borrar episodio\n(Ignorando los ajustes globales) \u0020descargas paralelas + Global + Siempre + Nunca URL del canal URL del canal o del sitio web @@ -73,14 +87,20 @@ Se marcaron todos los episodios como escuchados Por favor, confirme que desea marcar todos los episodios como escuchados. Por favor, confirme que desea marcar todos los episodios de este feed como escuchados. + Marcar todos como vistos Información del programa Eliminar podcast + Compartir... Compartir el enlace de la web - Compartir el enlace del canal + Compartir enlace con posición + Compartir URL del canal + Compartir URL del episodio + Compartir URL del episodio con posición Confirme que quiere eliminar este canal y TODOS los episodios descargados del mismo. Quitando el canal Actualizar el canal completo Ocultar episodios + Aplicar acciones No escuchados Pausados Escuchados @@ -99,8 +119,8 @@ Quitar Quitar episodio Marcar como escuchado - Marcar como no escuchado Marcado como escuchado + Marcar como no escuchado Añadir a la cola Añadido a la cola Quitar de la cola @@ -229,8 +249,12 @@ Marcar como escuchado inteligente Reproducción Red - Intervalo de actualización - Especificar el intervalo en que se actualizarán automáticamente los canales, o desactivarlo + Intervalo de actualización u hora del día + Especificar el intervalo o la hora del día en que se actualizarán automáticamente los canales + Se puede ajustar un intervalo como \"cada 2 horas\", especificar una hora del día como \"7:00 AM\" o deshabilitar las actualizaciones automáticas.\n\nNota: Las horas de actualización no son exactas. Puede haber un ligero retraso. + Deshabilitar + Ajustar intervalo + Ajustar hora del día Solo descargar los contenidos por WiFi Reproducción continua Descarga de contenidos por WiFi @@ -250,8 +274,14 @@ Configurar flattr automático Interfaz de usuario Elegir un tema + Personalizar el cajón de navegación + Personalizar la apariencia del cajón de navegación Cambiar el cajón de navegación Cambiar los ítems que aparecen en el cajón de navegación + Ajustar orden de suscripción + Cambiar el orden de las suscripciones + Ajustar contador de suscripción + Cambiar la información mostrada en el contador de suscripción Cambiar la apariencia de AntennaPod. Descarga automática Configurar la descarga automática de episodios. @@ -283,10 +313,14 @@ Expandir siempre la notificación para mostrar los botones de reproducción Controles de reproducción persistentes Mantener la notificación y controles en pantalla de bloqueo cuando se pausa. + Mostrar informe de descarga + Si la descarga falla, generar un informe con los detalles del fallo Las versiones de Android anteriores a la 4.1 no soportan notificaciones expandidas Agregar nuevos episodios al principio de la cola. Poner al principio de la cola. Deshabilitado + Tamaño de la caché de imágenes + Tamaño de la caché en disco para imágenes. Habilitar Flattr automático Hacer Flattr del episodio en cuanto se haya reproducido el %d por ciento @@ -312,6 +346,7 @@ El directorio de importación está vacío. Seleccionar todo Deseleccionar todo + Seleccionar... Desde el sistema de ficheros local Usar aplicación externa Exportar a OPML @@ -326,9 +361,21 @@ Temporizador Tiempo restante:\u0020 Entrada no válida, el tiempo debe ser un entero - segundos - minutos - horas + segundos + minutos + horas + + 1 segundo + %d segundos + + + 1 minuto + %d minutos + + + 1 hora + %d horas + CATEGORÍAS MEJORES PODCASTS @@ -373,6 +420,7 @@ Pausar durante las interrupciones Reanudar reproducción tras una llamada Reanudar tras una llamada + Es necesario reiniciar AntennaPod para aplicar los cambios. Suscribirse Suscrito @@ -399,7 +447,29 @@ Autenticación Cambiar nombre y contraseña de este podcast y sus episodios + + Actualizando la base de datos Importando subscripciones de aplicaciones de uso específico... Buscar en iTunes + Seleccionar... + Todo + Seleccionados todos los episodios + Ninguno + Deseleccionados todos los episodios + Reproducido + Seleccionados episodios reproducidos + No reproducidos + Seleccionados episodios no reproducidos + Descargado + Seleccionados episodios descargados + No descargado + Seleccionados episodios no descargados + Ordenar por... + Título (A \u2192 Z) + Título (Z \u2192 A) + Fecha (Nuevo \u2192 Antiguo) + Fecha (Antiguo \u2192 Nuevo) + Duración (Corto \u2192 Largo) + Duración (Largo \u2192 Corto) diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml index 2f59e139d..3b952e56b 100644 --- a/core/src/main/res/values-fr/strings.xml +++ b/core/src/main/res/values-fr/strings.xml @@ -74,7 +74,6 @@ Voir les détails Supprimer le podcast Partager un lien vers le site - Partager le flux Veuillez confirmer que vous voulez bien supprimer ce flux et TOUS ses épisodes que vous avez téléchargés. Flux en cours de suppression Mettre à jour tout le flux @@ -87,8 +86,8 @@ Supprimer Supprimer cet épisode Marquer comme lu - Marquer comme non lu Les épisodes ont été marqués comme lus + Marquer comme non lu Ajouter à la liste Supprimer de la liste Visiter le site @@ -202,8 +201,6 @@ Supression automatique Lecture Réseau - Intervalle de mise à jour - Indiquer un intervalle de mise à jour automatique des flux, ou le désactiver Ne télécharger les épisodes que par Wi-Fi Lecture continue Téléchargement en Wi-Fi @@ -294,9 +291,6 @@ Arrêt automatique Durée restante :\u0020 Entrée invalide, la durée doit être un nombre entier - secondes - minutes - heures CATEGORIES PODCASTS POPULAIRES @@ -365,6 +359,7 @@ Authentification Modifier votre identifiant et mot de passe pour ce podcast et tous ses épisodes + Importation des abonnements à partir d\'applications à usage unique... Chercher sur iTunes diff --git a/core/src/main/res/values-it-rIT/strings.xml b/core/src/main/res/values-it-rIT/strings.xml index 82c7395ff..c12fedbaa 100644 --- a/core/src/main/res/values-it-rIT/strings.xml +++ b/core/src/main/res/values-it-rIT/strings.xml @@ -73,7 +73,6 @@ Informazioni Rimuovi un podcast Condividi il link al sito - Condividi il link al feed Per favore conferma la cancellazione di questo feed e di TUTTI gli episodi collegati che sono stati precedentemente scaricati. Rimozione feed Ricarica il feed completo @@ -96,8 +95,8 @@ Rimuovi Rimuovi l\'episodio Segna come riprodotto - Segna come non riprodotto Segnato come riprodotto + Segna come non riprodotto Aggiungi alla coda Aggiunto alla coda Rimuovi dalla coda @@ -220,8 +219,6 @@ Elimina automaticamente Riproduzione Rete - Intervallo di update - Specifica un intervallo per l\'aggiornamento automatico dei feed o disabilitalo Abilita il download dei media solo tramite WiFi Playback continuo Download dei media su WiFi @@ -308,9 +305,6 @@ Timer di spegnimento Tempo residuo:\u0020 Input non valido, il campo deve essere un numero intero. - secondi - minuti - ore CATEGORIE TOP PODCAST @@ -380,6 +374,7 @@ Autenticazione Cambia il tuo nome utente e la tua password per questo podcast e i suoi episodi. + Importazione di sottoscrizioni da applicazioni monouso in corso... Cerca su iTunes diff --git a/core/src/main/res/values-ja/strings.xml b/core/src/main/res/values-ja/strings.xml index 79411ffc1..3a9e58d9a 100644 --- a/core/src/main/res/values-ja/strings.xml +++ b/core/src/main/res/values-ja/strings.xml @@ -27,6 +27,12 @@ メニューを開く メニューを閉じる ドロワー設定 + カウンターで並び替え + アルファベット順に並び替え + 新しい未再生のエピソードの数 + 新しいエピソードの数 + 未再生のエピソードの数 + なし ブラウザーで開く URLをコピー @@ -38,6 +44,8 @@ 確認 キャンセル + はい + いいえ 作者 言語 URL @@ -60,7 +68,13 @@ 閉じる 再試行 自動ダウンロードに含む + 前のエピソードに適用 + 新しい 自動ダウンロード の設定は、新しいエピソードに自動的に適用されます。\n前のエピソードにも適用しますか? + エピソードの自動削除\n(全般のデフォルトを上書きします) \u0020パラレル ダウンロード + 全般 + 常に + しない フィードURL フィードまたはWebサイトのURL @@ -73,14 +87,20 @@ すべてのエピソードを再生済にしました 再生済としてマークするすべてのエピソードを確認してください。 再生済としてマークするこのフィードのすべてのエピソードを確認してください。 + 参照済としてマーク 情報を表示 ポッドキャストを削除 + 共有... Webサイトのリンクを共有 - フィードのリンクを共有 + 場所とリンクを共有 + フィード URLを共有 + エピソード URLを共有 + 場所とエピソード URL を共有 このフィードと、このフィードのダウンロードしたすべてのエピソードを削除することを確認してください。 フィードの削除中 フィードをすべて更新 エピソードを非表示にする + 操作を適用 未再生 一時停止しました 再生しました @@ -99,8 +119,8 @@ 削除 エピソードを削除 再生済としてマーク - 未再生としてマーク 再生済としてマークしました + 未再生としてマーク キューに追加 キューに追加しました キューから削除 @@ -229,8 +249,12 @@ 再生済としてスマートマーク 再生 ネットワーク - 更新間隔 - フィードが自動的に更新される間隔を指定するか、または無効にしてください + 間隔または時間を更新 + 自動的にフィードを更新する間隔または時間を指定してください + \"2 時間ごと\" のような 間隔 、\"7:00 AM\" のような特定の 時間 、または自動更新を完全に 無効 にセットすることができます。\n\nご注意ください: 更新時間は正確ではありません。少し遅延が発生する可能性があります。 + 無効 + 間隔をセット + 時間をセット WiFi接続時のみメディアファイルをダウンロードします 連続再生 WiFiメディアダウンロード @@ -250,8 +274,14 @@ 自動Flattrを構成 インターフェース テーマを選択 + ナビゲーションドロワーをカスタマイズ + ナビゲーションドロワーの外観をカスタマイズします。 ナビゲーションドロワーを変更 ナビゲーションドロワーに表示するアイテムを変更します。 + 購読注文をセット + 購読の注文を変更します + 購読カウンターをセット + 購読カウンターで表示される情報を変更します AntennaPodの外観を変更します。 自動ダウンロード エピソードの自動ダウンロードを構成します。 @@ -283,10 +313,14 @@ 常に再生ボタンを表示するように通知を展開します。 永続再生コントロール 再生が一時停止された時に、通知およびロック画面のコントロールを保持します。 + ダウンロード レポートを表示 + ダウンロードが失敗した場合、失敗の詳細を表示するレポートを生成します。 Androidバージョン4.1以前では、拡張通知をサポートしていません。 新しいエピソードをキューの先頭に追加します。 キューの先頭に入れる 無効 + 画像キャッシュサイズ + 画像のディスクキャッシュのサイズ。 自動Flattrを有効にする %d %再生したらエピソードをFlattr @@ -312,6 +346,7 @@ インポートディレクトリが空です。 すべてを選択 選択解除 + 選択 ... ローカル ファイルシステムから 外部アプリケーションを使用する OPMLエクスポート @@ -326,9 +361,18 @@ スリープタイマー 残り時間:\u0020 入力が正しくありません、時間は数字で入力してください - - - + + + 時間 + + %d 秒 + + + %d 分 + + + %d 時間 + カテゴリー トップ ボッドキャスト @@ -373,6 +417,7 @@ 割り込み時に一時停止 着信が完了した後に再生を再開します 着信後に再開 + この変更を有効にするには AntennaPod を再起動する必要があります。 購読 購読しました @@ -399,7 +444,29 @@ 認証 このポッドキャストとそのエピソード用のあなたのユーザー名とパスワードを変更します。 + + データベースをアップグレードしています 単一目的のアプリから購読をインポート中… iTunes を検索 + 選択 ... + すべて + すべてのエピソードを選択しました + なし + すべてのエピソードの選択を解除しました + 再生しました + 再生済のエピソードを選択しました + 未再生 + 未再生のエピソードを選択しました + ダウンロードしました + ダウンロード済のエピソードを選択しました + ダウンロードしていません + ダウンロードしていないエピソードを選択しました + 並び替え順 ... + タイトル (A \u2192 Z) + タイトル (Z \u2192 A) + 日付 (新 \u2192 旧) + 日付 (旧 \u2192 新) + 期間 (短 \u2192 長) + 期間 (長 \u2192 短) diff --git a/core/src/main/res/values-ko/strings.xml b/core/src/main/res/values-ko/strings.xml index 148010050..fcfa89e88 100644 --- a/core/src/main/res/values-ko/strings.xml +++ b/core/src/main/res/values-ko/strings.xml @@ -76,7 +76,6 @@ 정보 표시 팟캐스트 제거 홈페이지 링크 공유 - 피드 링크 공유 이 피드와 이 피드에서 다운로드한 모든 에피소드를 삭제하시려면 확인을 누르십시오. 피드 삭제하는 중 전체 피드 새로고침 @@ -99,8 +98,8 @@ 제거 에피소드 제거 재생했다고 표시 - 재생하지 않음으로 표시 재생했다고 표시함 + 재생하지 않음으로 표시 대기열에 추가 대기열에 추가함 대기열에서 제거 @@ -229,8 +228,6 @@ 똑똑하게 재생한 것으로 표시 재생 네트워크 - 업데이트 주기 - 피드를 새로 고칠 주기를 지정하거나 새로 고침을 하지 않음 Wi-Fi를 통해서만 미디어 파일 다운로드 연속 재생 Wi-Fi 미디어 다운로드 @@ -326,9 +323,6 @@ 취침 타이머 남은 시간:\u0020 입력이 잘못되었습니다. 시간으로 숫자를 입력해야 합니다. - - - 시간 분류 상위 팟캐스트 @@ -399,6 +393,7 @@ 인증 이 팟캐스트와 에피소드에 대한 사용자 이름과 비밀번호를 바꿉니다. + 단일 용도 앱에서 구독 정보를 가져옵니다... iTunes 검색 diff --git a/core/src/main/res/values-nl/strings.xml b/core/src/main/res/values-nl/strings.xml index 0f447d54a..4ef43ecaf 100644 --- a/core/src/main/res/values-nl/strings.xml +++ b/core/src/main/res/values-nl/strings.xml @@ -54,7 +54,6 @@ Alles als gelezen markeren Toon informatie Website link delen - Feed link delen Bevestig dat u deze feed en ALLE afleveringen van deze feed die u hebt gedownload wilt verwijderen. Feed verwijderen @@ -162,8 +161,6 @@ Volgende wachtrij item afspelen als de episode voltooid is Afspelen Netwerk - Update interval - Voer een tijdsinterval in waarin de feeds automatisch worden vernieuwd, of schakel het uit Download mediabestanden alleen via WiFi Continu afspelen WiFi download van media @@ -295,6 +292,7 @@ Aantal nieuwe afleveringen Aantal afleveringen dat begonnen te luisteren zijn + Abonnementen aan het importeren vanuit single-purpose apps... diff --git a/core/src/main/res/values-no/strings.xml b/core/src/main/res/values-no/strings.xml index 16639048b..645d576a4 100644 --- a/core/src/main/res/values-no/strings.xml +++ b/core/src/main/res/values-no/strings.xml @@ -26,5 +26,6 @@ + diff --git a/core/src/main/res/values-pt-rBR/strings.xml b/core/src/main/res/values-pt-rBR/strings.xml index c3523acfb..3d421fdb2 100644 --- a/core/src/main/res/values-pt-rBR/strings.xml +++ b/core/src/main/res/values-pt-rBR/strings.xml @@ -54,7 +54,6 @@ Marcar todos como lido Mostrar informação Compartilhar link do site - Compartilhar link do feed Por favor confirme que você deseja apagar este feed e TODOS os episódios que você fez download deste feed. Removendo feed @@ -148,8 +147,6 @@ Pular para próximo item da fila quando a reprodução terminar Reprodução Rede - Intervalo de atualização - Especifica o intervalo com que os feeds serão atualizados automaticamente ou desabilita esta funcionalidade Fazer download dos arquivos apenas via rede WiFi Reprodução contínua Download de mídia via WiFi @@ -271,5 +268,6 @@ Episódio está na fila Numero de novos episódios + diff --git a/core/src/main/res/values-pt/strings.xml b/core/src/main/res/values-pt/strings.xml index abbf97de6..902fe5575 100644 --- a/core/src/main/res/values-pt/strings.xml +++ b/core/src/main/res/values-pt/strings.xml @@ -12,11 +12,11 @@ Lista de espera Definições Adicionar podcast - Transferências + Descargas Em curso Terminadas Registo - Cancelar transferência + Cancelar\ndescarga Histórico de reprodução gpodder.net Dados gpodder.net @@ -27,6 +27,12 @@ Abrir menu Fechar menu Preferências do menu + Ordenar por contador + Ordenar alfabeticamente + Número de episódios novos ou por reproduzir + Número de novos episódios + Número de episódios por reproduzir + Nenhum Abrir no navegador Copiar URL @@ -38,6 +44,8 @@ Confirmar Cancelar + Sim + Não Autor Idioma URL @@ -59,8 +67,14 @@ Guardar utilizador e palavra-passe Fechar Tentar novamente - Incluir nas transferências automáticas - \u0020transferências simultâneas + Incluir nas descargas automáticas + Aplicar aos episódios anteriores + A definição Descarga automática será aplicada a todos os novos episódios.\nGostaria de também a aplicar aos episódios anteriores? + Apagar episódio automáticamente\n(altera a definição global) + \u0020descargas simultâneas + Global + Sempre + Nunca URL da fonte URL da fonte ou sítio web @@ -73,25 +87,31 @@ Marcar todos os episódios como reproduzidos Por favor confirme que deseja marcar todos os episódios como reproduzidos Por favor confirme que deseja marcar todos os episódios desta fonte como reproduzidos + Marcar tudo como visto Mostrar informações Remover podcast - Partilhar ligação do sítio web - Partilhar ligação da fonte - Confirme a eliminação desta fonte e de todos os episódios a ela pertencentes + Partilhar... + Partilhar ligação + Partilhar ligação com posição + Partilhar URL da fonte + Partilhar URL do episódio + Partilhar URL do episódio com posição + Por favor confirme que deseja apagar esta fonte e todos os episódios descarregados Remover fonte Atualizar todas as páginas da fonte Ocultar episódios + Aplicar ações Não reproduzidos Em pausa Reproduzidos Na fila Não na fila - Transferidos - Não transferidos + Descarregados + Não descarregados Filtrados {fa-exclamation-circle} Última atualização falhada - Transferir + Descarregar Reproduzir Pausa Parar @@ -99,24 +119,24 @@ Remover Remover episódio Marcar como reproduzido - Marcar como não reproduzido Marcado como reproduzido + Marcar como não reproduzido Adicionar à fila Adicionado à fila Remover da fila Aceder ao sítio web Flattr Colocar tudo na fila - Transferir tudo + Descarregar tudo Ignorar episódio - Ativar transferência automática - Desativar transferência automática + Ativar descarga automática + Desativar descarga automática Repor posição de reprodução sucesso falha - Transferência pendente - Transferência atual + Descarga pendente + Descarga atual Cartão SD não encontrado Espaço insuficiente Erro no ficheiro @@ -127,29 +147,29 @@ Erro de ligação Servidor desconhecido Erro de autenticação - Cancelar transferências - Transferência cancelada - Transferência cancelada\nTransferência automática desativada para este item - Transferências terminadas com erros - Relatório de transferências + Cancelar descargas + Descarga cancelada + Descarga cancelada\nDescarga automática desativada para este item + Descargas terminadas com erros + Relatório de descargas URL inválido Erro I/O Erro de pedido Erro de acesso à base de dados - \u0020Transferências em falta - Processamento de transferências - A transferir dados... - %1$d transferências efetuadas, %2$d falhadas + \u0020Descargas em falta + Processamento de descargas + A descarregar dados do podcast + %1$d descargas efetuadas, %2$d falhadas Título desconhecido Fonte Ficheiro multimédia Imagem - Ocorreu um erro ao transferir o ficheiro:\u0020 + Ocorreu um erro ao descarregar o ficheiro:\u0020 Requer autenticação O recurso solicitado requer um utilizador e uma palavra-passe - Confirmação de transferência - A transferência através de dados móveis está desativada nas definições.\n\nAtivar temporariamente ou apenas adicionar à fila?\n\nA sua decisão será memorizada durante 10 minutos. - A transferência através de dados móveis está desativada nas definições.\n\nAtivar temporariamente?\n\nA sua decisão será memorizada durante 10 minutos. + Confirmação de descarga + A descarga através de dados móveis está desativada nas definições.\n\nAtivar temporariamente ou apenas adicionar à fila?\n\nA sua decisão será memorizada durante 10 minutos. + A descarga através de dados móveis está desativada nas definições.\n\nAtivar temporariamente?\n\nA sua decisão será memorizada durante 10 minutos. Apenas adicionados à fila Ativar temporariamente @@ -207,9 +227,9 @@ O AntennaPod não fez o flattr A obter itens com flattr - Transferir extra + Descarregar extra Extra não instalado - Para que a velocidade de reprodução variável funcione, tem que instalar um biblioteca de terceiros.\n\nClique em Transferir extra para a transferir no Google Play.\n\nQuaisquer problemas que ocorram na utilização do extra devem ser reportados diretamente ao seu programador. + Para que a velocidade variável de reprodução funcione, tem que instalar um biblioteca de terceiros.\n\nClique em Descarregar extra para a transferir no Google Play.\n\nQuaisquer erros que ocorram na utilização do extra devem ser reportados diretamente ao seu programador. Velocidades de reprodução Não existem itens nesta lista @@ -223,19 +243,23 @@ Pausa na reprodução ao remover os auscultadores Continuar reprodução ao ligar os auscultadores Ir para a faixa seguinte ao terminar a reprodução - Eliminar episódio ao terminar a reprodução + Apagar episódio ao terminar a reprodução Eliminação automática Marcar episódios como reproduzidos mesmo que restem alguns segundos de reprodução Marcar como reproduzido (inteligente) Reprodução Rede - Intervalo entre atualizações - Indique o intervalo de tempo entre as atualizações de fontes ou desative a opção - Apenas transferir pelas redes sem fios + Intervalo de atualização ou hora do dia + Define um intervalo de atualização ou hora para atualizar automaticamente a fonte + Pode definir um intervalo, ex.: \"a cada 2 horas\", definir uma hora do dia, ex.: \"7:00 AM\" ou desativar as atualizações automáticas.\n\nTenha em conta que a hora de atualização não é precisa. Pode existir um pouco de atraso. + Desativar + Definir intervalo + Definir hora do dia + Apenas descarregar através de redes sem fios Reprodução contínua - Transferência Wi-Fi + Descarga por Wi-Fi Auscultadores removidos - Auscultadores ligados + Auscultadores inseridos Atualizações móveis Permitir atualizações através da rede de dados móveis A atualizar @@ -250,16 +274,22 @@ Configurar flattr automático Interface Tema - Alterar itens do menu + Personalizar menu de navegação + Personaliza a aparência do menu de navegação + Alterar elementos do menu Alterar os itens que aparecem no menu de navegação + Definir ordem de subscrição + Alterar a ordem das suas subscrições + Definir contador de subsrições + Mudar informação mostrada no contador de subscrições Mudar o aspeto do AntennaPod - Transferência automática - Configure a transferência automática dos episódios + Descarga automática + Configure a descarga automática dos episódios Ativar filtro Wi-Fi - Apenas permitir transferências automáticas através de redes sem fios - Transferência se não estiver a carregar - Permitir transferência automática se a bateria não estiver a ser carregada - Transferências simultâneas + Apenas permitir descargas automáticas através de redes sem fios + Descarregar se não estiver a carregar + Permitir descarga automática se a bateria não estiver a ser carregada + Descargas simultâneas Cache de episódios Claro Escuro @@ -283,10 +313,14 @@ Expandir sempre a notificação para mostrar os botões de reprodução Controlos de reprodução persistentes Manter controlos de notificação e ecrã de bloqueio ao colocar a reprodução em pausa + Mostrar relatório de erros + Se a descarga falhar, gera um relatório que mostra os detalhes do erro As versões Android anteriores à 4.1 não possuem suporte à expansão de notificações Colocar novos episódios no inicio da fila Novos episódios no inicio Desativada + Cache de imagens + O tamanho da cache de imagens Ativar flattr automático Flattr de episódios ao atingir %d porcento de reprodução @@ -312,6 +346,7 @@ O diretório de importação está vazio Marcar tudo Desmarcar tudo + Selecionar... Do sistema local de ficheiros Utilizar aplicação externa Exportação OPML @@ -326,9 +361,21 @@ Temporizador Tempo restante:\u0020 Tem que introduzir um número inteiro - segundos - minutos - horas + segundos + minutos + horas + + 1 segundo + %d segundos + + + 1 minuto + %d minutos + + + 1 hora + %d horas + Categorias Melhores @@ -367,16 +414,17 @@ A pasta já existe Não é possível criar a pasta A pasta não está vazia - A pasta escolhida não está vazia. As transferências multimédia e os ficheiros serão colocados nesta pasta. Continuar? + A pasta escolhida não está vazia. As descargas multimédia e os ficheiros serão colocados nesta pasta. Continuar? Escolha a pasta pré-definida Pausa na reprodução em vez de baixar o volume se outra aplicação quiser reproduzir sons Pausa nas interrupções Continuar reprodução ao terminar a chamada Continuar após a chamada + Tem que reiniciar o AntennaPod para aplicar as alterações Subscrever Subscrito - A transferir... + A descarregar... Mostrar capítulos Mostrar notas @@ -388,8 +436,8 @@ Navegar para cima Mais ações Episódio em reprodução - Episódio a ser transferido - Episódio transferido + Episódio a ser descarregado + Episódio descarregado Novo item Episódio está na fila Número de novos episódios @@ -399,7 +447,29 @@ Autenticação Altere o seu nome de utilizador e senha para este podcast e seus episódios + + Atualizando base de dados Importar subscrições de aplicações single-purpose... Procurar no iTunes + Selecionar... + Todos + Marcar todos os episódios + Nenhum + Desmarcar todos os episódios + Reproduzidos + Selecionar episódios reproduzidos + Não reproduzidos + Selecionar episódios não reproduzidos + Descarregados + Selecionar episódios descarregados + Não descarregados + Selecionar episódios não descarregados + Ordenar por... + Título (A \u2192 Z) + Título (Z \u2192 A) + Data (Recente \u2192 Antiga) + Data (Antiga \u2192 Recente) + Duração (Curta \u2192 Longa) + Duração (Longa \u2192 Curta) diff --git a/core/src/main/res/values-ro-rRO/strings.xml b/core/src/main/res/values-ro-rRO/strings.xml index 390f50767..ce82dec1e 100644 --- a/core/src/main/res/values-ro-rRO/strings.xml +++ b/core/src/main/res/values-ro-rRO/strings.xml @@ -50,7 +50,6 @@ Marchează toate ca citite Arată informații Împarte adresă website - Împarte adresă feed Confirmați ștergerea feedului și a TUTUROR episoadelor pe care le-ați descărcat. Descarcă @@ -140,8 +139,6 @@ Sari la următorul element din coadă cand se termină ascultarea Ascultare Rețea - Interval actualizare - Specifică un interval în care feedurile sunt actualizate automat sau oprește funcția Descarcă fișiere media doar pe WiFi Ascultare continuă Descărcare media pe WiFi @@ -237,5 +234,6 @@ Se descarcă... + diff --git a/core/src/main/res/values-ru/strings.xml b/core/src/main/res/values-ru/strings.xml index ae10b314f..b8206d906 100644 --- a/core/src/main/res/values-ru/strings.xml +++ b/core/src/main/res/values-ru/strings.xml @@ -74,7 +74,6 @@ Показать информацию Удалить подкаст Поделиться ссылкой на сайт - Ссылка на канал Подтвердите удаление канала и всех выпусков, загруженных с этого канала. Удаление канала Обновить весь канал @@ -87,8 +86,8 @@ Удалить Удалить Отметить как прочитанное - Отметить как непрочитанное Помечено как прослушанное + Отметить как непрочитанное Добавить в очередь Удалить из очереди Посетить сайт @@ -202,8 +201,6 @@ Автоматическое удаление Воспроизведение Сеть - Интервал обновлений - Укажите интервал через который каналы обновляются автоматически, или отключите его Загружать файлы только через Wi-Fi Непрерывное воспроизведение Загрузка по Wi-Fi @@ -294,9 +291,6 @@ Таймер сна Осталось времени:\u0020 Неправильный ввод, время должно быть в виде числа - с - м - ч Категории Лучшее @@ -365,6 +359,7 @@ Авторизация Изменить имя пользователя и пароль для этого подкаста и его выпусков. + Импорт подписок из одноцелевых приложений… Поиск в iTunes diff --git a/core/src/main/res/values-sv-rSE/strings.xml b/core/src/main/res/values-sv-rSE/strings.xml index c0c49ca7d..ad970e521 100644 --- a/core/src/main/res/values-sv-rSE/strings.xml +++ b/core/src/main/res/values-sv-rSE/strings.xml @@ -3,41 +3,49 @@ AntennaPod Flöden - Lägg till podcast + Lägg till Podcast PODCASTS EPISODER - Nya episoder - Alla episoder + Nya Episoder + Alla Episoder Ny Väntelista Inställningar - Lägg till podcast + Lägg till Podcast Nedladdningar Körs Färdiga Logg - Avbryt nedladdning + Avbryt\nNedladdning Uppspelningshistorik gpodder.net - gpodder.net login + Inloggning till gpodder.net Nyligen publicerade - Visa bara nya episoder + Visa bara nya Episoder Öppna meny Stäng meny Lådinställningar + Sortera efter räknare + Sortera alfabetiskt + Antal nya och ospelade episoder + Antal nya episoder + Antal ospelade episoder + Inga - Öppna i webbläsare + Öppna i Webbläsare Kopiera URL Dela URL - Kopierade URL till clipboard. - Gå hit + Kopierade URL:en till Urklipp + Gå till denna Position - Rensa historik + Rensa Historiken Bekräfta Avbryt + Ja + Nej Skapare Språk URL @@ -60,27 +68,39 @@ Stäng Försök igen Inkludera i automatiska nedladdningar + Applicera på Föregående Episoder + Den nya inställningen Automatisk Nedladdning kommer automatiskt att appliceras på nya episoder.\nVill du också applicera det på tidigare episoder? + Ta automatiskt bort episod\n(åsidosätter global standardinställning) \u0020parallella nedladdningar + Global + Alltid + Aldrig Flödets URL URL till flöde eller webbsida Lägg till podcast via URL - Hitta podcast i mapp + Hitta Podcast i Biblioteket Du kan söka efter podcasts baserat på namn, kategori eller populäritet med tjänsten gpodder.net eller på iTunes Store. Bläddra på gpodder.net Markera alla som spelade - Markera alla episoder som spelade + Markera alla Episoder som spelade Bekräfta att du verkligen vill markera alla episoder som spelade. Bekräfta att du verkligen vill markera alla episoder i detta flöde som spelade. + Markera alla som sedda Visa information - Ta bort podcast - Dela hemsidans länk - Dela flödeslänk + Ta bort Podcast + Dela... + Dela Länk + Dela Länk med Position + Dela Flödets URL + Dela Episodens URL + Dela Episodens URL med Position Bekräfta att du vill ta bort denna feed och ALLA avsnitt av denna feed som du har hämtat. - Tar bort flöde - Uppdatera hela flödet - Dölj episoder + Tar bort Flöde + Uppdatera hela Flödet + Dölj Episoder + Applicera åtgärder Ospelade Pausad Spelad @@ -97,10 +117,10 @@ Stopp Strömma Ta bort - Ta bort episod + Ta bort Episod Markera som spelad - Markera som ospelad Markera som spelad + Markera som ospelad Lägg till i kön Lägg till i Kö Ta bort från Kön @@ -109,24 +129,24 @@ Lägg till alla i kön Ladda ner alla Hoppa över episod - Aktivera automatisk nedladdning - Avaktivera automatisk nedladdning - Nollställ uppspelningsposition + Aktivera Automatisk Nedladdning + Avaktivera Automatisk Nedladdning + Nollställ Uppspelningspositionen lyckades misslyckades Avvaktar nedladdning Nedladdning pågår - Lagringsenhet hittades inte - Otillräckligt utrymme + Hittade ingen lagringsenhet + Otillräckligt Utrymme Filfel HTTP data fel Okänt fel Tolkningsfel - Flödestyp utan stöd + Flödestypen stöds inte Anslutningsfel - Okänd värd - Autentiseringsproblem + Okänd Värd + Autentiseringsfel Avbryt alla nedladdningar Nedladdning avbruten Nedladdning avbruten\nStängde av Automatisk nedladdning för denna sak @@ -134,13 +154,13 @@ Nedladdningsrapport Felaktig webbadress IO fel - Request fel - Ingen tillgång till databasen + Förfrågningsfel + Åtkomstfel till databasen \u0020Nedladdningar kvar Bearbetar nedladdningar Laddar ner podcastdata %1$d nedladdningar lyckades, %2$d misslyckades - Okänd titel + Okänd Titel Flöde Mediafil Bild @@ -148,10 +168,10 @@ Autentisering krävs Resursen du begärde kräver ett användarnamn och ett lösenord Bekräfta mobil nedladdning - Nedladdning över mobil dataanslutning är avaktiverat i inställningarna.\n\nAktivera tillfälligt eller bara lägg till i kön?\n\nDitt val gäller i 10 minuter. - Nedladdning över mobil dataanslutning är avstängt i inställningarna.\n\nAktivera tillfälligt?\n\nDitt val gäller i 10 minuter. - Lägg bara till i kön - Aktivera tillfälligt + Nedladdning över mobil dataanslutning är avaktiverat i inställningarna.\n\nDu kan välja att antingen bara lägga till episoden i kön eller att tillfälligt tillåta nedladdning.\n\nDitt val gäller i 10 minuter. + Nedladdning över mobil dataanslutning är avaktiverat i inställningarna.\n\nVill du tillfälligt tillåta nedladdning?\n\nDitt val gäller i 10 minuter. + Köa + Tillåt tillfälligt Fel! Inget media spelar @@ -166,9 +186,9 @@ Spelar podcast AntannaPod - Okänd mediaknapp: %1$d - Lås kön - Lås upp kön - Rensa kön + Lås Kön + Lås upp Kön + Rensa Kön Ångra Föremålet avlägsnades Flytta längst upp @@ -229,37 +249,47 @@ Smart markering av uppspelat innehåll Uppspelning Nätverk - Uppdateringsintervall - Ange ett intervall för att automatiskt uppdatera flödet eller avaktivera det + Uppdateringsintervall eller Tid på Dagen + Ange ett intervall eller specifik tid på dagen för att uppdatera flödena automatisk. + Du kan välja ett intervall som \"var 2 timmar\", en specifik tid på dagen som \"07:00\" eller avaktivera automatiska uppdateringar helt.\n\nNotera: Uppdateringstiderna är inte exakta. Korta fördröjningar kan uppstå. + Avaktivera + Sätt intervall + Sätt Tid på Dagen Hämta mediefiler endast över WiFi - Kontinuerlig uppspelning + Kontinuerlig Uppspelning WiFi nedladdning - Hörlurar bortkopplade - Hörlurar återanslutna - Mobila uppdateringar + Hörlurar Bortkopplade + Hörlurar Återanslutna + Mobila Uppdateringar Tillåt uppdateringar via mobil dataanslutning Uppdaterar Flattr inställningar Flattr inloggning För att Flattra saker direkt från appen, logga in på ditt Flattr-konto. - Flattra den här appen + Flattra denna App Stöd utvecklingen av AntennaPod genom att flattra den. Tack! Återkalla åtkomst Återkalla behörigheten till ditt Flattr-konto för denna app. Automatisk Flattring Konfigurerar automatisk Flattring Användargränssnitt - Välj tema - Ändra navigationslådan + Välj Tema + Anpassa Navigeringsrutan + Anpassa utseendet på navigeringsrutan. + Välj saker i Navigeringsrutan Ändra vilka saker som visas i navigationslådan. + Välj Prenumerationsordning + Ändra ordningen på dina prenumerationer + Välj Prenumerationsräknaren + Ändra informationen som visas av prenumerationsräknaren Ändra utseendet på AntennaPod. - Automatisk nedladdning + Automatisk Nedladdning Konfigurera automatisk nedladdning av episoder. Aktivera WiFi filtrering Tillåt automatisk nedladdning endast för utvalda WiFi-nätverk. Nedladdning vid batteridrift Tillåt automatisk nedladdning när batteriet inte laddas - Parallella nedladdningar + Parallella Nedladdningar Episodcache Ljust Mörkt @@ -281,12 +311,16 @@ Använd standardvärden Expandera notifieringar Expandera alltid notifieringen för att visa uppspelningskontrollerna. - Bestående uppspelningskontroller + Bestående Uppspelningskontroller Behåll notifiering och kontroller på låsskärmen när uppspelningen pausas. + Visa Nedladdningsrapport + Visa en rapport med detaljer om felet när nedladdningar misslyckas. Androidversioner före 4.1 har inte stöd för expanderade notifieringar. Lägg till episoder först i kön. - Köa först. + Köa Först Avaktiverad + Bildcachestorlek + Storleken på bildcachen på disken. Aktivera automatisk Flattring Flattra episoden så snart %d procent har spelats @@ -305,19 +339,20 @@ Använd en extern applikation som Dropbox, Google Drive eller ditt favoritval av filhanterare för att öppna en OPML fil. Flera applikationer som Google Mail, Dropbox, Google Drive och de flesta filhanterare kan öppna OPML filer med AntennaPod. Påbörja importering - Importera OPML-fil + OPML Importering FEL! Läser OPML-fil Ett fel har skett vid iläsning av opml dokumentet: Katalogen är tom. Välj alla Avmarkera alla + Välj ... Från lokalt filsystem Använd extern applikation OPML export Exporterar... Exporteringsfel - OPML export lyckades + OPML Exportering lyckades. .opml filen skrevs till:\u0020 Ställ in sömntimer @@ -326,9 +361,21 @@ Sömntimer Återstående tid:\u0020 Ogiltigt tal, tiden måste vara ett heltal - sekunder - minuter - timmar + sekunder + minuter + timmar + + 1 sekund + %d sekunder + + + 1 minut + %d minuter + + + 1 timme + %d timmar + KATEGORIER BÄSTA PODCASTS @@ -360,7 +407,7 @@ Vald mapp: Skapa mapp - Välj mapp + Välj Datakatalog Skapa ny mapp med namnet \"%1$s\"? Skapade ny mapp Kan inte skriva till den här mappen @@ -370,9 +417,10 @@ Den mapp du har valt är inte tom. Filer kommer att placeras direkt i denna mapp. Fortsätt ändå? Välj standardmapp Pausa uppspelning istället för att sänka volymen när en annan app vill spela ljud - Pausa för avbrott + Pausa för Avbrott Återuppta uppspelning när ett telefonsamtal avslutas - Återuppta efter samtal + Fortsätt efter Samtal + AntennaPod behöver startas om för att denna inställning ska gälla. Prenumerera Prenumererar @@ -399,7 +447,29 @@ Autentisering Byt ditt användarnamn och lösenord för den här podcasten och dess episoder. + + Uppgraderar databasen Importerar prenumerationer från appar gjorda för ett enda syfte... Leta i iTunes + Välj ... + Alla + Välj alla Episoder + Inga + Avmarkera alla Episoder + Spelade + Valde spelade Episoder + Ospelade + Valde ospelade Episoder + Nedladdade + Valde nedladdade Episoder + Ej nedladdade + Valde ej nedladdade Episoder + Sortera efter ... + Titel (A \u2192 Ö) + Titel (Ö \u2192 A) + Datum (Ny \u2192 Gammal) + Datum (Gammal \u2192 Ny) + Längd (Kort \u2192 Lång) + Längd (Lång \u2192 Kort) diff --git a/core/src/main/res/values-uk-rUA/strings.xml b/core/src/main/res/values-uk-rUA/strings.xml index b6cd8ca98..d156d2fa1 100644 --- a/core/src/main/res/values-uk-rUA/strings.xml +++ b/core/src/main/res/values-uk-rUA/strings.xml @@ -76,7 +76,6 @@ Інформація Видалити подкаст Поділитися URL сайту - Поділитися URL каналу Ви впенені що хочете видаліти канал та всі завантажені епізоди Удаляю канал Оновити канал цілком @@ -99,8 +98,8 @@ Видалити Видалити епізод Позначити як граний - Позначити як не граний Позначено як граний + Позначити як не граний Додати до черги Додано до черги Видалити з черги @@ -229,8 +228,6 @@ Розумне позначення граних епізодів Відтворення Мережа - Частота оновлень - Визначити інтервал часу для автооновлювання або відключити автооновлення Завантажувати тільки через Wifi Грати безперервно Завантаження через Wifi @@ -326,9 +323,6 @@ Таймер сну Залишилось:\u0020 Помилка вводу, час повинен бути цілим - секунд - хвилин - годин КАТЕГОРІЇ ТОП ПОДКАСТІВ @@ -399,6 +393,7 @@ Автентикація Змінити ваші логін та пароль для подкаста та епізодів + Імпорт подкастів з інших програм... Пошук в iTunes -- cgit v1.2.3 From d252544d2fee0e8a2c6a18b38777cf4dc7b641c6 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 8 Aug 2015 14:22:09 -0400 Subject: Cache all images (should reduce lag displaying lists of episodes) Cache strategy is now set in ApGlideSettings and referenced everywhere else from there. --- .../java/de/danoeh/antennapod/core/glide/ApGlideSettings.java | 11 +++++++++++ .../antennapod/core/service/playback/PlaybackService.java | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java new file mode 100644 index 000000000..cc8a1fe4b --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java @@ -0,0 +1,11 @@ +package de.danoeh.antennapod.core.glide; + +import com.bumptech.glide.load.engine.DiskCacheStrategy; + +/** + * Created by Tom on 8/8/15. + */ +public class ApGlideSettings { + + public static final DiskCacheStrategy AP_DISK_CACHE_STRATEGY = DiskCacheStrategy.ALL; +} 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 aa1816e1c..7e3f27856 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 @@ -46,6 +46,7 @@ import de.danoeh.antennapod.core.feed.Chapter; 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.glide.ApGlideSettings; import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeAction; import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeAction.Action; import de.danoeh.antennapod.core.preferences.GpodnetPreferences; @@ -801,7 +802,7 @@ public class PlaybackService extends Service { icon = Glide.with(PlaybackService.this) .load(info.playable.getImageUri()) .asBitmap() - .diskCacheStrategy(DiskCacheStrategy.SOURCE) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) .into(-1, -1) // this resizing would not be exact, so we have // scale the bitmap ourselves .get(); -- cgit v1.2.3 From 4832b1aeb28d29644169022bc2ec8196809a9858 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 8 Aug 2015 16:37:14 -0400 Subject: updated comment --- core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src') diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java index cc8a1fe4b..fc1acd0e1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java @@ -3,7 +3,7 @@ package de.danoeh.antennapod.core.glide; import com.bumptech.glide.load.engine.DiskCacheStrategy; /** - * Created by Tom on 8/8/15. + * The settings that AntennaPod will use for various Glide options */ public class ApGlideSettings { -- cgit v1.2.3 From 652063b060e8e8407fb1ee32c262b37f7531b3c3 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Thu, 13 Aug 2015 18:34:34 -0400 Subject: updated strings from transifex --- core/src/main/res/values-da/strings.xml | 9 +-- core/src/main/res/values-de/strings.xml | 16 +++++ core/src/main/res/values-es-rES/strings.xml | 4 +- core/src/main/res/values-fr/strings.xml | 94 +++++++++++++++++++++++++++++ core/src/main/res/values-hi-rIN/strings.xml | 4 +- core/src/main/res/values-it-rIT/strings.xml | 45 ++++++++++++++ core/src/main/res/values-iw-rIL/strings.xml | 11 +--- core/src/main/res/values-ko/strings.xml | 72 ++++++++++++++++++++++ core/src/main/res/values-pl-rPL/strings.xml | 9 +-- core/src/main/res/values-pt/strings.xml | 92 ++++++++++++++-------------- core/src/main/res/values-ru/strings.xml | 24 ++++++-- core/src/main/res/values-tr/strings.xml | 9 +-- core/src/main/res/values-uk-rUA/strings.xml | 78 ++++++++++++++++++++++++ core/src/main/res/values-zh-rCN/strings.xml | 7 +-- 14 files changed, 378 insertions(+), 96 deletions(-) (limited to 'core/src') diff --git a/core/src/main/res/values-da/strings.xml b/core/src/main/res/values-da/strings.xml index ba7fafca6..cc18185ec 100644 --- a/core/src/main/res/values-da/strings.xml +++ b/core/src/main/res/values-da/strings.xml @@ -71,7 +71,6 @@ Vis information Fjern podcast Del webside link - Del feed link Bekræft venligst at du vil fjerne dette feed og ALLE episoder du har downloadet fra dette feed. Fjerner feed Opdater hele feed\'et @@ -197,8 +196,6 @@ Slet Automatisk Afspilning Netværk - Opdaterings interval - Specificer et interval indenfor hvilket feeds opdaterer automatisk eller deaktiver det Download kun medie filer over WiFi Kontinuerlig afspilning WiFi medie download @@ -240,8 +237,6 @@ Skift din gpodder.net kontos login information. Afspilningshastigheder Tilpas tilgængelige hastigheder for variabelt afspilningshastigheds plugin - Søg tid - Søg så mange sekunder når der spoles tilbage eller frem Indstil værtsnavn Brug standard vært Udvid notifikation @@ -283,9 +278,6 @@ Søvn timer Tid tilbage:\u0020 Ugyldig indtastning, tid skal være et heltal - sekunder - minutter - timer KATEGORIER TOP PODCASTS @@ -354,6 +346,7 @@ Godkendelse Skift dit brugernavn og kodeord for denne podcast og dets episoder. + Importerer abonnementer fra single-purpose apps… diff --git a/core/src/main/res/values-de/strings.xml b/core/src/main/res/values-de/strings.xml index c6e7acbcc..47a0d7877 100644 --- a/core/src/main/res/values-de/strings.xml +++ b/core/src/main/res/values-de/strings.xml @@ -251,6 +251,7 @@ Netzwerk Aktualisierungsintervall oder -tageszeit Lege ein Intervall oder eine Tageszeit zur automatischen Aktualisierung der Podcasts fest + Du kannst ein festes Intervall wie \"alle 2 Stunden\", eine bestimmte Tageszeit wie \"7 Uhr morgens\" festlegen oder die automatische Aktualisierung komplett deaktivieren.\n\nBitte beachte: Der Zeitpunkt der Aktualisierung ist ungenau. Du wirst vielleicht eine kurze Verzögerung bemerken. Deaktivieren Intervall einstellen Tageszeit festlegen @@ -360,6 +361,21 @@ Schlummerfunktion Zeit übrig:\u0020 Ungültige Eingabe, Zeit muss eine Ganzzahl sein + Sekunden + Minuten + Stunden + + 1 Sekunde + %d Sekunden + + + 1 Minute + %d Minuten + + + 1 Stunde + %d Stunden + KATEGORIEN BESTE PODCASTS diff --git a/core/src/main/res/values-es-rES/strings.xml b/core/src/main/res/values-es-rES/strings.xml index d05c34876..2607d1794 100644 --- a/core/src/main/res/values-es-rES/strings.xml +++ b/core/src/main/res/values-es-rES/strings.xml @@ -42,7 +42,6 @@ Marcar todo como leído Información del programa Compartir el enlace de la web - Compartir el enlace del canal Confirme que quiere eliminar este canal y TODOS los episodios descargados del mismo. Descargar @@ -125,8 +124,6 @@ Saltar al siguiente elemento de la cola al acabar la reproducción Reproducción Red - Intervalo de actualización - Especificar el intervalo en que se actualizarán automáticamente los canales, o desactivarlo Solo descargar los contenidos por WiFi Reproducción continua Descarga de contenidos por WiFi @@ -193,5 +190,6 @@ + diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml index 3b952e56b..10d3fe9a4 100644 --- a/core/src/main/res/values-fr/strings.xml +++ b/core/src/main/res/values-fr/strings.xml @@ -26,6 +26,12 @@ Ouvrir le menu Fermer le menu + Trier par compteur + Trier alphabétiquement + Nombre de nouveaux épisodes non-lus + Nombre de nouveaux épisodes + Nombre d\'épisodes non-lus + Aucun Ouvrir dans le navigateur Copier l\'URL @@ -37,8 +43,11 @@ Confirmer Annuler + Oui + Non Auteur Langue + URL Préférences Image Erreur @@ -58,7 +67,11 @@ Fermer Réessayer Télécharger automatiquement à l\'avenir + Appliquer aux épisodes précédents \u0020téléchargements parallèles + Global + Toujours + Jamais URL du flux URL ou flux ou site web @@ -71,12 +84,29 @@ Tous les épisodes ont été marqués comme lus Veuillez confirmer que vous voulez bien marquer tous les épisodes comme lus Veuillez confirmer que vous voulez bien marquer tous les épisode de ce flux comme lus + Marquer tout comme vu Voir les détails Supprimer le podcast + Partager... Partager un lien vers le site + Partager lien avec position + Partager lien du flux + Partager lien de l\'épisode + Partager lien de l\'épisode avec position Veuillez confirmer que vous voulez bien supprimer ce flux et TOUS ses épisodes que vous avez téléchargés. Flux en cours de suppression Mettre à jour tout le flux + Cacher épisodes + Appliquer les actions + Non joués + En pause + Joués + Rajouté à la liste + Pas rajouté à la liste + Téléchargé + Non téléchargé + Filtré + {fa-exclamation-circle} Dernière mise à jour échouée Télécharger Lire @@ -89,12 +119,15 @@ Les épisodes ont été marqués comme lus Marquer comme non lu Ajouter à la liste + Ajouté à la liste Supprimer de la liste Visiter le site Flattr ça! Ajouter tous à la liste Tous télécharger Passer cet épisode + Activer téléchargement automatique + Désactiver téléchargement automatique terminé échoué @@ -113,6 +146,7 @@ Annuler tous les téléchargements Téléchargement annulé Téléchargements terminés + Rapport des téléchargements URL incorrecte Erreur d\'E/S Erreur de requête @@ -128,6 +162,9 @@ Une erreur s\'est produite durant le téléchargement du fichier :\u0020 Authentification requise La ressource que vous avez demandé nécessite un nom d\'utilisateur et un mot de passe + Confirmer téléchargement mobile + Rajouter à la liste + Permettre temporairement Erreur ! Pas de lecture en cours @@ -142,6 +179,8 @@ Lecture de podcast en cours AntennaPod - Touche média inconnue : %1$d + Bloquer la liste + Débloquer la liste Effacer la liste Annuler Élément retiré @@ -199,8 +238,12 @@ Après la fin d\'un épisode, passer au suivant Supprimer l\'épisode quand la lecture est finie Supression automatique + Marquer les épisodes comme lus même s\'il reste encore moins d\'un certain intervalle de temps + Marquer comme lu intelligent Lecture Réseau + Désactiver + Définir intervalle Ne télécharger les épisodes que par Wi-Fi Lecture continue Téléchargement en Wi-Fi @@ -220,6 +263,10 @@ Configurer les paiements flattr automatiques Interface utilisateur Choisir un thème + Définir ordre des abonnements + Change l\'ordre de vos abonnements + Définir compteur des abonnements + Change l\'information affichée à côté du compteur des abonnements Modifier l\'apparence d\'AntennaPod. Téléchargement automatique Configurer le téléchargement automatique des épisodes. @@ -243,15 +290,22 @@ Modifier les information de connexion pour votre compte gpodder.net Vitesses de lecture Modifier la liste des vitesses disponibles pour la lecture audio + Avance rapide + Retour en arrière Choisir un nom de domaine Utiliser le nom de domaine par défaut Etendre la notification Toujours étendre les notifications pour montrer les boutons de lecture Boutons de lecture permanents Garder les notifications et les boutons de lecture sur l\'écran de verouillage quand la lecture est en pause + Afficher rapport des téléchargements + Si les téléchargements échouent, générer un rapport des détails des échecs. Les versions d\'Android antérieures à 4.1 ne sont pas compatibles avec les notifications élargies Ajouter de nouveaux épisodes en tête de file Mettre au début de la file d\'attente + Désactivé + Taille de la cache d\'image + Taille de l’espace disque pour stocker temporairement les images. Activer le paiement flattr automatique Lancer un paiement flattr pour un épisode dès que %d de l\'épisode a été joué @@ -277,6 +331,7 @@ Le répertoire d\'importation est vide. Tout choisir Ne rien choisir + Sélectionner... Depuis le système de fichier local Utiliser une application tierce Exportation OPML @@ -291,6 +346,21 @@ Arrêt automatique Durée restante :\u0020 Entrée invalide, la durée doit être un nombre entier + secondes + minutes + heures + + 1 seconde + %d secondes + + + 1 minute + %d minutes + + + 1 heure + %d heures + CATEGORIES PODCASTS POPULAIRES @@ -333,6 +403,9 @@ Choisir le répertoire par défaut Mettre la lecture en pause au lieu de baisser le volume quand une autre application veut jouer un son Mettre en pause lors des interruptions + Reprendre la lecture après un appel téléphonique + Reprendre après appel + AntennaPod doit être redémarré afin que ce changement prenne effet S\'abonner Abonné @@ -360,7 +433,28 @@ Authentification Modifier votre identifiant et mot de passe pour ce podcast et tous ses épisodes + Mise à jour de la base de données Importation des abonnements à partir d\'applications à usage unique... Chercher sur iTunes + Sélectionner ... + Tout + Sélectionné tous les épisodes + Aucun + Désélectionné tous les épisodes + Joués + Sélectionné tous les épisodes joués + Non joués + Sélectionné tous les épisodes non joués + Téléchargés + Sélectionné tous les épisodes téléchargés + Non téléchargés + Sélectionné tous les épisodes non téléchargés + Trier par ... + Titre (A \u2192 Z) + Titre (Z \u2192 A) + Date (Nouveau \u2192 Ancien) + Date (Ancien \u2192 Nouveau) + Durée (Courte \u2192 Longue) + Durée (Longue \u2192 Courte) diff --git a/core/src/main/res/values-hi-rIN/strings.xml b/core/src/main/res/values-hi-rIN/strings.xml index f32c7c02f..13ef6d489 100644 --- a/core/src/main/res/values-hi-rIN/strings.xml +++ b/core/src/main/res/values-hi-rIN/strings.xml @@ -57,7 +57,6 @@ पॉडकास्ट हटाएँ शेयर वेबसाइट लिंक - शेयर फ़ीड लिंक इसकी पुष्टि करें कि आप इस फ़ीड और इस फ़ीड के सभी प्रकरणों को हटाना चाहते हैं जिन्हें आपने डाउनलोड किया है. फ़ीड निकाल रहा है @@ -158,8 +157,6 @@ प्लेबैक के पूरा होने पर अगली पंक्ति आइटम के लिए जाएँ प्लेबैक संजाल - अंतराल अद्यतन - फ़ीड स्वचालित रूप से ताजा कर रहे हैं जिसमें एक अंतराल निर्दिष्ट करें या उसे निष्क्रिय करें केवल वाईफ़ाई पर मीडिया फ़ाइलें डाउनलोड करें सतत प्लेबैक वाईफाई मीडिया डाउनलोड करें @@ -274,5 +271,6 @@ डाउनलोड कर रहा है ... + diff --git a/core/src/main/res/values-it-rIT/strings.xml b/core/src/main/res/values-it-rIT/strings.xml index c12fedbaa..a7ddf81d3 100644 --- a/core/src/main/res/values-it-rIT/strings.xml +++ b/core/src/main/res/values-it-rIT/strings.xml @@ -26,6 +26,11 @@ Apri il menù Chiudi il menù + Ordina alfabeticamente + Numero di episodi nuovi e non riprodotti + Numero di episodi nuovi + Numero di episodi non riprodotti + Nessuno Apri nel browser Copia URL @@ -37,6 +42,8 @@ Conferma Annulla + + No Autore Lingua URL @@ -59,7 +66,11 @@ Chiudi Riprova Includi nei download automatici + Applica ai Precedenti Episodi \u0020download paralleli + Globale + Sempre + Mai URL del feed www.example.com/feed @@ -70,9 +81,13 @@ Segna tutti come riprodotti Segnati tutti gli episodi come riprodotti + Segna tutti come visti Informazioni Rimuovi un podcast + Condividi... Condividi il link al sito + Condividi URL del Feed + Condividi URL dell\'Episodio Per favore conferma la cancellazione di questo feed e di TUTTI gli episodi collegati che sono stati precedentemente scaricati. Rimozione feed Ricarica il feed completo @@ -219,6 +234,7 @@ Elimina automaticamente Riproduzione Rete + Disabilita Abilita il download dei media solo tramite WiFi Playback continuo Download dei media su WiFi @@ -267,6 +283,7 @@ Espandi sempre le notifiche per mostrare i pulsanti di riproduzione. Controlli di riproduzione persistenti Mantieni le notifiche e i controlli del blocco dello schermo quando la riproduzione è in pausa. + Mostra il Rapporto del Download Le versioni di Android prima della 4.1 non supportano le notifiche estese. Disabilitato @@ -305,6 +322,21 @@ Timer di spegnimento Tempo residuo:\u0020 Input non valido, il campo deve essere un numero intero. + secondi + minuti + ore + + 1 secondo + %d secondi + + + 1 minuto + %d minuti + + + 1 ora + %d ore + CATEGORIE TOP PODCAST @@ -378,4 +410,17 @@ Importazione di sottoscrizioni da applicazioni monouso in corso... Cerca su iTunes + Seleziona ... + Tutti + Tutti gli Episodi Selezionati + Nessuno + Tutti gli Episodi Deselezionati + Riprodotto + Non riprodotto + Titolo (A \u2192 Z) + Titolo (Z \u2192 A) + Data (New \u2192 Old) + Data (Old \u2192 New) + Durata (Short \u2192 Long) + Durata (Long \u2192 Short) diff --git a/core/src/main/res/values-iw-rIL/strings.xml b/core/src/main/res/values-iw-rIL/strings.xml index 20ddd6d71..07f3602ff 100644 --- a/core/src/main/res/values-iw-rIL/strings.xml +++ b/core/src/main/res/values-iw-rIL/strings.xml @@ -78,7 +78,6 @@ הצג מידע הסר פודקאסט שתף קישור אתר - שתף קישור הזנה אשר מחיקת הזנה זו ואת כל פרקי ההזנה שהורדת. הסר הזנה רענן את כל ההזנה @@ -91,8 +90,8 @@ הסר הסר פרק סמן כנקרא - סמן כלא נקרא סומן כנקרא + סמן כלא נקרא הוסף לתור הסר מהתור בקר באתר @@ -207,8 +206,6 @@ מחיקה אוטומטית ניגון רשת - זמן בין עידכונים - ציין פרק זמן שבו ההזנות עוברות רענון באופן אוטומטי או לבטל ריענון הורד קבצי מדיה רק דרך חיבור אינטרנט אלחוטי ניגון מתמשך הורדת מדיה דרך אינטרנט אלחוטי @@ -251,8 +248,6 @@ שנה פרטי התחברות של חשבון gpodder.net. מהירויות ניגון התאמת המהיריות הזמינות לניגון במהירות משתנה - זמן דילוג - דלג מספר שניות זה בדילוג לאחור או קדימה הגדר שם שרת השתמש בשרת ברירת מידל הרחב הודעה @@ -301,9 +296,6 @@ טיימר שינה זמן נותר:\u0020 קלט לא חוקי, זמן חייב להיות מספר שלם - שניות - דקות - שעות קטגוריות פודקאסטים בכירים @@ -372,6 +364,7 @@ אימות שנה את שם המשתמש והסיסמה שלך לפודקאסט ופרקים שלו. + מייבא רישום מאפליקציות יעודיות... חפש בiTunes diff --git a/core/src/main/res/values-ko/strings.xml b/core/src/main/res/values-ko/strings.xml index fcfa89e88..7c9f76fcf 100644 --- a/core/src/main/res/values-ko/strings.xml +++ b/core/src/main/res/values-ko/strings.xml @@ -27,6 +27,12 @@ 메뉴 열기 메뉴 닫기 드로어 기본 설정 + 카운터로 정렬 + 사전 순서로 정렬 + 새로운 에피소드와 재생하지 않은 에피소드 수 + 새로운 에피소드 수 + 재생하지 않은 에피소드 수 + 없음 브라우저에서 열기 URL 복사 @@ -38,6 +44,8 @@ 확인 취소 + + 아니요 저자 언어 URL @@ -60,7 +68,13 @@ 닫기 다시 시도 자동 다운로드에 포함 + 예전 에피소드에 적용 + 새로운 <i>자동 다운로드</I> 설정은 자동으로 새로운 에피소드에 적용됩니다. 예전 에피소드에도 적용하시겠습니까? + 에피소드 자동 삭제\n(전체 설정보다 우선) \u0020동시 다운로드 + 전체 설정 + 항상 + 안 함 피드 URL 피드의 URL 또는 홈페이지 @@ -73,13 +87,20 @@ 모든 에피소드를 재생했다고 표시했습니다 모든 에피소드를 재생했다고 표시할지 확인하십시오. 이 피드에 들어 있는 모든 에피소드를 재생했다고 표시할지 확인하십시오. + 모두 봤다고 표시 정보 표시 팟캐스트 제거 + 공유... 홈페이지 링크 공유 + 위치와 같이 링크 공유 + 피드 URL 공유 + 에피소드 URL 공유 + 위치와 같이 에피소드 URL 공유 이 피드와 이 피드에서 다운로드한 모든 에피소드를 삭제하시려면 확인을 누르십시오. 피드 삭제하는 중 전체 피드 새로고침 에피소드 감추기 + 동작 적용 재생 안 함 일시 중지 재생함 @@ -228,6 +249,12 @@ 똑똑하게 재생한 것으로 표시 재생 네트워크 + 업데이트 주기 또는 하루 중 시각 + 피드를 자동으로 새로 고칠 주기 또는 하루 중 특정 시각을 지정하십시오 + \"매 2시간\"과 같이 주기를 지정할 수도 있고, \"오전 7:00\"와 같이 하루 중 시각을 지정할 수도 있고, 자동 업데이트를 모두 사용 안 할 수도 있습니다.\n\n안내: 업데이트 시간은 정확하지 않습니다. 약간 늦게 업데이트할 수 있습니다. + 사용 안 함 + 주기 지정 + 하루 중 시각 지정 Wi-Fi를 통해서만 미디어 파일 다운로드 연속 재생 Wi-Fi 미디어 다운로드 @@ -247,8 +274,14 @@ 자동 flattr 설정 사용자 인터페이스 테마 선택 + 네비게이션 드로어 사용자 설정 + 네비게이션 드로어의 모양을 사용자 설정합니다. 네비게이션 드로어 바꾸기 네비게이션 드로어에 어떤 항목을 표시할지 바꿉니다. + 구독 순서 설정 + 구독 순서를 바꿉니다 + 구독 카운터 설정 + 구독 카운터에 따라 표시되는 정보를 바꿉니다 안테나팟의 겉모양을 바꿉니다. 자동 다운로드 에피소드 자동 다운로드를 설정합니다. @@ -280,10 +313,14 @@ 항상 알림에서 재생 버튼이 표시되도록 확장 재생 조작 고정 재생이 일시 중지했을 때에도 알림과 잠금 화면의 조작 기능 유지 + 다운로드 보고서 보기 + 다운로드가 실패하면, 실패를 자세히 표시하는 보고서를 만듭니다. 안드로이드 4.1 전 버전에서는 알림 확장을 지원하지 않습니다. 새 에피소드를 대기열 앞에 추가합니다. 대기열 앞에 추가 사용 안 함 + 이미지 캐시 크기 + 이미지에 사용할 디스크 캐시 크기 자동 flattr 사용 %d 퍼센트를 재생하면 에피소드에 flattr합니다 @@ -309,6 +346,7 @@ 가져오기 디렉터리가 비어 있습니다. 모두 선택 모두 선택 해제 + 선택... 로컬 파일시스템에서 외부 앱 사용 OPML 내보내기 @@ -323,6 +361,18 @@ 취침 타이머 남은 시간:\u0020 입력이 잘못되었습니다. 시간으로 숫자를 입력해야 합니다. + + + 시간 + + %d초 + + + %d분 + + + %d시간 + 분류 상위 팟캐스트 @@ -367,6 +417,7 @@ 끼어들면 일시 중지 전화 통화가 끝난 후에 재생 다시 시작 통화 후에 다시 시작 + 이 변경 사항을 적용하려면 안테나팟을 다시 시작해야 합니다. 구독 구독함 @@ -394,7 +445,28 @@ 인증 이 팟캐스트와 에피소드에 대한 사용자 이름과 비밀번호를 바꿉니다. + 데이터베이스 업그레이드 중 단일 용도 앱에서 구독 정보를 가져옵니다... iTunes 검색 + 선택 ... + 모두 + 모든 에피소드 선택 + 없음 + 모든 에피소드 선택 해제 + 재생함 + 재생 에피소드 선택 + 재생 안 함 + 재생 안 한 에피소드 선택 + 다운로드함 + 다운로드한 에피소드 선택 + 다운로드 안 함 + 다운로드 안 한 에피소드 선택 + 정렬 ... + 제목 (A \u2192 Z) + 제목 (Z \u2192 A) + 시각 (최근 \u2192 과거) + 시각 (과거 \u2192 최근) + 길이 (짧은 \u2192 긴) + 길이 (긴 \u2192 짧은) diff --git a/core/src/main/res/values-pl-rPL/strings.xml b/core/src/main/res/values-pl-rPL/strings.xml index ba1a0bb91..a43ce7722 100644 --- a/core/src/main/res/values-pl-rPL/strings.xml +++ b/core/src/main/res/values-pl-rPL/strings.xml @@ -71,7 +71,6 @@ Pokaż informacje Usuń podcast Udostępnij stronę - Udostępnij kanał Potwierdź chęć usunięcia tego kanału wraz ze WSZYSTKIMI odcinkami, które zostały pobrane. Usuwanie kanału Odśwież cały kanał @@ -197,8 +196,6 @@ Automatyczne usuwanie Odtwarzanie Sieć - Częstość aktualizacji - Określ częstotliwość automatycznego odświeżania lub je wyłącz Pobieraj pliki tylko przez WiFi Odtwarzanie ciągłe WiFi media pobrane @@ -238,8 +235,6 @@ Zmień dane logowania konta gpodder.net. Prędkość odtwarzania Dostosuj prędkości dostępne dla odtwarzania audio o zmiennej prędkości - Seek time - Przeskocz o tyle sekund przewijając Ustaw nazwę hosta Użyj domyślnego hosta Rozwiń Powiadomienia @@ -281,9 +276,6 @@ Wyłącznik czasowy Pozostały czas:\u0020 Błąd wpisu, czas musi być liczbą całkowitą - sekundy - minuty - godziny KATEGORIE TOP PODCASTY @@ -353,6 +345,7 @@ https://gpodder.net/register/ Autoryzacja Zmień swoją nazwę użytkownika oraz hasło dla tego podcastu i jego odcinków + Importowanie subskrybcji z jednozadaniowych aplikacji diff --git a/core/src/main/res/values-pt/strings.xml b/core/src/main/res/values-pt/strings.xml index 902fe5575..f02cd629e 100644 --- a/core/src/main/res/values-pt/strings.xml +++ b/core/src/main/res/values-pt/strings.xml @@ -12,11 +12,11 @@ Lista de espera Definições Adicionar podcast - Descargas + Transferências Em curso Terminadas Registo - Cancelar\ndescarga + Cancelar\ntransferência Histórico de reprodução gpodder.net Dados gpodder.net @@ -67,11 +67,11 @@ Guardar utilizador e palavra-passe Fechar Tentar novamente - Incluir nas descargas automáticas + Incluir nas transferências automáticas Aplicar aos episódios anteriores - A definição Descarga automática será aplicada a todos os novos episódios.\nGostaria de também a aplicar aos episódios anteriores? + A definição Transferência automática será aplicada a todos os novos episódios.\nGostaria de também a aplicar aos episódios anteriores? Apagar episódio automáticamente\n(altera a definição global) - \u0020descargas simultâneas + \u0020transferências simultâneas Global Sempre Nunca @@ -96,7 +96,7 @@ Partilhar URL da fonte Partilhar URL do episódio Partilhar URL do episódio com posição - Por favor confirme que deseja apagar esta fonte e todos os episódios descarregados + Por favor confirme que deseja apagar esta fonte e todos os episódios transferidos Remover fonte Atualizar todas as páginas da fonte Ocultar episódios @@ -106,12 +106,12 @@ Reproduzidos Na fila Não na fila - Descarregados - Não descarregados + Transferidos + Não transferidos Filtrados {fa-exclamation-circle} Última atualização falhada - Descarregar + Transferir Reproduzir Pausa Parar @@ -127,16 +127,16 @@ Aceder ao sítio web Flattr Colocar tudo na fila - Descarregar tudo + Transferir tudo Ignorar episódio - Ativar descarga automática - Desativar descarga automática + Ativar transferência automática + Desativar transferência automática Repor posição de reprodução sucesso falha - Descarga pendente - Descarga atual + Transferência pendente + Transferência atual Cartão SD não encontrado Espaço insuficiente Erro no ficheiro @@ -147,29 +147,29 @@ Erro de ligação Servidor desconhecido Erro de autenticação - Cancelar descargas - Descarga cancelada - Descarga cancelada\nDescarga automática desativada para este item - Descargas terminadas com erros - Relatório de descargas + Cancelar transferências + Transferência cancelada + Transferência cancelada\nTransferência automática desativada para este item + Transferências terminadas com erros + Relatório de transferências URL inválido Erro I/O Erro de pedido Erro de acesso à base de dados - \u0020Descargas em falta - Processamento de descargas - A descarregar dados do podcast - %1$d descargas efetuadas, %2$d falhadas + \u0020Transferências em falta + Processamento de transferências + A transferir dados do podcast + %1$d transferências efetuadas, %2$d falhadas Título desconhecido Fonte Ficheiro multimédia Imagem - Ocorreu um erro ao descarregar o ficheiro:\u0020 + Ocorreu um erro ao transferir o ficheiro:\u0020 Requer autenticação O recurso solicitado requer um utilizador e uma palavra-passe - Confirmação de descarga - A descarga através de dados móveis está desativada nas definições.\n\nAtivar temporariamente ou apenas adicionar à fila?\n\nA sua decisão será memorizada durante 10 minutos. - A descarga através de dados móveis está desativada nas definições.\n\nAtivar temporariamente?\n\nA sua decisão será memorizada durante 10 minutos. + Confirmação de transferência + A transferência através de dados móveis está desativada nas definições.\n\nAtivar temporariamente ou apenas adicionar à fila?\n\nA sua decisão será memorizada durante 10 minutos. + A transferência através de dados móveis está desativada nas definições.\n\nAtivar temporariamente?\n\nA sua decisão será memorizada durante 10 minutos. Apenas adicionados à fila Ativar temporariamente @@ -227,9 +227,9 @@ O AntennaPod não fez o flattr A obter itens com flattr - Descarregar extra + Transferir extra Extra não instalado - Para que a velocidade variável de reprodução funcione, tem que instalar um biblioteca de terceiros.\n\nClique em Descarregar extra para a transferir no Google Play.\n\nQuaisquer erros que ocorram na utilização do extra devem ser reportados diretamente ao seu programador. + Para que a velocidade variável de reprodução funcione, tem que instalar um biblioteca de terceiros.\n\nClique em Transferir extra para a transferir no Google Play.\n\nQuaisquer erros que ocorram na utilização do extra devem ser reportados diretamente ao seu programador. Velocidades de reprodução Não existem itens nesta lista @@ -255,9 +255,9 @@ Desativar Definir intervalo Definir hora do dia - Apenas descarregar através de redes sem fios + Apenas transferir através de redes sem fios Reprodução contínua - Descarga por Wi-Fi + Transferir por Wi-Fi Auscultadores removidos Auscultadores inseridos Atualizações móveis @@ -283,13 +283,13 @@ Definir contador de subsrições Mudar informação mostrada no contador de subscrições Mudar o aspeto do AntennaPod - Descarga automática - Configure a descarga automática dos episódios + Transferência automática + Configure a transferência automática dos episódios Ativar filtro Wi-Fi - Apenas permitir descargas automáticas através de redes sem fios - Descarregar se não estiver a carregar - Permitir descarga automática se a bateria não estiver a ser carregada - Descargas simultâneas + Apenas permitir transferências automáticas através de redes sem fios + Transferir se não estiver a carregar + Permitir transferência automática se a bateria não estiver a ser carregada + Transferências simultâneas Cache de episódios Claro Escuro @@ -314,7 +314,7 @@ Controlos de reprodução persistentes Manter controlos de notificação e ecrã de bloqueio ao colocar a reprodução em pausa Mostrar relatório de erros - Se a descarga falhar, gera um relatório que mostra os detalhes do erro + Se a transferência falhar, gera um relatório que mostra os detalhes do erro As versões Android anteriores à 4.1 não possuem suporte à expansão de notificações Colocar novos episódios no inicio da fila Novos episódios no inicio @@ -414,7 +414,7 @@ A pasta já existe Não é possível criar a pasta A pasta não está vazia - A pasta escolhida não está vazia. As descargas multimédia e os ficheiros serão colocados nesta pasta. Continuar? + A pasta escolhida não está vazia. As transferências multimédia e os ficheiros serão colocados nesta pasta. Continuar? Escolha a pasta pré-definida Pausa na reprodução em vez de baixar o volume se outra aplicação quiser reproduzir sons Pausa nas interrupções @@ -424,7 +424,7 @@ Subscrever Subscrito - A descarregar... + A transferir... Mostrar capítulos Mostrar notas @@ -436,8 +436,8 @@ Navegar para cima Mais ações Episódio em reprodução - Episódio a ser descarregado - Episódio descarregado + Episódio a ser transferido + Episódio transferido Novo item Episódio está na fila Número de novos episódios @@ -461,10 +461,10 @@ Selecionar episódios reproduzidos Não reproduzidos Selecionar episódios não reproduzidos - Descarregados - Selecionar episódios descarregados - Não descarregados - Selecionar episódios não descarregados + Transferidos + Selecionar episódios transferidos + Não transferidos + Selecionar episódios não transferidos Ordenar por... Título (A \u2192 Z) Título (Z \u2192 A) diff --git a/core/src/main/res/values-ru/strings.xml b/core/src/main/res/values-ru/strings.xml index b8206d906..c2c27484a 100644 --- a/core/src/main/res/values-ru/strings.xml +++ b/core/src/main/res/values-ru/strings.xml @@ -17,7 +17,7 @@ Завершено Журнал Отменить загрузку - История воспроизведения + Журнал gpodder.net Войти на gpodder.net @@ -26,6 +26,12 @@ Открыть меню Закрыть меню + Сортировать по количеству + Сортировать по алфавиту + Количество новых и непрослушанных выпусков + Количество новых выпусков + Количество непрослушанных выпусков + Ничего Открыть в браузере Скопировать ссылку @@ -37,8 +43,11 @@ Подтвердить Отмена + Да + Нет Автор Язык + Адрес Настройки Обложка Ошибка @@ -58,6 +67,7 @@ Закрыть Повторить Добавить в автозагрузки + Применить к предыдущим выпускам \u0020одновременных загрузок URL канала @@ -73,7 +83,8 @@ Подтвердите, что хотите пометить все эпизоды в этом канале как прослушанные. Показать информацию Удалить подкаст - Поделиться ссылкой на сайт + Поделиться... + Поделиться ссылкой Подтвердите удаление канала и всех выпусков, загруженных с этого канала. Удаление канала Обновить весь канал @@ -84,11 +95,12 @@ Остановить Воспроизвести из сети Удалить - Удалить - Отметить как прочитанное + Удалить выпуск + Отметить как прослушанное Помечено как прослушанное - Отметить как непрочитанное + Отметить как непрослушанное Добавить в очередь + Добавлено в очередь Удалить из очереди Посетить сайт Поддержать через Flattr @@ -267,7 +279,7 @@ OPML файлы позволяют перемещать ваши подкасты из одного менеджера подкастов в другой. Укажите путь к файлу на устройстве - Откройте OPML-файл с помощью внешних приложений: Dropbox, Google Drive или любой файловый менеджер. + Откройте OPML-файл с помощью внешних приложений: Dropbox, Google Drive или любого файлового менеджера. Множество приложений умеют открывать OPML-файлы в AntennaPod, например: Google Mail, Dropbox, Google Drive и большинство файловых менеджеров. Начать импорт Импорт OPML diff --git a/core/src/main/res/values-tr/strings.xml b/core/src/main/res/values-tr/strings.xml index 9f80f8532..d202bc67c 100644 --- a/core/src/main/res/values-tr/strings.xml +++ b/core/src/main/res/values-tr/strings.xml @@ -76,7 +76,6 @@ Bilgiyi göster Cep yayını kaldır Web sayfası bağlantısı paylaş - Besleme bağlantısını paylaş Lütfen bu beslemeyi ve bu beslemeye ait indirilmiş BÜTÜN bölümleri silme isteğinizi onaylayın. Besleme kaldırılıyor Tüm beslemeyi yenile @@ -99,8 +98,8 @@ Kaldır Bölümü kaldır Oynatıldı olarak işaretle - Oynatılmadı olarak işaretle Oynatıldı olarak işaretlendi + Oynatılmadı olarak işaretle Kuyruğa Ekle Kuyruğa Eklendi Kuyruktan Kaldır @@ -227,8 +226,6 @@ Otomatik Silme Çalma - Güncelleme aralığı - Beslemeleri yenilemek için bir aralık belirtin veya devre dışı bırakın. Medya dosyalarını sadece kablosuz bağlantı üzerinden indir Devamlı çalma Kablosuz medya indirmesi @@ -322,9 +319,6 @@ Zamanlayıcı Kalan süre:\u0020 Geçersiz giriş, zaman bir tam sayı olmalıdır - saniye - dakika - saat KATEGORİLER POPÜLER CEP YAYINLARI @@ -395,6 +389,7 @@ Yetkilendirme Bu cep yayını ve içerdiği bölümler için kullanıcı adı şifreyi değiştir. + Üyelikler tek-amaçlı uygulamalardan içe aktarılıyor... iTunes\'da Arama diff --git a/core/src/main/res/values-uk-rUA/strings.xml b/core/src/main/res/values-uk-rUA/strings.xml index d156d2fa1..9715e40c3 100644 --- a/core/src/main/res/values-uk-rUA/strings.xml +++ b/core/src/main/res/values-uk-rUA/strings.xml @@ -27,6 +27,12 @@ Показати меню Сховати меню Настройки навігації + Сортувати за лічильником + Сортування за абеткою + Кількість нових та непрослуханих епізодів + Кількість нових епізодів + Кількість непрослуханих епізодів + Жодних Відкрити в браузері Копіювати URL @@ -38,6 +44,8 @@ Підтвердити Скасувати + Так + Ні Автор Мова URL @@ -60,7 +68,13 @@ Закрити Повторити знову Включити до автозавантаження + Застосувати до попередніх епізодів + Нове налаштування Автозавантаження буде автоматично застосоване до нових епізодів.\nБажаєте також застосувати його до попередніх епізодів? + Автоматичне видалення епізода\n(перевизначити глобальне налаштування за замовчуванням) \u0020паралельні завантаження + Для всіх + Завжди + Ніколи Посилання на канал URL канала або сайта @@ -73,13 +87,20 @@ Позначено всі епізоди як грані Будь ласка, підтвердіть що ви бажаєте позначити всі епізоди як грані. Будь ласка, підтвердіть що ви бажаєте позначити всі епізоди цього канала як грані. + Позначити всі як переглянуті Інформація Видалити подкаст + Поділитись... Поділитися URL сайту + Поділитись посиланням на позицію + Поділитись посиланням на канал + Поділитись посиланням на епізод + Поділитись посиланням на епізод з позицією Ви впенені що хочете видаліти канал та всі завантажені епізоди Удаляю канал Оновити канал цілком Приховати епізоди + Застосувати дії Неграні На паузі Грані @@ -228,6 +249,12 @@ Розумне позначення граних епізодів Відтворення Мережа + Частота оновлень або оновлення в зазначений час + Визначити інтервал часу або визначити час щодня для автооновлення + Можливо встановити інтервал як то \"кожні 2 години\", встановити час щодня як то \"7:00\" або відклюсити автоматичне оновлення взагалі.\n\nЗверніть увагу: Час оновлення не є точним. Можливі короткі затримки. + Вимкнути + Встановити інтервал + Встановити час щодня Завантажувати тільки через Wifi Грати безперервно Завантаження через Wifi @@ -247,8 +274,14 @@ Налаштування автоматичного заохочення авторів через сервіс flattr Вигляд Обрати тему + Налаштувати панель навігації + Налаштувати вигляд панелі навігації Змінити настройки навігації Вибрати елементи для використання у навігації + Встановити порядок підписок + Змінити порядок ваших підписок + Встановити лічильник підписок + Змінити інформацію яку відображає лічильник підписок Змінити вигляд AntennaPod Автоматичне завантаження Налаштування автоматичного завантаження епізодів @@ -280,10 +313,14 @@ Завжди розгортати повідомлення, щоб показати кнопки керування. Завжди показувати елементи керування відтворенням Показувати повідомлення та елементи керування на lockscreen в режимі паузи. + Показати звіт про завантаження + У разі помилки при завантаженні створити детальний звіт про помилку. Android до версії 4.1 не підтримує розширені повідомлення. Додавати нові епізоди до початку черги. Додавати в початок черги. Вимкнено + Розмір кеша зображень + Розмір дискового кеша для зображень. Включити автоматичне заохочення авторів через сервіс flattr Заохотити автора через Flattr щойно %d відсотків епізода було відтворено @@ -309,6 +346,7 @@ Директорія імпорту пуста Обрати все Убрати виділення + Обрати ... З локальної файлової системи За допомогою додатка OPML экспорт @@ -323,6 +361,24 @@ Таймер сну Залишилось:\u0020 Помилка вводу, час повинен бути цілим + секунд + хвилин + годин + + 1 секунда + %d секунди + %d секунд + + + 1 хвилина + %d хвилини + %d хвилин + + + 1 година + %d години + %d годин + КАТЕГОРІЇ ТОП ПОДКАСТІВ @@ -367,6 +423,7 @@ Пауза в разі переривання Відновити відтворення після закінчення дзвінка Відновити після дзвінка + Для застосування змін потрібно перезапустити AntennaPod Підписатися Підписано @@ -394,7 +451,28 @@ Автентикація Змінити ваші логін та пароль для подкаста та епізодів + Оновлення бази даних Імпорт подкастів з інших програм... Пошук в iTunes + Обрати ... + Всі + Обрано всі епізоди + Жодного + Жодного епізода обрано + Переглянуті + Обрано переглянуті епізоди + Непереглянуті + Обрано непереглянуті епізоди + Завантажені + Обрано завантажені епізоди + Незавантажені + Обрано незавантажені епізоди + Сортувати за ... + Назва (А \u2192 Я) + Назва (Я \u2192 А) + Дата (Нові \u2192 Старі) + Дата (Старі \u2192 Нові) + Тривалість (Короткі \u2192 Довгі) + Тривалість (Довгі \u2192 Короткі) diff --git a/core/src/main/res/values-zh-rCN/strings.xml b/core/src/main/res/values-zh-rCN/strings.xml index 594249a31..332c8ed4c 100644 --- a/core/src/main/res/values-zh-rCN/strings.xml +++ b/core/src/main/res/values-zh-rCN/strings.xml @@ -72,7 +72,6 @@ 查看信息 删除播客 分享网站链接 - 分享订阅链接 确认要删除这些订阅吗? 该订阅所有已经下载的曲目将一并删除. 删除订阅 刷新全部订阅 @@ -199,8 +198,6 @@ 自动删除 播放 网络 - 更新周期 - 设置订阅自动刷新周期 仅在 WIFI 情况下载媒体文件 连续播放 仅在 WIFI 情况下载 @@ -292,9 +289,6 @@ 休眠计时器 计时剩余:\u0020 无效的输入, 时间是一个整数 - - 分钟 - 小时 目录 头条播客 @@ -363,6 +357,7 @@ 验证 给本播客及曲目变更用户名及密码 + 正在从选定的应用中导入订阅... 搜索 iTunes -- cgit v1.2.3