summaryrefslogtreecommitdiff
path: root/core/src
diff options
context:
space:
mode:
authordaniel oeh <daniel.oeh@gmail.com>2015-02-01 14:12:40 +0100
committerdaniel oeh <daniel.oeh@gmail.com>2015-02-01 14:12:40 +0100
commitc9e8af52c24b405c65fc9220a6c5c573574df672 (patch)
tree2ac0c4b5a4bc5b3f2ffbccc6a6de878aed7e9840 /core/src
parent9659c18d899349d9be1573fb9520defc7d3a19cd (diff)
parent12f70ca7fcc4e651af25acca51d68ef3275ba780 (diff)
downloadAntennaPod-c9e8af52c24b405c65fc9220a6c5c573574df672.zip
Merge branch 'develop'1.0
Diffstat (limited to 'core/src')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/DBTasksCallbacks.java20
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/asynctask/DBTaskLoader.java29
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java251
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/menuhandler/MenuItemUtils.java38
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java30
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java114
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java125
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java103
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java133
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java139
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java72
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/AutomaticDownloadAlgorithm.java20
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java178
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java67
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java13
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/EpisodeCleanupAlgorithm.java36
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/PowerUtils.java32
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java89
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java2
-rw-r--r--core/src/main/res/drawable-hdpi/ic_settings_grey600_24dp.pngbin0 -> 572 bytes
-rw-r--r--core/src/main/res/drawable-hdpi/ic_settings_white_24dp.pngbin0 -> 561 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_settings_grey600_24dp.pngbin0 -> 704 bytes
-rw-r--r--core/src/main/res/drawable-xhdpi/ic_settings_white_24dp.pngbin0 -> 737 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_settings_grey600_24dp.pngbin0 -> 994 bytes
-rw-r--r--core/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.pngbin0 -> 974 bytes
-rw-r--r--core/src/main/res/layout/refresh_action_view.xml8
-rw-r--r--core/src/main/res/values-ca/strings.xml12
-rw-r--r--core/src/main/res/values-cs-rCZ/strings.xml16
-rw-r--r--core/src/main/res/values-da/strings.xml12
-rw-r--r--core/src/main/res/values-de/strings.xml14
-rw-r--r--core/src/main/res/values-es/strings.xml56
-rw-r--r--core/src/main/res/values-fr/strings.xml12
-rw-r--r--core/src/main/res/values-it-rIT/strings.xml124
-rw-r--r--core/src/main/res/values-iw-rIL/strings.xml12
-rw-r--r--core/src/main/res/values-ja/strings.xml20
-rw-r--r--core/src/main/res/values-ko/strings.xml14
-rw-r--r--core/src/main/res/values-pl-rPL/strings.xml10
-rw-r--r--core/src/main/res/values-pt/strings.xml12
-rw-r--r--core/src/main/res/values-sv-rSE/strings.xml14
-rw-r--r--core/src/main/res/values-uk-rUA/strings.xml60
-rw-r--r--core/src/main/res/values/attrs.xml1
-rw-r--r--core/src/main/res/values/colors.xml5
-rw-r--r--core/src/main/res/values/dimens.xml2
-rw-r--r--core/src/main/res/values/strings.xml12
-rw-r--r--core/src/main/res/values/styles.xml95
47 files changed, 1703 insertions, 303 deletions
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 e5e609f5f..1a2671555 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java
@@ -22,4 +22,6 @@ 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/DBTasksCallbacks.java b/core/src/main/java/de/danoeh/antennapod/core/DBTasksCallbacks.java
new file mode 100644
index 000000000..edf3e3199
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/DBTasksCallbacks.java
@@ -0,0 +1,20 @@
+package de.danoeh.antennapod.core;
+
+import de.danoeh.antennapod.core.storage.AutomaticDownloadAlgorithm;
+import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithm;
+
+/**
+ * Callbacks for the DBTasks class of the storage module.
+ */
+public interface DBTasksCallbacks {
+
+ /**
+ * Returns the client's implementation of the AutomaticDownloadAlgorithm interface.
+ */
+ public AutomaticDownloadAlgorithm getAutomaticDownloadAlgorithm();
+
+ /**
+ * Returns the client's implementation of the EpisodeCacheCleanupAlgorithm interface.
+ */
+ public EpisodeCleanupAlgorithm getEpisodeCacheCleanupAlgorithm();
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/DBTaskLoader.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/DBTaskLoader.java
new file mode 100644
index 000000000..0f402f44a
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/DBTaskLoader.java
@@ -0,0 +1,29 @@
+package de.danoeh.antennapod.core.asynctask;
+
+import android.content.Context;
+import android.support.v4.content.AsyncTaskLoader;
+
+/**
+ * Subclass of AsyncTaskLoader that is made for loading data with one of the DB*-classes.
+ * This class will provide a useful default implementation that would otherwise always be necessary when interacting
+ * with the DB*-classes with an AsyncTaskLoader.
+ */
+public abstract class DBTaskLoader<D> extends AsyncTaskLoader<D> {
+
+ public DBTaskLoader(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void onStopLoading() {
+ super.onStopLoading();
+ cancelLoad();
+ }
+
+ @Override
+ protected void onStartLoading() {
+ super.onStartLoading();
+ // according to https://code.google.com/p/android/issues/detail?id=14944, this has to be called manually
+ forceLoad();
+ }
+}
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 1ed29c23a..b6ece6dc8 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
@@ -14,6 +14,7 @@ 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;
@@ -209,4 +210,254 @@ public class PicassoProvider {
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);
+ 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 <mario at quasimondo.com>
+ // http://incubator.quasimondo.com
+ // created Feburary 29, 2004
+ // Android port : Yahel Bouaziz <yahel at kayenko.com>
+ // 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 <mario@quasimondo.com>
+
+ Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), 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/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java
index 42e4191f6..c63b61f55 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
@@ -143,7 +143,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
paymentLink = other.paymentLink;
}
if (other.chapters != null) {
- if (chapters == null) {
+ if (!hasChapters) {
chapters = other.chapters;
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/menuhandler/MenuItemUtils.java b/core/src/main/java/de/danoeh/antennapod/core/menuhandler/MenuItemUtils.java
new file mode 100644
index 000000000..b8d17bcce
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/menuhandler/MenuItemUtils.java
@@ -0,0 +1,38 @@
+package de.danoeh.antennapod.core.menuhandler;
+
+import android.support.v4.view.MenuItemCompat;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import de.danoeh.antennapod.core.R;
+
+/**
+ * Utilities for menu items
+ */
+public class MenuItemUtils {
+
+ /**
+ * Changes the appearance of a MenuItem depending on whether the given UpdateRefreshMenuItemChecker
+ * is refreshing or not. If it returns true, the menu item will be replaced by an indeterminate progress
+ * bar, otherwise nothing will happen.
+ *
+ * @param menu The menu that the MenuItem belongs to
+ * @param resId The id of the MenuItem
+ * @param checker Is used for checking whether to show the progress indicator or not.
+ * @return The returned value of the UpdateRefreshMenuItemChecker's isRefreshing() method.
+ */
+ public static boolean updateRefreshMenuItem(Menu menu, int resId, UpdateRefreshMenuItemChecker checker) {
+ // expand actionview if feeds are being downloaded, collapse otherwise
+ if (checker.isRefreshing()) {
+ MenuItem refreshItem = menu.findItem(resId);
+ MenuItemCompat.setActionView(refreshItem, R.layout.refresh_action_view);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static interface UpdateRefreshMenuItemChecker {
+ public boolean isRefreshing();
+ }
+}
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 f18028e8f..a3b9f6049 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
@@ -38,6 +38,7 @@ public class UserPreferences implements
private static final String TAG = "UserPreferences";
public static final String PREF_PAUSE_ON_HEADSET_DISCONNECT = "prefPauseOnHeadsetDisconnect";
+ public static final String PREF_UNPAUSE_ON_HEADSET_RECONNECT = "prefUnpauseOnHeadsetReconnect";
public static final String PREF_FOLLOW_QUEUE = "prefFollowQueue";
public static final String PREF_DOWNLOAD_MEDIA_ON_WIFI_ONLY = "prefDownloadMediaOnWifiOnly";
public static final String PREF_UPDATE_INTERVAL = "prefAutoUpdateIntervall";
@@ -50,6 +51,7 @@ public class UserPreferences implements
public static final String PREF_DATA_FOLDER = "prefDataFolder";
public static final String PREF_ENABLE_AUTODL = "prefEnableAutoDl";
public static final String PREF_ENABLE_AUTODL_WIFI_FILTER = "prefEnableAutoDownloadWifiFilter";
+ public static final String PREF_ENABLE_AUTODL_ON_BATTERY = "prefEnableAutoDownloadOnBattery";
private static final String PREF_AUTODL_SELECTED_NETWORKS = "prefAutodownloadSelectedNetworks";
public static final String PREF_EPISODE_CACHE_SIZE = "prefEpisodeCacheSize";
private static final String PREF_PLAYBACK_SPEED = "prefPlaybackSpeed";
@@ -69,6 +71,7 @@ public class UserPreferences implements
// Preferences
private boolean pauseOnHeadsetDisconnect;
+ private boolean unpauseOnHeadsetReconnect;
private boolean followQueue;
private boolean downloadMediaOnWifiOnly;
private long updateInterval;
@@ -80,6 +83,7 @@ public class UserPreferences implements
private int theme;
private boolean enableAutodownload;
private boolean enableAutodownloadWifiFilter;
+ private boolean enableAutodownloadOnBattery;
private String[] autodownloadSelectedNetworks;
private int episodeCacheSize;
private String playbackSpeed;
@@ -121,6 +125,8 @@ public class UserPreferences implements
R.integer.episode_cache_size_unlimited);
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);
downloadMediaOnWifiOnly = sp.getBoolean(
PREF_DOWNLOAD_MEDIA_ON_WIFI_ONLY, true);
@@ -140,6 +146,7 @@ public class UserPreferences implements
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);
playbackSpeed = sp.getString(PREF_PLAYBACK_SPEED, "1.0");
playbackSpeedArray = readPlaybackSpeedArray(sp.getString(
PREF_PLAYBACK_SPEED_ARRAY, null));
@@ -221,6 +228,11 @@ public class UserPreferences implements
return instance.pauseOnHeadsetDisconnect;
}
+ public static boolean isUnpauseOnHeadsetReconnect() {
+ instanceAvailable();
+ return instance.unpauseOnHeadsetReconnect;
+ }
+
public static boolean isFollowQueue() {
instanceAvailable();
return instance.followQueue;
@@ -282,6 +294,15 @@ public class UserPreferences implements
return instance.theme;
}
+ public static int getNoTitleTheme() {
+ int theme = getTheme();
+ if (theme == R.style.Theme_AntennaPod_Dark) {
+ return R.style.Theme_AntennaPod_Dark_NoTitle;
+ } else {
+ return R.style.Theme_AntennaPod_Light_NoTitle;
+ }
+ }
+
public static boolean isEnableAutodownloadWifiFilter() {
instanceAvailable();
return instance.enableAutodownloadWifiFilter;
@@ -326,6 +347,11 @@ public class UserPreferences implements
return instance.enableAutodownload;
}
+ public static boolean isEnableAutodownloadOnBattery() {
+ instanceAvailable();
+ return instance.enableAutodownloadOnBattery;
+ }
+
public static boolean shouldPauseForFocusLoss() {
instanceAvailable();
return instance.pauseForFocusLoss;
@@ -377,6 +403,8 @@ public class UserPreferences implements
PREF_EPISODE_CACHE_SIZE, "20"));
} else if (key.equals(PREF_ENABLE_AUTODL)) {
enableAutodownload = sp.getBoolean(PREF_ENABLE_AUTODL, false);
+ } else if (key.equals(PREF_ENABLE_AUTODL_ON_BATTERY)) {
+ enableAutodownloadOnBattery = sp.getBoolean(PREF_ENABLE_AUTODL_ON_BATTERY, true);
} else if (key.equals(PREF_PLAYBACK_SPEED)) {
playbackSpeed = sp.getString(PREF_PLAYBACK_SPEED, "1.0");
} else if (key.equals(PREF_PLAYBACK_SPEED_ARRAY)) {
@@ -388,6 +416,8 @@ public class UserPreferences implements
seekDeltaSecs = Integer.valueOf(sp.getString(PREF_SEEK_DELTA_SECS, "30"));
} else if (key.equals(PREF_PAUSE_ON_HEADSET_DISCONNECT)) {
pauseOnHeadsetDisconnect = sp.getBoolean(PREF_PAUSE_ON_HEADSET_DISCONNECT, true);
+ } else if (key.equals(PREF_UNPAUSE_ON_HEADSET_RECONNECT)) {
+ unpauseOnHeadsetReconnect = sp.getBoolean(PREF_UNPAUSE_ON_HEADSET_RECONNECT, true);
} else if (key.equals(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD)) {
autoFlattrPlayedDurationThreshold = sp.getFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD,
PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD_DEFAULT);
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 a5560e3fb..aabbcc185 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
@@ -144,6 +144,10 @@ public class PlaybackService extends Service {
* Is true if service has received a valid start command.
*/
public static boolean started = false;
+ /**
+ * Is true if the service was running, but paused due to headphone disconnect
+ */
+ public static boolean transientPause = false;
private static final int NOTIFICATION_ID = 1;
@@ -206,6 +210,8 @@ public class PlaybackService extends Service {
Intent.ACTION_HEADSET_PLUG));
registerReceiver(shutdownReceiver, new IntentFilter(
ACTION_SHUTDOWN_PLAYBACK_SERVICE));
+ registerReceiver(bluetoothStateUpdated, new IntentFilter(
+ AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED));
registerReceiver(audioBecomingNoisy, new IntentFilter(
AudioManager.ACTION_AUDIO_BECOMING_NOISY));
registerReceiver(skipCurrentEpisodeReceiver, new IntentFilter(
@@ -228,6 +234,7 @@ public class PlaybackService extends Service {
unregisterReceiver(headsetDisconnected);
unregisterReceiver(shutdownReceiver);
+ unregisterReceiver(bluetoothStateUpdated);
unregisterReceiver(audioBecomingNoisy);
unregisterReceiver(skipCurrentEpisodeReceiver);
mediaPlayer.shutdown();
@@ -284,7 +291,6 @@ public class PlaybackService extends Service {
private void handleKeycode(int keycode) {
if (BuildConfig.DEBUG)
Log.d(TAG, "Handling keycode: " + keycode);
-
final PlaybackServiceMediaPlayer.PSMPInfo info = mediaPlayer.getPSMPInfo();
final PlayerStatus status = info.playerStatus;
switch (keycode) {
@@ -315,12 +321,14 @@ public class PlaybackService extends Service {
break;
case KeyEvent.KEYCODE_MEDIA_PAUSE:
if (status == PlayerStatus.PLAYING) {
- if (UserPreferences.isPersistNotify()) {
- mediaPlayer.pause(false, true);
- } else {
- mediaPlayer.pause(true, true);
- }
+ mediaPlayer.pause(false, true);
+ }
+ if (UserPreferences.isPersistNotify()) {
+ mediaPlayer.pause(false, true);
+ } else {
+ mediaPlayer.pause(true, true);
}
+
break;
case KeyEvent.KEYCODE_MEDIA_NEXT:
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
@@ -333,7 +341,9 @@ public class PlaybackService extends Service {
case KeyEvent.KEYCODE_MEDIA_STOP:
if (status == PlayerStatus.PLAYING) {
mediaPlayer.pause(true, true);
+ started = false;
}
+
stopForeground(true); // gets rid of persistent notification
break;
default:
@@ -411,10 +421,13 @@ public class PlaybackService extends Service {
taskManager.cancelWidgetUpdater();
if (UserPreferences.isPersistNotify() && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
// do not remove notification on pause based on user pref and whether android version supports expanded notifications
- } else {
+ // Change [Play] button to [Pause]
+ setupNotification(newInfo);
+ } else if (!UserPreferences.isPersistNotify()) {
// remove notifcation on pause
stopForeground(true);
}
+
break;
case STOPPED:
@@ -431,6 +444,7 @@ public class PlaybackService extends Service {
taskManager.startPositionSaver();
taskManager.startWidgetUpdater();
setupNotification(newInfo);
+ started = true;
break;
case ERROR:
writePlaybackPreferencesNoMediaPlaying();
@@ -539,6 +553,15 @@ public class PlaybackService extends Service {
if (isAutoFlattrable(media) && UserPreferences.getAutoFlattrPlayedDurationThreshold() == 1.0f) {
DBTasks.flattrItemIfLoggedIn(PlaybackService.this, item);
}
+
+ //Delete episode if enabled
+ if(UserPreferences.isAutoDelete()) {
+ DBWriter.deleteFeedMediaOfItem(PlaybackService.this, item.getMedia().getId());
+
+ if(BuildConfig.DEBUG)
+ Log.d(TAG, "Episode Deleted");
+ }
+
}
// Load next episode if previous episode was in the queue and if there
@@ -734,8 +757,9 @@ public class PlaybackService extends Service {
PlaybackServiceMediaPlayer.PSMPInfo newInfo = mediaPlayer.getPSMPInfo();
final int smallIcon = ClientConfig.playbackServiceCallbacks.getNotificationIconResource(getApplicationContext());
- if (!isCancelled() && info.playerStatus == PlayerStatus.PLAYING
- && info.playable != null) {
+ if (!isCancelled() &&
+ started &&
+ info.playable != null) {
String contentText = info.playable.getFeedTitle();
String contentTitle = info.playable.getEpisodeTitle();
Notification notification = null;
@@ -775,16 +799,30 @@ public class PlaybackService extends Service {
.setContentIntent(pIntent)
.setLargeIcon(icon)
.setSmallIcon(smallIcon)
- .setPriority(UserPreferences.getNotifyPriority()) // set notification priority
- .addAction(android.R.drawable.ic_media_play, //play action
- getString(R.string.play_label),
- playButtonPendingIntent)
- .addAction(android.R.drawable.ic_media_pause, //pause action
- getString(R.string.pause_label),
- pauseButtonPendingIntent)
- .addAction(android.R.drawable.ic_menu_close_clear_cancel, // stop action
- getString(R.string.stop_label),
- stopButtonPendingIntent);
+ .setPriority(UserPreferences.getNotifyPriority()); // set notification priority
+ if (newInfo.playerStatus == PlayerStatus.PLAYING) {
+ notificationBuilder.addAction(android.R.drawable.ic_media_pause, //pause action
+ getString(R.string.pause_label),
+ pauseButtonPendingIntent);
+ } else {
+ notificationBuilder.addAction(android.R.drawable.ic_media_play, //play action
+ getString(R.string.play_label),
+ playButtonPendingIntent);
+ }
+ if (UserPreferences.isPersistNotify()) {
+ notificationBuilder.addAction(android.R.drawable.ic_menu_close_clear_cancel, // stop action
+ getString(R.string.stop_label),
+ stopButtonPendingIntent);
+ }
+
+ if (Build.VERSION.SDK_INT >= 21) {
+ notificationBuilder.setStyle(new Notification.MediaStyle()
+ .setMediaSession((android.media.session.MediaSession.Token) mediaPlayer.getSessionToken().getToken())
+ .setShowActionsInCompactView(0))
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setColor(Notification.COLOR_DEFAULT);
+ }
+
notification = notificationBuilder.build();
} else {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(
@@ -793,11 +831,9 @@ public class PlaybackService extends Service {
.setContentText(contentText).setOngoing(true)
.setContentIntent(pIntent).setLargeIcon(icon)
.setSmallIcon(smallIcon);
- notification = notificationBuilder.getNotification();
- }
- if (newInfo.playerStatus == PlayerStatus.PLAYING) {
- startForeground(NOTIFICATION_ID, notification);
+ notification = notificationBuilder.build();
}
+ startForeground(NOTIFICATION_ID, notification);
if (BuildConfig.DEBUG)
Log.d(TAG, "Notification set up");
}
@@ -966,6 +1002,7 @@ public class PlaybackService extends Service {
private BroadcastReceiver headsetDisconnected = new BroadcastReceiver() {
private static final String TAG = "headsetDisconnected";
private static final int UNPLUGGED = 0;
+ private static final int PLUGGED = 1;
@Override
public void onReceive(Context context, Intent intent) {
@@ -978,6 +1015,10 @@ public class PlaybackService extends Service {
if (BuildConfig.DEBUG)
Log.d(TAG, "Headset was unplugged during playback.");
pauseIfPauseOnDisconnect();
+ } else if (state == PLUGGED) {
+ if (BuildConfig.DEBUG)
+ Log.d(TAG, "Headset was plugged in during playback.");
+ unpauseIfPauseOnDisconnect();
}
} else {
Log.e(TAG, "Received invalid ACTION_HEADSET_PLUG intent");
@@ -986,6 +1027,21 @@ public class PlaybackService extends Service {
}
};
+ private BroadcastReceiver bluetoothStateUpdated = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (StringUtils.equals(intent.getAction(), AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)) {
+ int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
+ int prevState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, -1);
+ if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
+ if (BuildConfig.DEBUG)
+ Log.d(TAG, "Received bluetooth connection intent");
+ unpauseIfPauseOnDisconnect();
+ }
+ }
+ }
+ };
+
private BroadcastReceiver audioBecomingNoisy = new BroadcastReceiver() {
@Override
@@ -1003,6 +1059,9 @@ public class PlaybackService extends Service {
*/
private void pauseIfPauseOnDisconnect() {
if (UserPreferences.isPauseOnHeadsetDisconnect()) {
+ if (mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING) {
+ transientPause = true;
+ }
if (UserPreferences.isPersistNotify()) {
mediaPlayer.pause(false, true);
} else {
@@ -1011,6 +1070,15 @@ public class PlaybackService extends Service {
}
}
+ private void unpauseIfPauseOnDisconnect() {
+ if (transientPause) {
+ transientPause = false;
+ if (UserPreferences.isPauseOnHeadsetDisconnect() && UserPreferences.isUnpauseOnHeadsetReconnect()) {
+ mediaPlayer.resume();
+ }
+ }
+ }
+
private BroadcastReceiver shutdownReceiver = new BroadcastReceiver() {
@Override
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 dbf870eac..c143d7f2c 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
@@ -6,6 +6,9 @@ import android.media.AudioManager;
import android.media.RemoteControlClient;
import android.net.wifi.WifiManager;
import android.os.PowerManager;
+import android.support.v4.media.MediaMetadataCompat;
+import android.support.v4.media.session.MediaSessionCompat;
+import android.support.v4.media.session.PlaybackStateCompat;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.Pair;
@@ -48,6 +51,10 @@ public class PlaybackServiceMediaPlayer {
private volatile PlayerStatus statusBeforeSeeking;
private volatile IPlayer mediaPlayer;
private volatile Playable media;
+ /**
+ * Only used for Lollipop notifications.
+ */
+ private final MediaSessionCompat mediaSession;
private volatile boolean stream;
private volatile MediaType mediaType;
@@ -89,6 +96,10 @@ public class PlaybackServiceMediaPlayer {
}
);
+ mediaSession = new MediaSessionCompat(context, TAG);
+ mediaSession.setCallback(sessionCallback);
+ mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
+
mediaPlayer = null;
statusBeforeSeeking = null;
pausedBecauseOfTransientAudiofocusLoss = false;
@@ -181,6 +192,7 @@ public class PlaybackServiceMediaPlayer {
setPlayerStatus(PlayerStatus.INITIALIZING, media);
try {
media.loadMetadata();
+ mediaSession.setMetadata(getMediaSessionMetadata(media));
if (stream) {
mediaPlayer.setDataSource(media.getStreamUrl());
} else {
@@ -211,6 +223,13 @@ public class PlaybackServiceMediaPlayer {
}
}
+ private MediaMetadataCompat getMediaSessionMetadata(Playable p) {
+ MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
+ builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, p.getEpisodeTitle());
+ builder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, p.getFeedTitle());
+ return builder.build();
+ }
+
/**
* Resumes playback if the PSMP object is in PREPARED or PAUSED state. If the PSMP object is in an invalid state.
@@ -586,6 +605,10 @@ public class PlaybackServiceMediaPlayer {
return mediaType;
}
+ public PlayerStatus getPlayerStatus() {
+ return playerStatus;
+ }
+
public boolean isStreaming() {
return stream;
}
@@ -599,6 +622,9 @@ public class PlaybackServiceMediaPlayer {
if (mediaPlayer != null) {
mediaPlayer.release();
}
+ if (mediaSession != null) {
+ mediaSession.release();
+ }
releaseWifiLockIfNecessary();
}
@@ -663,6 +689,16 @@ public class PlaybackServiceMediaPlayer {
}
/**
+ * Returns a token to this object's MediaSession. The MediaSession should only be used for notifications
+ * at the moment.
+ *
+ * @return The MediaSessionCompat.Token object.
+ */
+ public MediaSessionCompat.Token getSessionToken() {
+ return mediaSession.getSessionToken();
+ }
+
+ /**
* Sets the player status of the PSMP object. PlayerStatus and media attributes have to be set at the same time
* so that getPSMPInfo can't return an invalid state (e.g. status is PLAYING, but media is null).
* <p/>
@@ -679,6 +715,45 @@ public class PlaybackServiceMediaPlayer {
this.playerStatus = newStatus;
this.media = newMedia;
+
+ PlaybackStateCompat.Builder sessionState = new PlaybackStateCompat.Builder();
+
+ int state;
+ if (playerStatus != null) {
+ switch (playerStatus) {
+ case PLAYING:
+ state = PlaybackStateCompat.STATE_PLAYING;
+ break;
+ case PREPARED:
+ case PAUSED:
+ state = PlaybackStateCompat.STATE_PAUSED;
+ break;
+ case STOPPED:
+ state = PlaybackStateCompat.STATE_STOPPED;
+ break;
+ case SEEKING:
+ state = PlaybackStateCompat.STATE_FAST_FORWARDING;
+ break;
+ case PREPARING:
+ case INITIALIZING:
+ state = PlaybackStateCompat.STATE_CONNECTING;
+ break;
+ case INITIALIZED:
+ case INDETERMINATE:
+ state = PlaybackStateCompat.STATE_NONE;
+ break;
+ case ERROR:
+ state = PlaybackStateCompat.STATE_ERROR;
+ break;
+ default:
+ state = PlaybackStateCompat.STATE_NONE;
+ break;
+ }
+ } else {
+ state = PlaybackStateCompat.STATE_NONE;
+ }
+ sessionState.setState(state, PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN, getPlaybackSpeed());
+
callback.statusChanged(new PSMPInfo(playerStatus, media));
}
@@ -976,4 +1051,54 @@ public class PlaybackServiceMediaPlayer {
}
});
}
+
+ private final MediaSessionCompat.Callback sessionCallback = new MediaSessionCompat.Callback() {
+
+ @Override
+ public void onPlay() {
+ if (playerStatus == PlayerStatus.PAUSED || playerStatus == PlayerStatus.PREPARED) {
+ resume();
+ } else if (playerStatus == PlayerStatus.INITIALIZED) {
+ setStartWhenPrepared(true);
+ prepare();
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ if (playerStatus == PlayerStatus.PLAYING) {
+ pause(false, true);
+ }
+ if (UserPreferences.isPersistNotify()) {
+ pause(false, true);
+ } else {
+ pause(true, true);
+ }
+ }
+
+ @Override
+ public void onSkipToNext() {
+ super.onSkipToNext();
+ endPlayback();
+ }
+
+ @Override
+ public void onFastForward() {
+ super.onFastForward();
+ seekDelta(UserPreferences.getSeekDeltaMs());
+ }
+
+ @Override
+ public void onRewind() {
+ super.onRewind();
+ seekDelta(-UserPreferences.getSeekDeltaMs());
+ }
+
+ @Override
+ public void onSeekTo(long pos) {
+ super.onSeekTo(pos);
+ seekTo((int) pos);
+ }
+ };
}
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
new file mode 100644
index 000000000..0164e914b
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java
@@ -0,0 +1,103 @@
+package de.danoeh.antennapod.core.storage;
+
+import android.content.Context;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.util.QueueAccess;
+
+/**
+ * Implementation of the EpisodeCleanupAlgorithm interface used by AntennaPod.
+ */
+public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm<Integer> {
+ private static final String TAG = "APCleanupAlgorithm";
+
+ @Override
+ public int performCleanup(Context context, Integer episodeNumber) {
+ List<FeedItem> candidates = new ArrayList<FeedItem>();
+ List<FeedItem> downloadedItems = DBReader.getDownloadedItems(context);
+ QueueAccess queue = QueueAccess.IDListAccess(DBReader.getQueueIDList(context));
+ List<FeedItem> delete;
+ for (FeedItem item : downloadedItems) {
+ if (item.hasMedia() && item.getMedia().isDownloaded()
+ && !queue.contains(item.getId()) && item.isRead()) {
+ candidates.add(item);
+ }
+
+ }
+
+ Collections.sort(candidates, new Comparator<FeedItem>() {
+ @Override
+ public int compare(FeedItem lhs, FeedItem rhs) {
+ Date l = lhs.getMedia().getPlaybackCompletionDate();
+ Date r = rhs.getMedia().getPlaybackCompletionDate();
+
+ if (l == null) {
+ l = new Date(0);
+ }
+ if (r == null) {
+ r = new Date(0);
+ }
+ return l.compareTo(r);
+ }
+ });
+
+ if (candidates.size() > episodeNumber) {
+ delete = candidates.subList(0, episodeNumber);
+ } else {
+ delete = candidates;
+ }
+
+ for (FeedItem item : delete) {
+ try {
+ DBWriter.deleteFeedMediaOfItem(context, item.getMedia().getId()).get();
+ } catch (InterruptedException | ExecutionException e) {
+ e.printStackTrace();
+ }
+ }
+
+ int counter = delete.size();
+
+
+ Log.i(TAG, String.format(
+ "Auto-delete deleted %d episodes (%d requested)", counter,
+ episodeNumber));
+
+ return counter;
+ }
+
+ @Override
+ public Integer getDefaultCleanupParameter(Context context) {
+ return getPerformAutoCleanupArgs(context, 0);
+ }
+
+ @Override
+ public Integer getPerformCleanupParameter(Context context, List<FeedItem> items) {
+ return getPerformAutoCleanupArgs(context, items.size());
+ }
+
+ static int getPerformAutoCleanupArgs(Context context,
+ final int episodeNumber) {
+ if (episodeNumber >= 0
+ && UserPreferences.getEpisodeCacheSize() != UserPreferences
+ .getEpisodeCacheSizeUnlimited()) {
+ int downloadedEpisodes = DBReader
+ .getNumberOfDownloadedEpisodes(context);
+ if (downloadedEpisodes + episodeNumber >= UserPreferences
+ .getEpisodeCacheSize()) {
+
+ return downloadedEpisodes + episodeNumber
+ - UserPreferences.getEpisodeCacheSize();
+ }
+ }
+ return 0;
+ }
+}
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
new file mode 100644
index 000000000..c5f871f48
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java
@@ -0,0 +1,133 @@
+package de.danoeh.antennapod.core.storage;
+
+import android.content.Context;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+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;
+import de.danoeh.antennapod.core.util.PowerUtils;
+
+/**
+ * Implements the automatic download algorithm used by AntennaPod. This class assumes that
+ * the client uses the APEpisodeCleanupAlgorithm.
+ */
+public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm {
+ private static final String TAG = "APDownloadAlgorithm";
+
+ private final APCleanupAlgorithm cleanupAlgorithm = new APCleanupAlgorithm();
+
+ /**
+ * Looks for undownloaded episodes in the queue or list of unread 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
+ * This method is executed on an internal single thread executor.
+ *
+ * @param context Used for accessing the DB.
+ * @param mediaIds If this list is not empty, the method will only download a candidate for automatic downloading if
+ * its media ID is in the mediaIds list.
+ * @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() {
+
+ // true if we should auto download based on network status
+ boolean networkShouldAutoDl = NetworkUtils.autodownloadNetworkAvailable(context)
+ && UserPreferences.isEnableAutodownload();
+
+ // true if we should auto download based on power status
+ boolean powerShouldAutoDl = PowerUtils.deviceCharging(context)
+ || UserPreferences.isEnableAutodownloadOnBattery();
+
+ // we should only auto download if both network AND power are happy
+ if (networkShouldAutoDl && powerShouldAutoDl) {
+
+ Log.d(TAG, "Performing auto-dl of undownloaded episodes");
+
+ final List<FeedItem> queue = DBReader.getQueue(context);
+ final List<FeedItem> unreadItems = DBReader
+ .getUnreadItemsList(context);
+
+ int undownloadedEpisodes = DBTasks.getNumberOfUndownloadedEpisodes(queue,
+ unreadItems);
+ int downloadedEpisodes = DBReader
+ .getNumberOfDownloadedEpisodes(context);
+ int deletedEpisodes = cleanupAlgorithm.performCleanup(context,
+ APCleanupAlgorithm.getPerformAutoCleanupArgs(context, undownloadedEpisodes));
+ int episodeSpaceLeft = undownloadedEpisodes;
+ boolean cacheIsUnlimited = UserPreferences.getEpisodeCacheSize() == UserPreferences
+ .getEpisodeCacheSizeUnlimited();
+
+ if (!cacheIsUnlimited
+ && UserPreferences.getEpisodeCacheSize() < downloadedEpisodes
+ + undownloadedEpisodes) {
+ episodeSpaceLeft = UserPreferences.getEpisodeCacheSize()
+ - (downloadedEpisodes - deletedEpisodes);
+ }
+
+ Arrays.sort(mediaIds); // sort for binary search
+ final boolean ignoreMediaIds = mediaIds.length == 0;
+ List<FeedItem> itemsToDownload = new ArrayList<FeedItem>();
+
+ if (episodeSpaceLeft > 0 && undownloadedEpisodes > 0) {
+ for (int i = 0; i < queue.size(); i++) { // ignore playing item
+ FeedItem item = queue.get(i);
+ long mediaId = (item.hasMedia()) ? item.getMedia().getId() : -1;
+ if ((ignoreMediaIds || Arrays.binarySearch(mediaIds, mediaId) >= 0)
+ && item.hasMedia()
+ && !item.getMedia().isDownloaded()
+ && !item.getMedia().isPlaying()
+ && item.getFeed().getPreferences().getAutoDownload()) {
+ itemsToDownload.add(item);
+ episodeSpaceLeft--;
+ undownloadedEpisodes--;
+ if (episodeSpaceLeft == 0 || undownloadedEpisodes == 0) {
+ break;
+ }
+ }
+ }
+ }
+
+ if (episodeSpaceLeft > 0 && undownloadedEpisodes > 0) {
+ for (FeedItem item : unreadItems) {
+ long mediaId = (item.hasMedia()) ? item.getMedia().getId() : -1;
+ if ((ignoreMediaIds || Arrays.binarySearch(mediaIds, mediaId) >= 0)
+ && item.hasMedia()
+ && !item.getMedia().isDownloaded()
+ && item.getFeed().getPreferences().getAutoDownload()) {
+ itemsToDownload.add(item);
+ episodeSpaceLeft--;
+ undownloadedEpisodes--;
+ if (episodeSpaceLeft == 0 || undownloadedEpisodes == 0) {
+ break;
+ }
+ }
+ }
+ }
+ if (BuildConfig.DEBUG)
+ Log.d(TAG, "Enqueueing " + itemsToDownload.size()
+ + " items for download");
+
+ 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/APSPCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java
new file mode 100644
index 000000000..420bbc09d
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java
@@ -0,0 +1,139 @@
+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<Integer> {
+ 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<FeedItem> candidates = getAutoCleanupCandidates(context);
+ List<FeedItem> deleteList = new ArrayList<FeedItem>();
+ long deletedEpisodesSize = 0;
+ Collections.sort(candidates, new Comparator<FeedItem>() {
+ @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<FeedItem> 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<FeedItem> 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<FeedItem> getAutoCleanupCandidates(Context context) {
+ List<FeedItem> downloaded = new ArrayList<FeedItem>(DBReader.getDownloadedItems(context));
+ List<FeedItem> recent = new ArrayList<FeedItem>(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
new file mode 100644
index 000000000..f760ec0ce
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java
@@ -0,0 +1,72 @@
+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<FeedItem> itemsToDownload = DBReader.getRecentlyPublishedEpisodes(context,
+ numberOfNewAutomaticallyDownloadedEpisodes);
+ Iterator<FeedItem> 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/AutomaticDownloadAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/AutomaticDownloadAlgorithm.java
new file mode 100644
index 000000000..9ca9620a7
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/AutomaticDownloadAlgorithm.java
@@ -0,0 +1,20 @@
+package de.danoeh.antennapod.core.storage;
+
+import android.content.Context;
+
+public interface AutomaticDownloadAlgorithm {
+
+ /**
+ * Looks for undownloaded episodes 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
+ * This method is executed on an internal single thread executor.
+ *
+ * @param context Used for accessing the DB.
+ * @param mediaIds If this list is not empty, the method will only download a candidate for automatic downloading if
+ * its media ID is in the mediaIds list.
+ * @return A Runnable that will be submitted to an ExecutorService.
+ */
+ public Runnable autoDownloadUndownloadedItems(Context context, long... mediaIds);
+}
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 b1aff5594..e73f9599d 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
@@ -8,7 +8,6 @@ import android.util.Log;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
@@ -35,7 +34,6 @@ import de.danoeh.antennapod.core.service.GpodnetSyncService;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.util.DownloadError;
-import de.danoeh.antennapod.core.util.NetworkUtils;
import de.danoeh.antennapod.core.util.QueueAccess;
import de.danoeh.antennapod.core.util.comparator.FeedItemPubdateComparator;
import de.danoeh.antennapod.core.util.exception.MediaFileNotFoundException;
@@ -386,8 +384,8 @@ public final class DBTasks {
downloadFeedItems(true, context, items);
}
- private static void downloadFeedItems(boolean performAutoCleanup,
- final Context context, final FeedItem... items)
+ static void downloadFeedItems(boolean performAutoCleanup,
+ final Context context, final FeedItem... items)
throws DownloadRequestException {
final DownloadRequester requester = DownloadRequester.getInstance();
@@ -396,8 +394,10 @@ public final class DBTasks {
@Override
public void run() {
- performAutoCleanup(context,
- getPerformAutoCleanupArgs(context, items.length));
+ ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm()
+ .performCleanup(context,
+ ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm()
+ .getPerformCleanupParameter(context, Arrays.asList(items)));
}
}.start();
@@ -427,7 +427,7 @@ public final class DBTasks {
}
}
- private static int getNumberOfUndownloadedEpisodes(
+ static int getNumberOfUndownloadedEpisodes(
final List<FeedItem> queue, final List<FeedItem> unreadItems) {
int counter = 0;
for (FeedItem item : queue) {
@@ -449,7 +449,8 @@ public final class DBTasks {
/**
* Looks for undownloaded episodes in the queue or list of unread items and request a download if
* 1. Network is available
- * 2. There is free space in the episode cache
+ * 2. The device is charging or the user allows auto download on battery
+ * 3. There is free space in the episode cache
* This method is executed on an internal single thread executor.
*
* @param context Used for accessing the DB.
@@ -458,107 +459,9 @@ 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) {
- return autodownloadExec.submit(new Runnable() {
- @Override
- public void run() {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Performing auto-dl of undownloaded episodes");
- if (NetworkUtils.autodownloadNetworkAvailable(context)
- && UserPreferences.isEnableAutodownload()) {
- final List<FeedItem> queue = DBReader.getQueue(context);
- final List<FeedItem> unreadItems = DBReader
- .getUnreadItemsList(context);
-
- int undownloadedEpisodes = getNumberOfUndownloadedEpisodes(queue,
- unreadItems);
- int downloadedEpisodes = DBReader
- .getNumberOfDownloadedEpisodes(context);
- int deletedEpisodes = performAutoCleanup(context,
- getPerformAutoCleanupArgs(context, undownloadedEpisodes));
- int episodeSpaceLeft = undownloadedEpisodes;
- boolean cacheIsUnlimited = UserPreferences.getEpisodeCacheSize() == UserPreferences
- .getEpisodeCacheSizeUnlimited();
-
- if (!cacheIsUnlimited
- && UserPreferences.getEpisodeCacheSize() < downloadedEpisodes
- + undownloadedEpisodes) {
- episodeSpaceLeft = UserPreferences.getEpisodeCacheSize()
- - (downloadedEpisodes - deletedEpisodes);
- }
-
- Arrays.sort(mediaIds); // sort for binary search
- final boolean ignoreMediaIds = mediaIds.length == 0;
- List<FeedItem> itemsToDownload = new ArrayList<FeedItem>();
-
- if (episodeSpaceLeft > 0 && undownloadedEpisodes > 0) {
- for (int i = 0; i < queue.size(); i++) { // ignore playing item
- FeedItem item = queue.get(i);
- long mediaId = (item.hasMedia()) ? item.getMedia().getId() : -1;
- if ((ignoreMediaIds || Arrays.binarySearch(mediaIds, mediaId) >= 0)
- && item.hasMedia()
- && !item.getMedia().isDownloaded()
- && !item.getMedia().isPlaying()
- && item.getFeed().getPreferences().getAutoDownload()) {
- itemsToDownload.add(item);
- episodeSpaceLeft--;
- undownloadedEpisodes--;
- if (episodeSpaceLeft == 0 || undownloadedEpisodes == 0) {
- break;
- }
- }
- }
- }
-
- if (episodeSpaceLeft > 0 && undownloadedEpisodes > 0) {
- for (FeedItem item : unreadItems) {
- long mediaId = (item.hasMedia()) ? item.getMedia().getId() : -1;
- if ((ignoreMediaIds || Arrays.binarySearch(mediaIds, mediaId) >= 0)
- && item.hasMedia()
- && !item.getMedia().isDownloaded()
- && item.getFeed().getPreferences().getAutoDownload()) {
- itemsToDownload.add(item);
- episodeSpaceLeft--;
- undownloadedEpisodes--;
- if (episodeSpaceLeft == 0 || undownloadedEpisodes == 0) {
- break;
- }
- }
- }
- }
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Enqueueing " + itemsToDownload.size()
- + " items for download");
-
- try {
- downloadFeedItems(false, context,
- itemsToDownload.toArray(new FeedItem[itemsToDownload
- .size()])
- );
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- }
+ return autodownloadExec.submit(ClientConfig.dbTasksCallbacks.getAutomaticDownloadAlgorithm()
+ .autoDownloadUndownloadedItems(context, mediaIds));
- }
- }
- });
-
- }
-
- private static int getPerformAutoCleanupArgs(Context context,
- final int episodeNumber) {
- if (episodeNumber >= 0
- && UserPreferences.getEpisodeCacheSize() != UserPreferences
- .getEpisodeCacheSizeUnlimited()) {
- int downloadedEpisodes = DBReader
- .getNumberOfDownloadedEpisodes(context);
- if (downloadedEpisodes + episodeNumber >= UserPreferences
- .getEpisodeCacheSize()) {
-
- return downloadedEpisodes + episodeNumber
- - UserPreferences.getEpisodeCacheSize();
- }
- }
- return 0;
}
/**
@@ -570,63 +473,8 @@ public final class DBTasks {
* @param context Used for accessing the DB.
*/
public static void performAutoCleanup(final Context context) {
- performAutoCleanup(context, getPerformAutoCleanupArgs(context, 0));
- }
-
- private static int performAutoCleanup(final Context context,
- final int episodeNumber) {
- List<FeedItem> candidates = new ArrayList<FeedItem>();
- List<FeedItem> downloadedItems = DBReader.getDownloadedItems(context);
- QueueAccess queue = QueueAccess.IDListAccess(DBReader.getQueueIDList(context));
- List<FeedItem> delete;
- for (FeedItem item : downloadedItems) {
- if (item.hasMedia() && item.getMedia().isDownloaded()
- && !queue.contains(item.getId()) && item.isRead()) {
- candidates.add(item);
- }
-
- }
-
- Collections.sort(candidates, new Comparator<FeedItem>() {
- @Override
- public int compare(FeedItem lhs, FeedItem rhs) {
- Date l = lhs.getMedia().getPlaybackCompletionDate();
- Date r = rhs.getMedia().getPlaybackCompletionDate();
-
- if (l == null) {
- l = new Date(0);
- }
- if (r == null) {
- r = new Date(0);
- }
- return l.compareTo(r);
- }
- });
-
- if (candidates.size() > episodeNumber) {
- delete = candidates.subList(0, episodeNumber);
- } else {
- delete = candidates;
- }
-
- for (FeedItem item : delete) {
- try {
- DBWriter.deleteFeedMediaOfItem(context, item.getMedia().getId()).get();
- } catch (InterruptedException e) {
- e.printStackTrace();
- } catch (ExecutionException e) {
- e.printStackTrace();
- }
- }
-
- int counter = delete.size();
-
- if (BuildConfig.DEBUG)
- Log.d(TAG, String.format(
- "Auto-delete deleted %d episodes (%d requested)", counter,
- episodeNumber));
-
- return counter;
+ ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm().performCleanup(context,
+ ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm().getDefaultCleanupParameter(context));
}
/**
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 d71d19433..87bbdf455 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
@@ -7,23 +7,14 @@ import android.content.SharedPreferences;
import android.database.Cursor;
import android.preference.PreferenceManager;
import android.util.Log;
-import de.danoeh.antennapod.core.BuildConfig;
-import de.danoeh.antennapod.core.ClientConfig;
-import de.danoeh.antennapod.core.asynctask.FlattrClickWorker;
-import de.danoeh.antennapod.core.feed.*;
-import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
-import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
-import de.danoeh.antennapod.core.service.download.DownloadStatus;
-import de.danoeh.antennapod.core.service.playback.PlaybackService;
-import de.danoeh.antennapod.core.util.QueueAccess;
-import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
-import de.danoeh.antennapod.core.util.flattr.FlattrThing;
-import de.danoeh.antennapod.core.util.flattr.SimpleFlattrThing;
+
import org.shredzone.flattr4j.model.Flattr;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
@@ -33,6 +24,24 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
+import de.danoeh.antennapod.core.BuildConfig;
+import de.danoeh.antennapod.core.ClientConfig;
+import de.danoeh.antennapod.core.asynctask.FlattrClickWorker;
+import de.danoeh.antennapod.core.feed.EventDistributor;
+import de.danoeh.antennapod.core.feed.Feed;
+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.GpodnetPreferences;
+import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
+import de.danoeh.antennapod.core.service.download.DownloadStatus;
+import de.danoeh.antennapod.core.service.playback.PlaybackService;
+import de.danoeh.antennapod.core.util.QueueAccess;
+import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
+import de.danoeh.antennapod.core.util.flattr.FlattrThing;
+import de.danoeh.antennapod.core.util.flattr.SimpleFlattrThing;
+
/**
* Provides methods for writing data to AntennaPod's database.
* In general, DBWriter-methods will be executed on an internal ExecutorService.
@@ -819,7 +828,8 @@ public class DBWriter {
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
for (String key : urls.keySet()) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Replacing URL " + key + " with url " + urls.get(key));
+ if (BuildConfig.DEBUG)
+ Log.d(TAG, "Replacing URL " + key + " with url " + urls.get(key));
adapter.setFeedDownloadUrl(key, urls.get(key));
}
@@ -976,4 +986,35 @@ public class DBWriter {
}
});
}
+
+ /**
+ * Sort the FeedItems in the queue with the given Comparator.
+ *
+ * @param context A context that is used for opening a database connection.
+ * @param comparator FeedItem comparator
+ * @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to
+ * false if the caller wants to avoid unexpected updates of the GUI.
+ */
+ public static Future<?> sortQueue(final Context context, final Comparator<FeedItem> comparator, final boolean broadcastUpdate) {
+ return dbExec.submit(new Runnable() {
+ @Override
+ public void run() {
+ final PodDBAdapter adapter = new PodDBAdapter(context);
+ adapter.open();
+ final List<FeedItem> queue = DBReader.getQueue(context, adapter);
+
+ if (queue != null) {
+ Collections.sort(queue, comparator);
+ adapter.setQueue(queue);
+ if (broadcastUpdate) {
+ EventDistributor.getInstance()
+ .sendQueueUpdateBroadcast();
+ }
+ } else {
+ Log.e(TAG, "sortQueue: Could not load queue");
+ }
+ adapter.close();
+ }
+ });
+ }
}
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 f5ee9e28c..d0cdad649 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
@@ -92,8 +92,9 @@ public class DownloadRequester {
private void download(Context context, FeedFile item, FeedFile container, File dest,
boolean overwriteIfExists, String username, String password, boolean deleteOnFailure, Bundle arguments) {
+ final boolean partiallyDownloadedFileExists = item.getFile_url() != null;
if (!isDownloadingFile(item)) {
- if (!isFilenameAvailable(dest.toString()) || (deleteOnFailure && dest.exists())) {
+ if (!isFilenameAvailable(dest.toString()) || (!partiallyDownloadedFileExists && dest.exists())) {
if (BuildConfig.DEBUG)
Log.d(TAG, "Filename already used.");
if (isFilenameAvailable(dest.toString()) && overwriteIfExists) {
@@ -254,8 +255,7 @@ public class DownloadRequester {
* Cancels all running downloads
*/
public synchronized void cancelAllDownloads(Context context) {
- if (BuildConfig.DEBUG)
- Log.d(TAG, "Cancelling all running downloads");
+ Log.d(TAG, "Cancelling all running downloads");
context.sendBroadcast(new Intent(
DownloadService.ACTION_CANCEL_ALL_DOWNLOADS));
}
@@ -377,10 +377,13 @@ public class DownloadRequester {
String URLBaseFilename = URLUtil.guessFileName(media.getDownload_url(),
null, media.getMime_type());
- ;
- if (titleBaseFilename != "") {
+ if (!titleBaseFilename.equals("")) {
// Append extension
+ final int FILENAME_MAX_LENGTH = 220;
+ if (titleBaseFilename.length() > FILENAME_MAX_LENGTH) {
+ titleBaseFilename = titleBaseFilename.substring(0, FILENAME_MAX_LENGTH);
+ }
filename = titleBaseFilename + FilenameUtils.EXTENSION_SEPARATOR +
FilenameUtils.getExtension(URLBaseFilename);
} else {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/EpisodeCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/EpisodeCleanupAlgorithm.java
new file mode 100644
index 000000000..6a8b4a441
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/EpisodeCleanupAlgorithm.java
@@ -0,0 +1,36 @@
+package de.danoeh.antennapod.core.storage;
+
+import android.content.Context;
+
+import java.util.List;
+
+import de.danoeh.antennapod.core.feed.FeedItem;
+
+public interface EpisodeCleanupAlgorithm<T> {
+
+ /**
+ * Deletes downloaded episodes that are no longer needed. What episodes are deleted and how many
+ * of them depends on the implementation.
+ *
+ * @param context Can be used for accessing the database
+ * @param parameter An additional parameter. This parameter is either returned by getDefaultCleanupParameter
+ * or getPerformCleanupParameter.
+ * @return The number of episodes that were deleted.
+ */
+ public int performCleanup(Context context, T parameter);
+
+ /**
+ * Returns a parameter for performCleanup. The implementation of this interface should decide how much
+ * space to free to satisfy the episode cache conditions. If the conditions are already satisfied, this
+ * method should not have any effects.
+ */
+ public T getDefaultCleanupParameter(Context context);
+
+ /**
+ * Returns a parameter for performCleanup.
+ *
+ * @param items A list of FeedItems that are about to be downloaded. The implementation of this interface
+ * should decide how much space to free to satisfy the episode cache conditions.
+ */
+ public T getPerformCleanupParameter(Context context, List<FeedItem> items);
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/PowerUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/PowerUtils.java
new file mode 100644
index 000000000..39deea36a
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/PowerUtils.java
@@ -0,0 +1,32 @@
+package de.danoeh.antennapod.core.util;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
+
+/**
+ * Created by Tom on 1/5/15.
+ */
+public class PowerUtils {
+
+ private static final String TAG = "PowerUtils";
+
+ private PowerUtils() {
+
+ }
+
+ /**
+ * @return true if the device is charging
+ */
+ public static boolean deviceCharging(Context context) {
+ // from http://developer.android.com/training/monitoring-device-state/battery-monitoring.html
+ IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
+ Intent batteryStatus = context.registerReceiver(null, iFilter);
+
+ int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
+ return (status == BatteryManager.BATTERY_STATUS_CHARGING ||
+ status == BatteryManager.BATTERY_STATUS_FULL);
+
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java b/core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java
new file mode 100644
index 000000000..9a1496b75
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java
@@ -0,0 +1,89 @@
+package de.danoeh.antennapod.core.util;
+
+import android.content.Context;
+
+import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.feed.FeedMedia;
+import de.danoeh.antennapod.core.storage.DBWriter;
+
+import java.util.Comparator;
+
+/**
+ * Provides method for sorting the queue according to rules.
+ */
+public class QueueSorter {
+ public enum Rule {
+ ALPHA_ASC,
+ ALPHA_DESC,
+ DATE_ASC,
+ DATE_DESC,
+ DURATION_ASC,
+ DURATION_DESC
+ }
+
+ public static void sort(final Context context, final Rule rule, final boolean broadcastUpdate) {
+ Comparator<FeedItem> comparator = null;
+
+ switch (rule) {
+ case ALPHA_ASC:
+ comparator = new Comparator<FeedItem>() {
+ public int compare(FeedItem f1, FeedItem f2) {
+ return f1.getTitle().compareTo(f2.getTitle());
+ }
+ };
+ break;
+ case ALPHA_DESC:
+ comparator = new Comparator<FeedItem>() {
+ public int compare(FeedItem f1, FeedItem f2) {
+ return f2.getTitle().compareTo(f1.getTitle());
+ }
+ };
+ break;
+ case DATE_ASC:
+ comparator = new Comparator<FeedItem>() {
+ public int compare(FeedItem f1, FeedItem f2) {
+ return f1.getPubDate().compareTo(f2.getPubDate());
+ }
+ };
+ break;
+ case DATE_DESC:
+ comparator = new Comparator<FeedItem>() {
+ public int compare(FeedItem f1, FeedItem f2) {
+ return f2.getPubDate().compareTo(f1.getPubDate());
+ }
+ };
+ break;
+ case DURATION_ASC:
+ comparator = new Comparator<FeedItem>() {
+ public int compare(FeedItem f1, FeedItem f2) {
+ FeedMedia f1Media = f1.getMedia();
+ FeedMedia f2Media = f2.getMedia();
+ int duration1 = f1Media != null ? f1Media.getDuration() : -1;
+ int duration2 = f2Media != null ? f2Media.getDuration() : -1;
+
+ if (duration1 == -1 || duration2 == -1)
+ return duration2 - duration1;
+ else
+ return duration1 - duration2;
+ }
+ };
+ break;
+ case DURATION_DESC:
+ comparator = new Comparator<FeedItem>() {
+ public int compare(FeedItem f1, FeedItem f2) {
+ FeedMedia f1Media = f1.getMedia();
+ FeedMedia f2Media = f2.getMedia();
+ int duration1 = f1Media != null ? f1Media.getDuration() : -1;
+ int duration2 = f2Media != null ? f2Media.getDuration() : -1;
+
+ return -1 * (duration1 - duration2);
+ }
+ };
+ default:
+ }
+
+ if (comparator != null) {
+ DBWriter.sortQueue(context, comparator, broadcastUpdate);
+ }
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java
index 443ff0ad1..f31297b41 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java
@@ -28,7 +28,7 @@ import de.danoeh.antennapod.core.util.ShownotesProvider;
public class Timeline {
private static final String TAG = "Timeline";
- private static final String WEBVIEW_STYLE = "@font-face { font-family: 'Roboto-Light'; src: url('file:///android_asset/Roboto-Light.ttf'); } * { color: %s; font-family: roboto-Light; font-size: 11pt; } a { font-style: normal; text-decoration: none; font-weight: normal; color: #00A8DF; } a.timecode { color: #669900; } img { display: block; margin: 10 auto; max-width: %s; height: auto; } body { margin: %dpx %dpx %dpx %dpx; }";
+ private static final String WEBVIEW_STYLE = "@font-face { font-family: 'Roboto-Light'; src: url('file:///android_asset/Roboto-Light.ttf'); } * { color: %s; font-family: roboto-Light; font-size: 13pt; } a { font-style: normal; text-decoration: none; font-weight: normal; color: #00A8DF; } a.timecode { color: #669900; } img { display: block; margin: 10 auto; max-width: %s; height: auto; } body { margin: %dpx %dpx %dpx %dpx; }";
private ShownotesProvider shownotesProvider;
diff --git a/core/src/main/res/drawable-hdpi/ic_settings_grey600_24dp.png b/core/src/main/res/drawable-hdpi/ic_settings_grey600_24dp.png
new file mode 100644
index 000000000..20d2b66e0
--- /dev/null
+++ b/core/src/main/res/drawable-hdpi/ic_settings_grey600_24dp.png
Binary files differ
diff --git a/core/src/main/res/drawable-hdpi/ic_settings_white_24dp.png b/core/src/main/res/drawable-hdpi/ic_settings_white_24dp.png
new file mode 100644
index 000000000..f9a8915fd
--- /dev/null
+++ b/core/src/main/res/drawable-hdpi/ic_settings_white_24dp.png
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_settings_grey600_24dp.png b/core/src/main/res/drawable-xhdpi/ic_settings_grey600_24dp.png
new file mode 100644
index 000000000..2251d2bbb
--- /dev/null
+++ b/core/src/main/res/drawable-xhdpi/ic_settings_grey600_24dp.png
Binary files differ
diff --git a/core/src/main/res/drawable-xhdpi/ic_settings_white_24dp.png b/core/src/main/res/drawable-xhdpi/ic_settings_white_24dp.png
new file mode 100644
index 000000000..12e5d100d
--- /dev/null
+++ b/core/src/main/res/drawable-xhdpi/ic_settings_white_24dp.png
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_settings_grey600_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_settings_grey600_24dp.png
new file mode 100644
index 000000000..6a70402b4
--- /dev/null
+++ b/core/src/main/res/drawable-xxhdpi/ic_settings_grey600_24dp.png
Binary files differ
diff --git a/core/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png
new file mode 100644
index 000000000..6bb8f6e08
--- /dev/null
+++ b/core/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png
Binary files differ
diff --git a/core/src/main/res/layout/refresh_action_view.xml b/core/src/main/res/layout/refresh_action_view.xml
new file mode 100644
index 000000000..66148a553
--- /dev/null
+++ b/core/src/main/res/layout/refresh_action_view.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="end"
+ android:indeterminateOnly="true">
+
+</ProgressBar> \ No newline at end of file
diff --git a/core/src/main/res/values-ca/strings.xml b/core/src/main/res/values-ca/strings.xml
index ed8f67234..7f8aeebae 100644
--- a/core/src/main/res/values-ca/strings.xml
+++ b/core/src/main/res/values-ca/strings.xml
@@ -144,6 +144,12 @@
<string name="removed_from_queue">Ítem esborrat</string>
<string name="move_to_top_label">Mou al principi</string>
<string name="move_to_bottom_label">Mou al final</string>
+ <string name="sort">Ordena</string>
+ <string name="alpha">Alfabèticament</string>
+ <string name="date">Data</string>
+ <string name="duration">Durada</string>
+ <string name="ascending">Ascendent</string>
+ <string name="descending">Descendent</string>
<!--Flattr-->
<string name="flattr_auth_label">Inici de sessió a Flattr</string>
<string name="flattr_auth_explanation">Premeu el botó per iniciar el procés d\'autenticació. Quan s\'obri la pantalla d\'inici de sessió de Flattr al vostre navegador, introduïu les vostres credencials i concediu a AntennaPod els permisos de compartir mitjançant Flattr. En finalitzar el procés, tornareu automàticament a aquesta pantalla.</string>
@@ -173,6 +179,7 @@
<!--Variable Speed-->
<string name="download_plugin_label">Baixa el connector</string>
<string name="no_playback_plugin_title">Connector no instal·lat</string>
+ <string name="no_playback_plugin_msg">Per a què funcioni la velocitat de reproducció variable, cal instal·lar una biblioteca addicional.\n\nFeu un toc a «Baixa el connector» per baixar-vos el connector gratuït des de la Play Store.\n\nQualsevol problema que sorgeixi en utilitzar aquest connector no és culpa de l\'AntennaPod. Cal informar-ne, doncs, al propietari del connector.</string>
<string name="set_playback_speed_label">Velocitats de reproducció</string>
<!--Empty list labels-->
<string name="no_items_label">No hi ha elements a la llista.</string>
@@ -184,7 +191,10 @@
<string name="services_label">Serveis</string>
<string name="flattr_label">Flattr</string>
<string name="pref_pauseOnHeadsetDisconnect_sum">Pausa la reproducció en desconnectar els auriculars.</string>
+ <string name="pref_unpauseOnHeadsetReconnect_sum">Continua la reproducció en connectar novament els auriculars</string>
<string name="pref_followQueue_sum">Salta al següent element de la cua en acabar la reproducció</string>
+ <string name="pref_auto_delete_sum">Suprimeix l\'episodi quan s\'acabi de reproduir</string>
+ <string name="pref_auto_delete_title">Esborrat automàtic</string>
<string name="playback_pref">Reproducció</string>
<string name="network_pref">Xarxa</string>
<string name="pref_autoUpdateIntervall_title">Interval d\'actualització</string>
@@ -193,6 +203,7 @@
<string name="pref_followQueue_title">Reproducció continuada</string>
<string name="pref_downloadMediaOnWifiOnly_title">Baixa a través de xarxes sense fils</string>
<string name="pref_pauseOnHeadsetDisconnect_title">Desconnexió d\'auriculars</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">Connexió d\'auriculars</string>
<string name="pref_mobileUpdate_title">Actualitzacions sobre xarxes mòbils</string>
<string name="pref_mobileUpdate_sum">Permet actualitzacions a través de xarxes mòbils.</string>
<string name="refreshing_label">S\'està actualitzant</string>
@@ -212,6 +223,7 @@
<string name="pref_automatic_download_sum">Configureu la baixada automàtica d\'episodis.</string>
<string name="pref_autodl_wifi_filter_title">Activa el filtre de la xarxa sense fils</string>
<string name="pref_autodl_wifi_filter_sum">Permet les baixades automàtiques només per a les xarxes sense fils seleccionades.</string>
+ <string name="pref_automatic_download_on_battery_title">Baixa mentre no es carrega</string>
<string name="pref_episode_cache_title">Memòria d\'episodis</string>
<string name="pref_theme_title_light">Clar</string>
<string name="pref_theme_title_dark">Fosc</string>
diff --git a/core/src/main/res/values-cs-rCZ/strings.xml b/core/src/main/res/values-cs-rCZ/strings.xml
index a15ad6248..71a064d48 100644
--- a/core/src/main/res/values-cs-rCZ/strings.xml
+++ b/core/src/main/res/values-cs-rCZ/strings.xml
@@ -144,6 +144,12 @@
<string name="removed_from_queue">Položka odebrána</string>
<string name="move_to_top_label">Posunout na začátek</string>
<string name="move_to_bottom_label">Posunout na konec</string>
+ <string name="sort">Řazení</string>
+ <string name="alpha">Abecedně</string>
+ <string name="date">Datum</string>
+ <string name="duration">Délka</string>
+ <string name="ascending">Vzestupně</string>
+ <string name="descending">Sestupně</string>
<!--Flattr-->
<string name="flattr_auth_label">Flattr přihlášení</string>
<string name="flattr_auth_explanation">Stiskněte následující tlačítko pro spuštění autentizačního procesu. Budete přesměrováni na přihlašovací obrazovku flattru a vyzváni k potvrzení udělení práv pro použití flattru aplikací AntennaPod. Po udělení práv se automaticky vrátíte na tuto obrazovku.</string>
@@ -177,8 +183,11 @@
<string name="queue_label">Fronta</string>
<string name="services_label">Služby</string>
<string name="flattr_label">Flattr</string>
- <string name="pref_pauseOnHeadsetDisconnect_sum">Při odpojení sluchátek automaticky pozastavit přehrávání.</string>
+ <string name="pref_pauseOnHeadsetDisconnect_sum">Při odpojení sluchátek pozastavit přehrávání.</string>
+ <string name="pref_unpauseOnHeadsetReconnect_sum">Pokračovat v přehrávání po připojení sluchátek</string>
<string name="pref_followQueue_sum">Po přehrání položky z fronty přejít automaticky na další</string>
+ <string name="pref_auto_delete_sum">Smazat díl po jeho přehrání</string>
+ <string name="pref_auto_delete_title">Automatické mazání</string>
<string name="playback_pref">Přehrávání</string>
<string name="network_pref">Síť</string>
<string name="pref_autoUpdateIntervall_title">Interval aktualizace zdrojů</string>
@@ -186,7 +195,8 @@
<string name="pref_downloadMediaOnWifiOnly_sum">Stahovat soubory pouze pomocí WiFi</string>
<string name="pref_followQueue_title">Kontinuální přehrávání</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFi stahování</string>
- <string name="pref_pauseOnHeadsetDisconnect_title">Odpojení sluchátek</string>
+ <string name="pref_pauseOnHeadsetDisconnect_title">Sluchátka odpojena</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">Sluchátka připojena</string>
<string name="pref_mobileUpdate_title">Mobilní aktualizace</string>
<string name="pref_mobileUpdate_sum">Povolit aktualizace pomocí mobilního připojení</string>
<string name="refreshing_label">Obnovuji</string>
@@ -206,6 +216,8 @@
<string name="pref_automatic_download_sum">Nastavení automatického stahování epizod.</string>
<string name="pref_autodl_wifi_filter_title">Zapnout Wi-Fi filtr</string>
<string name="pref_autodl_wifi_filter_sum">Povolit automatické stahování pouze pomocí vybraných Wi-Fi sítí.</string>
+ <string name="pref_automatic_download_on_battery_title">Stahovat, pokud neprobíhá nabíjení</string>
+ <string name="pref_automatic_download_on_battery_sum">Povolit automatické stahování i pokud není baterie nabíjena</string>
<string name="pref_episode_cache_title">Historie epizod</string>
<string name="pref_theme_title_light">Světlý</string>
<string name="pref_theme_title_dark">Tmavý</string>
diff --git a/core/src/main/res/values-da/strings.xml b/core/src/main/res/values-da/strings.xml
index 8003f93c0..b3ba5006b 100644
--- a/core/src/main/res/values-da/strings.xml
+++ b/core/src/main/res/values-da/strings.xml
@@ -144,6 +144,12 @@
<string name="removed_from_queue">Emne slettet</string>
<string name="move_to_top_label">Flyt til toppen</string>
<string name="move_to_bottom_label">Flyt til bunden</string>
+ <string name="sort">Sorter</string>
+ <string name="alpha">Alfabetisk</string>
+ <string name="date">Dato</string>
+ <string name="duration">Varighed</string>
+ <string name="ascending">Stigende</string>
+ <string name="descending">Faldende</string>
<!--Flattr-->
<string name="flattr_auth_label">Flattr log ind</string>
<string name="flattr_auth_explanation">Tryk på knappen nedenfor for at starte godkendelsesprocessen. Du vil blive ført til flattr log ind siden i din browser og bedt om at give AntennaPod tilladelse til at flattr emner. Efter at du har givet tilladelsen vil du automatisk vende tilbage til denne side.</string>
@@ -185,7 +191,10 @@
<string name="services_label">Tjenester</string>
<string name="flattr_label">Flattr</string>
<string name="pref_pauseOnHeadsetDisconnect_sum">Sæt afspilning på pause når hovedtelefoner afbrydes</string>
+ <string name="pref_unpauseOnHeadsetReconnect_sum">Genoptag afspilning når hovedtelefoner tilsluttes igen</string>
<string name="pref_followQueue_sum">Hop til næste medie i køen når afspilning er færdig</string>
+ <string name="pref_auto_delete_sum">Slet episode når afspilningen er færdig</string>
+ <string name="pref_auto_delete_title">Slet Automatisk</string>
<string name="playback_pref">Afspilning</string>
<string name="network_pref">Netværk</string>
<string name="pref_autoUpdateIntervall_title">Opdaterings interval</string>
@@ -194,6 +203,7 @@
<string name="pref_followQueue_title">Kontinuerlig afspilning</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFi medie download</string>
<string name="pref_pauseOnHeadsetDisconnect_title">Hovedtelefoner afbrudt</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">Hovedtelefoner tilsluttes igen</string>
<string name="pref_mobileUpdate_title">Mobile opdateringer</string>
<string name="pref_mobileUpdate_sum">Tillad opdateringer over mobil data forbindelse</string>
<string name="refreshing_label">Opdaterer</string>
@@ -213,6 +223,8 @@
<string name="pref_automatic_download_sum">Konfigurer automatisk download af episoder</string>
<string name="pref_autodl_wifi_filter_title">Sæt Wi-Fi filter til</string>
<string name="pref_autodl_wifi_filter_sum">Tillad kun automatisk download for de valgte Wi-Fi netværk</string>
+ <string name="pref_automatic_download_on_battery_title">Download når der ikke oplades</string>
+ <string name="pref_automatic_download_on_battery_sum">Tillad automatisk download når batteriet ikke oplades</string>
<string name="pref_episode_cache_title">Episode cache</string>
<string name="pref_theme_title_light">Lys</string>
<string name="pref_theme_title_dark">Mørk</string>
diff --git a/core/src/main/res/values-de/strings.xml b/core/src/main/res/values-de/strings.xml
index c80363427..e47b65820 100644
--- a/core/src/main/res/values-de/strings.xml
+++ b/core/src/main/res/values-de/strings.xml
@@ -111,7 +111,7 @@
<string name="download_cancelled_msg">Download abgebrochen</string>
<string name="download_report_title">Download abgeschlossen</string>
<string name="download_error_malformed_url">Fehler in URL</string>
- <string name="download_error_io_error">IO Error</string>
+ <string name="download_error_io_error">E/A Error</string>
<string name="download_error_request_error">Anfragefehler</string>
<string name="download_error_db_access">Datenbankzugriffsfehler</string>
<string name="downloads_left">\u0020Downloads übrig</string>
@@ -144,6 +144,12 @@
<string name="removed_from_queue">Element entfernt</string>
<string name="move_to_top_label">Zum Anfang verschieben</string>
<string name="move_to_bottom_label">Zum Ende verschieben</string>
+ <string name="sort">Sortieren</string>
+ <string name="alpha">Alphabetisch</string>
+ <string name="date">Datum</string>
+ <string name="duration">Dauer</string>
+ <string name="ascending">Aufsteigend</string>
+ <string name="descending">Absteigend</string>
<!--Flattr-->
<string name="flattr_auth_label">Flattr Anmeldung</string>
<string name="flattr_auth_explanation">Drücke den Button unten um den Authentifizierungsprozess zu starten. Du wirst dann zur Flattr-Anmeldeseite weitergeleitet, wo du gefragt wirst, AntennaPod die Erlaubnis zu geben, Dinge zu flattrn. Nachdem du die Erlaubnis erteilt hast, kehrst du automatisch zu diesem Bildschirm zurück.</string>
@@ -185,7 +191,10 @@
<string name="services_label">Dienste</string>
<string name="flattr_label">Flattr</string>
<string name="pref_pauseOnHeadsetDisconnect_sum">Pausiere die Wiedergabe wenn der Kopfhörer entfernt worden ist.</string>
+ <string name="pref_unpauseOnHeadsetReconnect_sum">Wiedergabe fortsetzen wenn Kopfhörer wieder reingesteckt werden</string>
<string name="pref_followQueue_sum">Springe zur nächsten Episode wenn die vorherige Episode endet</string>
+ <string name="pref_auto_delete_sum">Episode löschen wenn Wiedergabe beendet</string>
+ <string name="pref_auto_delete_title">Automatisches Löschen</string>
<string name="playback_pref">Wiedergabe</string>
<string name="network_pref">Netzwerk</string>
<string name="pref_autoUpdateIntervall_title">Aktualisierungsintervall</string>
@@ -194,6 +203,7 @@
<string name="pref_followQueue_title">Durchgehendes Abspielen</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFi Medien-Download</string>
<string name="pref_pauseOnHeadsetDisconnect_title">Kopfhörer-Trennung</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">Kopfhörer wieder reingesteckt</string>
<string name="pref_mobileUpdate_title">Mobile Aktualisierungen</string>
<string name="pref_mobileUpdate_sum">Erlaube Aktualisierungen über die mobile Datenverbindung</string>
<string name="refreshing_label">Aktualisiere</string>
@@ -213,6 +223,8 @@
<string name="pref_automatic_download_sum">Konfiguriere das automatische Herunterladen von Episoden.</string>
<string name="pref_autodl_wifi_filter_title">W-LAN-Filter aktivieren</string>
<string name="pref_autodl_wifi_filter_sum">Erlaube das automatische Herunterladen nur in ausgewählten W-LAN Netzwerken.</string>
+ <string name="pref_automatic_download_on_battery_title">Automatischer Download im Batterie Modus</string>
+ <string name="pref_automatic_download_on_battery_sum">Automatische Downloads auch erlauben, wenn die Batterie nicht geladen wird</string>
<string name="pref_episode_cache_title">Episodenspeicher</string>
<string name="pref_theme_title_light">Hell</string>
<string name="pref_theme_title_dark">Dunkel</string>
diff --git a/core/src/main/res/values-es/strings.xml b/core/src/main/res/values-es/strings.xml
index a545c59a9..00dbb628a 100644
--- a/core/src/main/res/values-es/strings.xml
+++ b/core/src/main/res/values-es/strings.xml
@@ -13,27 +13,27 @@
<string name="settings_label">Ajustes</string>
<string name="add_new_feed_label">Añadir podcast</string>
<string name="downloads_label">Descargas</string>
- <string name="downloads_running_label">En Curso</string>
- <string name="downloads_completed_label">Completado</string>
- <string name="downloads_log_label">Log</string>
+ <string name="downloads_running_label">En curso</string>
+ <string name="downloads_completed_label">Completadas</string>
+ <string name="downloads_log_label">Registro</string>
<string name="cancel_download_label">Cancelar descarga</string>
- <string name="playback_history_label">Histórico de reproducción</string>
+ <string name="playback_history_label">Historial de reproducciones</string>
<string name="gpodnet_main_label">gpodder.net</string>
<string name="gpodnet_auth_label">Iniciar sesión en gpodder.net</string>
<!--New episodes fragment-->
- <string name="recently_published_episodes_label">Publicados Recientemente</string>
+ <string name="recently_published_episodes_label">Publicados recientemente</string>
<string name="episode_filter_label">Mostrar solo episodios nuevos</string>
<!--Main activity-->
<string name="drawer_open">Abrir menú</string>
- <string name="drawer_close">Cerrar Menú</string>
+ <string name="drawer_close">Cerrar menú</string>
<!--Webview actions-->
<string name="open_in_browser_label">Abrir en el navegador</string>
<string name="copy_url_label">Copiar URL</string>
<string name="share_url_label">Compartir URL</string>
- <string name="copied_url_msg">URL copiada al portapapeles.</string>
+ <string name="copied_url_msg">URL copiada en el portapapeles.</string>
<string name="go_to_position_label">Ir a esta posición</string>
<!--Playback history-->
- <string name="clear_history_label">Vaciar el histórico</string>
+ <string name="clear_history_label">Vaciar el historial</string>
<!--Other-->
<string name="confirm_label">Confirmar</string>
<string name="cancel_label">Cancelar</string>
@@ -42,7 +42,7 @@
<string name="podcast_settings_label">Ajustes</string>
<string name="cover_label">Imagen</string>
<string name="error_label">Error</string>
- <string name="error_msg_prefix">Ha ocurrido un error:</string>
+ <string name="error_msg_prefix">Se produjo un error:</string>
<string name="refresh_label">Actualizar</string>
<string name="external_storage_error_msg">No se encuentra un almacenamiento externo. Asegúrese de que su almacenamiento externo esté montado para que la aplicación funcione correctamente.</string>
<string name="chapters_label">Capítulos</string>
@@ -57,32 +57,32 @@
<string name="save_username_password_label">Guardar usuario y contraseña</string>
<string name="close_label">Cerrar</string>
<string name="retry_label">Reintentar</string>
- <string name="auto_download_label">Incluir en auto descargas</string>
+ <string name="auto_download_label">Incluir en descargas automáticas</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">URL del canal</string>
- <string name="etxtFeedurlHint">URL del feed o del sitio web</string>
+ <string name="etxtFeedurlHint">URL del canal o del sitio web</string>
<string name="txtvfeedurl_label">Añadir podcast por URL</string>
<string name="podcastdirectories_label">Buscar podcast en directorio</string>
- <string name="podcastdirectories_descr">Se puede buscar nuevos podcast según nombre, categoría o popularidad en el directorio gpodder.net</string>
+ <string name="podcastdirectories_descr">Es posible buscar podcasts nuevos por nombre, categoría o popularidad en el directorio de gpodder.net.</string>
<string name="browse_gpoddernet_label">Explorar gpodder.net</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Marcar todo como leído</string>
- <string name="mark_all_read_msg">Marcar todos los episodios como leídos</string>
+ <string name="mark_all_read_msg">Se marcaron todos los episodios como leídos</string>
<string name="show_info_label">Información del programa</string>
<string name="remove_feed_label">Eliminar podcast</string>
<string name="share_link_label">Compartir el enlace de la web</string>
<string name="share_source_label">Compartir el enlace del canal</string>
<string name="feed_delete_confirmation_msg">Confirme que quiere eliminar este canal y TODOS los episodios descargados del mismo.</string>
- <string name="feed_remover_msg">Eliminando el canal</string>
- <string name="load_complete_feed">Actualizar el feed completo</string>
+ <string name="feed_remover_msg">Quitando el canal</string>
+ <string name="load_complete_feed">Actualizar el canal completo</string>
<!--actions on feeditems-->
<string name="download_label">Descargar</string>
<string name="play_label">Reproducir</string>
<string name="pause_label">Pausar</string>
- <string name="stop_label">Stop</string>
- <string name="stream_label">Reproducir por streaming</string>
+ <string name="stop_label">Detener</string>
+ <string name="stream_label">Transmitir</string>
<string name="remove_label">Quitar</string>
- <string name="remove_episode_lable">Eliminar episodio</string>
+ <string name="remove_episode_lable">Quitar episodio</string>
<string name="mark_read_label">Marcar como leído</string>
<string name="mark_unread_label">Marcar como no leído</string>
<string name="add_to_queue_label">Añadir a la cola</string>
@@ -123,10 +123,10 @@
<string name="download_type_media">Archivo de medios</string>
<string name="download_type_image">Imagen</string>
<string name="download_request_error_dialog_message_prefix">Ha ocurrido un error al intentar descargar el archivo:\u0020</string>
- <string name="authentication_notification_title">Autenticación requerida</string>
- <string name="authentication_notification_msg">El recurso solicitado requiere usuario y contraseña</string>
+ <string name="authentication_notification_title">Se necesita autenticación</string>
+ <string name="authentication_notification_msg">Para acceder al recurso solicitado debe proporcionar un usuario y contraseña</string>
<!--Mediaplayer messages-->
- <string name="player_error_msg">¡Error!</string>
+ <string name="player_error_msg">Error</string>
<string name="player_stopped_msg">No hay medios en reproducción</string>
<string name="player_preparing_msg">Preparando</string>
<string name="player_ready_msg">Listo</string>
@@ -144,6 +144,12 @@
<string name="removed_from_queue">Artículo eliminado</string>
<string name="move_to_top_label">Mover al principio</string>
<string name="move_to_bottom_label">Mover al final</string>
+ <string name="sort">Ordenar</string>
+ <string name="alpha">Alfabéticamente</string>
+ <string name="date">Fecha</string>
+ <string name="duration">Duración</string>
+ <string name="ascending">Ascendente</string>
+ <string name="descending">Descendente</string>
<!--Flattr-->
<string name="flattr_auth_label">Identificarse en Flattr</string>
<string name="flattr_auth_explanation">Pulse el botón inferior para comenzar la autenticación. Su navegador abrirá la pantalla de identificación de Flattr y le preguntará si quiere conceder permiso a AntennaPod para valorar cosas. Tras concederlo, volverá a esta pantalla automáticamente.</string>
@@ -185,7 +191,10 @@
<string name="services_label">Servicios</string>
<string name="flattr_label">Flattr</string>
<string name="pref_pauseOnHeadsetDisconnect_sum">Pausar la reproducción al desconectar los auriculares</string>
+ <string name="pref_unpauseOnHeadsetReconnect_sum">Reanudar reproducción cuando se reconecten los auriculares</string>
<string name="pref_followQueue_sum">Saltar al siguiente elemento de la cola al acabar la reproducción</string>
+ <string name="pref_auto_delete_sum">Borrar episodio cuando finalice la reproducción</string>
+ <string name="pref_auto_delete_title">Eliminar automáticamente</string>
<string name="playback_pref">Reproducción</string>
<string name="network_pref">Red</string>
<string name="pref_autoUpdateIntervall_title">Intervalo de actualización</string>
@@ -194,6 +203,7 @@
<string name="pref_followQueue_title">Reproducción continua</string>
<string name="pref_downloadMediaOnWifiOnly_title">Descarga de contenidos por WiFi</string>
<string name="pref_pauseOnHeadsetDisconnect_title">Desconexión de los cascos</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">Reconectar auriculares</string>
<string name="pref_mobileUpdate_title">Actualizaciones por red móvil</string>
<string name="pref_mobileUpdate_sum">Permitir actualizaciones por red de datos móvil</string>
<string name="refreshing_label">Actualizando</string>
@@ -213,6 +223,8 @@
<string name="pref_automatic_download_sum">Configurar la descarga automática de episodios.</string>
<string name="pref_autodl_wifi_filter_title">Activar el filtro WiFi</string>
<string name="pref_autodl_wifi_filter_sum">Permitir la descarga automática sólo para las redes WiFi marcadas.</string>
+ <string name="pref_automatic_download_on_battery_title">Descargar cuando no se está cargando</string>
+ <string name="pref_automatic_download_on_battery_sum">Permitir la descarga automática cuando la batería no está cargando</string>
<string name="pref_episode_cache_title">Caché de episodios</string>
<string name="pref_theme_title_light">Claro</string>
<string name="pref_theme_title_dark">Oscuro</string>
@@ -291,7 +303,7 @@
<string name="gpodnetauth_device_descr">Cree un nuevo dispositivo para usar con su cuenta de gpodder.net o elija uno existente:</string>
<string name="gpodnetauth_device_deviceID">Id. de dispositivo:\u0020</string>
<string name="gpodnetauth_device_caption">Descripción</string>
- <string name="gpodnetauth_device_butCreateNewDevice">Crear nuevo dispositivo</string>
+ <string name="gpodnetauth_device_butCreateNewDevice">Crear dispositivo nuevo</string>
<string name="gpodnetauth_device_chooseExistingDevice">Elegir dispositivo existente:</string>
<string name="gpodnetauth_device_errorEmpty">El ID de dispositivo no puede estar vacío</string>
<string name="gpodnetauth_device_errorAlreadyUsed">El ID de dispositivo ya está en uso</string>
diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml
index 1494cc42b..ada7e4e96 100644
--- a/core/src/main/res/values-fr/strings.xml
+++ b/core/src/main/res/values-fr/strings.xml
@@ -144,6 +144,12 @@
<string name="removed_from_queue">Élément retiré</string>
<string name="move_to_top_label">Déplacer vers le haut de haut de la liste</string>
<string name="move_to_bottom_label">Déplacer vers le bas de la liste</string>
+ <string name="sort">Trier</string>
+ <string name="alpha">Ordre alphabétique</string>
+ <string name="date">Date</string>
+ <string name="duration">Durée</string>
+ <string name="ascending">Ordre croissant</string>
+ <string name="descending">Ordre décroissant</string>
<!--Flattr-->
<string name="flattr_auth_label">Connecter à Flattr</string>
<string name="flattr_auth_explanation">Appuyez sur le bouton ci-dessous pour vous authentifier. Vous serez envoyés à l\'écran de connexion Flattr dans le navigateur, et il vous sera demandé de donner à AntennaPod la permission de flattr. Une fois ceci fait, vous reviendrez automatiquement à cet écran.</string>
@@ -185,7 +191,10 @@
<string name="services_label">Services</string>
<string name="flattr_label">Flattr</string>
<string name="pref_pauseOnHeadsetDisconnect_sum">Interrompre la lecture lorsque le casque est débranché</string>
+ <string name="pref_unpauseOnHeadsetReconnect_sum">Reprendre la lecture quand les écouteurs sont reconnectés</string>
<string name="pref_followQueue_sum">Après la fin d\'un épisode, passer au suivant</string>
+ <string name="pref_auto_delete_sum">Supprimer l\'épisode quand la lecture est finie</string>
+ <string name="pref_auto_delete_title">Supression automatique</string>
<string name="playback_pref">Lecture</string>
<string name="network_pref">Réseau</string>
<string name="pref_autoUpdateIntervall_title">Intervalle de mise à jour</string>
@@ -194,6 +203,7 @@
<string name="pref_followQueue_title">Lecture continue</string>
<string name="pref_downloadMediaOnWifiOnly_title">Téléchargement en Wi-Fi</string>
<string name="pref_pauseOnHeadsetDisconnect_title">Déconnexion du casque</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">Reconnexion du casque</string>
<string name="pref_mobileUpdate_title">Mise à jour mobile</string>
<string name="pref_mobileUpdate_sum">Autoriser les mises à jour à travers la connexion de données mobile</string>
<string name="refreshing_label">Mise à jour en cours</string>
@@ -213,6 +223,8 @@
<string name="pref_automatic_download_sum">Configurer le téléchargement automatique des épisodes.</string>
<string name="pref_autodl_wifi_filter_title">Activer le filtre Wi-Fi</string>
<string name="pref_autodl_wifi_filter_sum">Autoriser le téléchargement automatique uniquement sur les réseaux Wi-Fi sélectionnés.</string>
+ <string name="pref_automatic_download_on_battery_title">Télécharger lorsque l\'appareil n\'est pas en charge</string>
+ <string name="pref_automatic_download_on_battery_sum">Autoriser le téléchargement automatique quand l\'appareil n\'est pas en train de charger</string>
<string name="pref_episode_cache_title">Épisodes stockés localement</string>
<string name="pref_theme_title_light">Clair</string>
<string name="pref_theme_title_dark">Sombre</string>
diff --git a/core/src/main/res/values-it-rIT/strings.xml b/core/src/main/res/values-it-rIT/strings.xml
index 4bd82db52..e91029724 100644
--- a/core/src/main/res/values-it-rIT/strings.xml
+++ b/core/src/main/res/values-it-rIT/strings.xml
@@ -17,7 +17,7 @@
<string name="downloads_completed_label">Completati</string>
<string name="downloads_log_label">Registro</string>
<string name="cancel_download_label">Annulla download</string>
- <string name="playback_history_label">Storico delle riproduzioni</string>
+ <string name="playback_history_label">Cronologia delle riproduzioni</string>
<string name="gpodnet_main_label">gpodder.net</string>
<string name="gpodnet_auth_label">gpodder.net login</string>
<!--New episodes fragment-->
@@ -33,7 +33,7 @@
<string name="copied_url_msg">URL copiato negli appunti</string>
<string name="go_to_position_label">Vai a questa posizione</string>
<!--Playback history-->
- <string name="clear_history_label">Cancella lo storico</string>
+ <string name="clear_history_label">Pulisci la cronologia</string>
<!--Other-->
<string name="confirm_label">Conferma</string>
<string name="cancel_label">Annulla</string>
@@ -42,18 +42,18 @@
<string name="podcast_settings_label">Impostazioni</string>
<string name="cover_label">Immagine</string>
<string name="error_label">Errore</string>
- <string name="error_msg_prefix">Un errore è stato rilevato:</string>
+ <string name="error_msg_prefix">È stato rilevato un errore:</string>
<string name="refresh_label">Aggiorna</string>
<string name="external_storage_error_msg">Non risulta disponibile lo spazio di archiviazione esterno. Assicurati che lo spazio di archiviazione sia montato per permettere all\'applicazione di funzionare correttamente.</string>
<string name="chapters_label">Capitoli</string>
<string name="shownotes_label">Note dell\'episodio</string>
<string name="description_label">Descrizione</string>
- <string name="most_recent_prefix">Episodi Recenti:\u0020</string>
+ <string name="most_recent_prefix">Episodi più recenti:\u0020</string>
<string name="episodes_suffix">\u0020episodi</string>
<string name="length_prefix">Durata:\u0020</string>
<string name="size_prefix">Dimensione:\u0020</string>
<string name="processing_label">Elaborazione in corso</string>
- <string name="loading_label">Caricamento...</string>
+ <string name="loading_label">Caricamento in corso...</string>
<string name="save_username_password_label">Salva nome utente e password</string>
<string name="close_label">Chiudi</string>
<string name="retry_label">Riprova</string>
@@ -63,6 +63,7 @@
<string name="etxtFeedurlHint">URL del feed o del sito web</string>
<string name="txtvfeedurl_label">Aggiungi un Podcast tramite URL</string>
<string name="podcastdirectories_label">Trova un podcast nella directory</string>
+ <string name="podcastdirectories_descr">Puoi cercare dei nuovi podcast in base al nome, alla categoria o alla popolarità nella directory di gpodder.net.</string>
<string name="browse_gpoddernet_label">Esplora gpodder.net</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Segna tutti come letti</string>
@@ -73,6 +74,7 @@
<string name="share_source_label">Condividi il link al feed</string>
<string name="feed_delete_confirmation_msg">Per favore conferma la cancellazione di questo feed e di TUTTI gli episodi collegati che sono stati precedentemente scaricati.</string>
<string name="feed_remover_msg">Rimozione feed</string>
+ <string name="load_complete_feed">Ricarica il feed completo</string>
<!--actions on feeditems-->
<string name="download_label">Download</string>
<string name="play_label">Riproduci</string>
@@ -86,19 +88,21 @@
<string name="add_to_queue_label">Aggiungi alla coda</string>
<string name="remove_from_queue_label">Rimuovi dalla coda</string>
<string name="visit_website_label">Visita il sito</string>
- <string name="support_label">Flattr this</string>
+ <string name="support_label">Carica questo su Flattr</string>
<string name="enqueue_all_new">Accoda tutti</string>
<string name="download_all">Scarica tutti</string>
- <string name="skip_episode_label">Salta episodio</string>
+ <string name="skip_episode_label">Salta l\'episodio</string>
<!--Download messages and labels-->
+ <string name="download_successful">successo</string>
+ <string name="download_failed">fallito</string>
<string name="download_pending">Download in attesa</string>
<string name="download_running">Download in corso</string>
<string name="download_error_device_not_found">Spazio di archiviazione non trovato</string>
<string name="download_error_insufficient_space">Spazio insufficiente</string>
<string name="download_error_file_error">Errore su file</string>
- <string name="download_error_http_data_error">HTTP Data Error</string>
+ <string name="download_error_http_data_error">Errore dei dati HTTP</string>
<string name="download_error_error_unknown">Errore sconosciuto</string>
- <string name="download_error_parser_exception">Parser Exception</string>
+ <string name="download_error_parser_exception">Eccezione del decodificatore</string>
<string name="download_error_unsupported_type">Tipo di feed non supportato</string>
<string name="download_error_connection_error">Errore di connessione</string>
<string name="download_error_unknown_host">Host sconosciuto</string>
@@ -107,58 +111,78 @@
<string name="download_cancelled_msg">Download annullato</string>
<string name="download_report_title">Download completati</string>
<string name="download_error_malformed_url">URL malformato</string>
- <string name="download_error_io_error">IO Error</string>
- <string name="download_error_request_error">Request error</string>
+ <string name="download_error_io_error">Errore IO</string>
+ <string name="download_error_request_error">Errore della richiesta</string>
<string name="download_error_db_access">Errore di accesso al database</string>
<string name="downloads_left">\u0020Download rimasti</string>
<string name="downloads_processing">Elaborazione dei download in corso</string>
<string name="download_notification_title">Download podcast in corso</string>
- <string name="download_report_content">%1$d download con successo, %2$d ko</string>
+ <string name="download_report_content">%1$d download con successo, %2$d falliti</string>
<string name="download_log_title_unknown">Titolo sconosciuto</string>
<string name="download_type_feed">Feed</string>
- <string name="download_type_media">Media file</string>
+ <string name="download_type_media">File multimediali</string>
<string name="download_type_image">Immagine</string>
<string name="download_request_error_dialog_message_prefix">Rilevato errore durante il download del file:\u0020</string>
<string name="authentication_notification_title">Autenticazione richiesta</string>
+ <string name="authentication_notification_msg">La risorsa che hai richiesto richiede un nome utente e una password</string>
<!--Mediaplayer messages-->
<string name="player_error_msg">Errore!</string>
<string name="player_stopped_msg">Nessun media in riproduzione</string>
<string name="player_preparing_msg">Preparazione</string>
<string name="player_ready_msg">Pronto</string>
<string name="player_seeking_msg">Ricerca posizione</string>
- <string name="playback_error_server_died">Server died</string>
+ <string name="playback_error_server_died">Server morto</string>
<string name="playback_error_unknown">Errore sconosciuto</string>
- <string name="no_media_playing_label">Nessun media in riproduzione</string>
+ <string name="no_media_playing_label">Nessun elemento multimediale in riproduzione</string>
<string name="position_default_label">00:00:00</string>
- <string name="player_buffering_msg">Buffering</string>
- <string name="playbackservice_notification_title">Riproduzione podcast in corso</string>
+ <string name="player_buffering_msg">Buffer in corso</string>
+ <string name="playbackservice_notification_title">Riproduzione del podcast in corso</string>
+ <string name="unknown_media_key">AntennaPod - Chiave dell\'elemento multimediale sconosciuta: %1$d</string>
<!--Queue operations-->
<string name="clear_queue_label">Svuota la coda</string>
<string name="undo">Undo</string>
<string name="removed_from_queue">Oggetto rimosso</string>
<string name="move_to_top_label">Sposta all\'inizio</string>
<string name="move_to_bottom_label">Sposta in fondo</string>
+ <string name="sort">Ordina</string>
+ <string name="alpha">Alfabeticamente</string>
+ <string name="date">Per data</string>
+ <string name="duration">Per durata</string>
+ <string name="ascending">In ordine crescente</string>
+ <string name="descending">In ordine decrescente</string>
<!--Flattr-->
- <string name="flattr_auth_label">Flattr sign-in</string>
+ <string name="flattr_auth_label">Accesso a Flattr</string>
<string name="flattr_auth_explanation">Premi il tasto seguente per iniziare il processo di autenticazione. Sarai trasferito alla pagina di login di flattr sul tuo browser e ti sarà richiesto di garantire ad AntennaPod il permesso di effettuare microdonazioni. Dopo la tua autorizzazione, sarai riportato alla seguente schermata in modo automatico.</string>
<string name="authenticate_label">Autenticazione</string>
- <string name="return_home_label">Ritorna alla home</string>
+ <string name="return_home_label">Ritorna alla pagina iniziale</string>
<string name="flattr_auth_success">Autenticazione avvenuta con successo! Adesso puoi microdonare con flattr dall\'interno dell\'app.</string>
<string name="no_flattr_token_title">Nessun token flattr trovato</string>
+ <string name="no_flattr_token_notification_msg">Il tuo account di Flattr non sembra essere collegato ad AntennaPod. Premi qui per autenticarti.</string>
<string name="no_flattr_token_msg">Il tuo account flattr non sembra essere collegato ad AntennaPod. Potresti collegare il tuo account ad AntennaPod per utilizzare flattr dall\'app oppure puoi visitare il sito per utilizzare flattr direttamente da lì.</string>
- <string name="authenticate_now_label">Autenticazione</string>
- <string name="action_forbidden_title">Azione inibita</string>
+ <string name="authenticate_now_label">Autenticati</string>
+ <string name="action_forbidden_title">Azione proibita</string>
<string name="action_forbidden_msg">AntennaPod non ha il permesso di effettuare questa azione. La ragione potrebbe essere che il token di accesso di AntennaPod al tuo account è stato revocato. Puoi eseguire la re-autenticazione o altrimenti visitare il sito web.</string>
<string name="access_revoked_title">Accesso revocato</string>
<string name="access_revoked_info">Hai revocato l\'accesso di AntennaPod al tuo account. Al fine di completare il processo devi rimuovere l\'app dalla lista delle applicazioni autorizzare nelle impostazioni del tuo account sul sito di flattr.</string>
<!--Flattr-->
+ <string name="flattr_click_success">Caricata una cosa su Flattr!</string>
+ <string name="flattr_click_success_count">Caricate %d cose su Flattr!</string>
+ <string name="flattr_click_success_queue">Caricato su Flattr: %s.</string>
+ <string name="flattr_click_failure_count">È stato fallito il caricamento su Flattr di %d cose!</string>
+ <string name="flattr_click_failure">Non caricato su Flattr: %s.</string>
+ <string name="flattr_click_enqueued">La cosa verrà caricata su Flattr più tardi</string>
+ <string name="flattring_thing">Caricamento su Flattr di %s in corso</string>
<string name="flattring_label">AntennaPod sta eseguendo Flattr</string>
+ <string name="flattrd_label">AntennaPod ha caricato su Flattr</string>
+ <string name="flattrd_failed_label">Caricamento su Flattr di AntennaPod fallito</string>
+ <string name="flattr_retrieving_status">Ricezione di cose caricate su Flattr in corso</string>
<!--Variable Speed-->
- <string name="download_plugin_label">Scarica Plugin</string>
+ <string name="download_plugin_label">Scarica plugin</string>
<string name="no_playback_plugin_title">Plugin non installato</string>
+ <string name="no_playback_plugin_msg">Perché la riproduzione a velocità variabile funzioni, deve venire installata una libreria di terze parti.\n\nPremi \'Scarica un plugin\' scaricare un plugin gratuito dal Play Store.\n\nTutti i problemi rilevati con questo plugin non sono responsabilità di AntennaPod, e devono essere segnalati al proprietario del plugin.</string>
<string name="set_playback_speed_label">Velocità di riproduzione</string>
<!--Empty list labels-->
- <string name="no_items_label">Non ci sono oggetti in questa lista.</string>
+ <string name="no_items_label">Non ci sono oggetti in questo elenco.</string>
<string name="no_feeds_label">Non sei ancora abbonato a nessun feed.</string>
<!--Preferences-->
<string name="other_pref">Altro</string>
@@ -167,7 +191,10 @@
<string name="services_label">Servizi</string>
<string name="flattr_label">Flattr</string>
<string name="pref_pauseOnHeadsetDisconnect_sum">Metti in pausa quanto le cuffie vengono disconnesse</string>
+ <string name="pref_unpauseOnHeadsetReconnect_sum">Riprendi la riproduzione quando vengono riconnesse le cuffie</string>
<string name="pref_followQueue_sum">Passa al prossimo episodio in coda quanto si completa una riproduzione</string>
+ <string name="pref_auto_delete_sum">Elimina l\'episodio quando viene completata la riproduzione</string>
+ <string name="pref_auto_delete_title">Elimina automaticamente</string>
<string name="playback_pref">Riproduzione</string>
<string name="network_pref">Rete</string>
<string name="pref_autoUpdateIntervall_title">Intervallo di update</string>
@@ -176,6 +203,7 @@
<string name="pref_followQueue_title">Playback continuo</string>
<string name="pref_downloadMediaOnWifiOnly_title">Download dei media su WiFi</string>
<string name="pref_pauseOnHeadsetDisconnect_title">Disconnessione cuffie</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">Riconnetti le cuffie</string>
<string name="pref_mobileUpdate_title">Update su rete mobile</string>
<string name="pref_mobileUpdate_sum">Permetti gli aggiornamenti tramite connessione dati mobile</string>
<string name="refreshing_label">Aggiornamento</string>
@@ -186,6 +214,8 @@
<string name="pref_flattr_this_app_sum">Supporta lo sviluppo di AntennaPod tramite flattr. Grazie!</string>
<string name="pref_revokeAccess_title">Revoca l\'accesso</string>
<string name="pref_revokeAccess_sum">Revoca il permesso, a questa applicazione, di accedere al tuo account flattr.</string>
+ <string name="pref_auto_flattr_title">Flattr automatico</string>
+ <string name="pref_auto_flattr_sum">Configura l\'esecuzione automatica di Flattr</string>
<string name="user_interface_label">Interfaccia utente</string>
<string name="pref_set_theme_title">Seleziona il tema</string>
<string name="pref_set_theme_sum">Cambia l\'aspetto di AntennaPod</string>
@@ -193,6 +223,8 @@
<string name="pref_automatic_download_sum">Configura il download automatico degli episodi</string>
<string name="pref_autodl_wifi_filter_title">Abilita il filtro Wi-Fi</string>
<string name="pref_autodl_wifi_filter_sum">Abilita il download automatico solo per alcune reti Wi-Fi selezionate.</string>
+ <string name="pref_automatic_download_on_battery_title">Scarica quando la batteria non è in carica</string>
+ <string name="pref_automatic_download_on_battery_sum">Permetti il download automatico quando la batteria non è in carica</string>
<string name="pref_episode_cache_title">Cache degli episodi</string>
<string name="pref_theme_title_light">Light</string>
<string name="pref_theme_title_dark">Dark</string>
@@ -208,12 +240,22 @@
<string name="pref_gpodnet_setlogin_information_sum">Cambia le informazioni di login per il tuo account gpodder.net.</string>
<string name="pref_playback_speed_title">Velocità di riproduzione</string>
<string name="pref_playback_speed_sum">Personalizza le velocità disponibili per la riproduzione audio a velocità variabile</string>
+ <string name="pref_seek_delta_title">Tempo di ricerca</string>
+ <string name="pref_seek_delta_sum">Cerca tutti questi secondi quando si riavvolge o si va avanti velocemente</string>
<string name="pref_gpodnet_sethostname_title">Imposta l\'hostname</string>
<string name="pref_gpodnet_sethostname_use_default_host">Usa l\'host di default</string>
<string name="pref_expandNotify_title">Espandi le notifiche</string>
+ <string name="pref_expandNotify_sum">Espandi sempre le notifiche per mostrare i pulsanti di riproduzione.</string>
+ <string name="pref_persistNotify_title">Controlli di riproduzione persistenti</string>
+ <string name="pref_persistNotify_sum">Mantieni le notifiche e i controlli del blocco dello schermo quando la riproduzione è in pausa.</string>
+ <string name="pref_expand_notify_unsupport_toast">Le versioni di Android prima della 4.1 non supportano le notifiche estese.</string>
<!--Auto-Flattr dialog-->
+ <string name="auto_flattr_enable">Abilita l\'esecuzione automatica di Flattr</string>
+ <string name="auto_flattr_after_percent">Carica l\'episodio su Flattr appena è stato riprodotto al %d percento</string>
+ <string name="auto_flattr_ater_beginning">Carica l\'episodio su Flattr appena comincia la riproduzione</string>
+ <string name="auto_flattr_ater_end">Carica l\'episodio su Flattr appena finisce la riproduzione</string>
<!--Search-->
- <string name="search_hint">Ricerca per Feed o Episodi</string>
+ <string name="search_hint">Cerca dei feed o degli episodi</string>
<string name="found_in_shownotes_label">Trovato nelle note dell\'episodio</string>
<string name="found_in_chapters_label">Trovato nei capitoli</string>
<string name="search_status_no_results">Nessun risultato trovato</string>
@@ -254,6 +296,7 @@
<string name="gpodnetauth_login_title">Login</string>
<string name="gpodnetauth_login_descr">Benvenuto sul processo di login di gpodder.net. Per prima cosa, inserisci le tue informazioni di login:</string>
<string name="gpodnetauth_login_butLabel">Login</string>
+ <string name="gpodnetauth_login_register">Se non hai ancora un account, puoi crearne uno qui:\nhttps://gpodder.net/register/</string>
<string name="username_label">Username</string>
<string name="password_label">Password</string>
<string name="gpodnetauth_device_title">Scelta del dispositivo</string>
@@ -268,23 +311,23 @@
<string name="gpodnetauth_finish_title">Login effettuato!</string>
<string name="gpodnetauth_finish_descr">Congraturazioni! Il tuo account gpodder.net è stato collegato con il tuo dispositivo. Da ora AntennaPod sincronizzerà automaticamente le sottoscrizioni sul tuo dispositivo con il tuo account gpodder.net.</string>
<string name="gpodnetauth_finish_butsyncnow">Avvia la sincronizzazione</string>
- <string name="gpodnetauth_finish_butgomainscreen">Schermata principale</string>
- <string name="gpodnetsync_auth_error_title">gpodder.net errore di autenticazione</string>
- <string name="gpodnetsync_auth_error_descr">Utente o password errata</string>
+ <string name="gpodnetauth_finish_butgomainscreen">Vai alla schermata principale</string>
+ <string name="gpodnetsync_auth_error_title">errore di autenticazione su gpodder.net</string>
+ <string name="gpodnetsync_auth_error_descr">Nome utente o password errati</string>
<string name="gpodnetsync_error_title">gpodder.net errore di sincronizzazione</string>
<string name="gpodnetsync_error_descr">Rilevato un errore in fase di sincronizzazione:\u0020</string>
<!--Directory chooser-->
- <string name="selected_folder_label">Seleziona la directory:</string>
- <string name="create_folder_label">Crea una directory</string>
+ <string name="selected_folder_label">Seleziona la cartella:</string>
+ <string name="create_folder_label">Crea una cartella</string>
<string name="choose_data_directory">Scegli la directory per i dati</string>
<string name="create_folder_msg">Crea una nuova directory con nome \"%1$s\"?</string>
<string name="create_folder_success">Crea una nuova directory</string>
<string name="create_folder_error_no_write_access">Impossibile scrivere in questa directory</string>
- <string name="create_folder_error_already_exists">La directory esiste già</string>
- <string name="create_folder_error">Impossibile creare la directory</string>
- <string name="folder_not_empty_dialog_title">La directory non è vuota</string>
- <string name="folder_not_empty_dialog_msg">La directory che hai selezionato non è vuota. I download dei media e altri file saranno creati in questa directory. Continuare?</string>
- <string name="set_to_default_folder">Scegli la directory predefinita</string>
+ <string name="create_folder_error_already_exists">La cartella esiste già</string>
+ <string name="create_folder_error">Non è stato possibile creare la cartella</string>
+ <string name="folder_not_empty_dialog_title">La cartella non è vuota</string>
+ <string name="folder_not_empty_dialog_msg">La cartella che hai selezionato non è vuota. I download dei media e altri file saranno creati in questa cartella. Continuare?</string>
+ <string name="set_to_default_folder">Scegli la cartella predefinita</string>
<string name="pref_pausePlaybackForFocusLoss_sum">Sospendi la riproduzione invece di abbassare il volume quando un\'altra app emette un suono</string>
<string name="pref_pausePlaybackForFocusLoss_title">Pausa su interruzione</string>
<!--Online feed view-->
@@ -299,17 +342,20 @@
<string name="fast_forward_label">Avanti veloce</string>
<string name="media_type_audio_label">Audio</string>
<string name="media_type_video_label">Video</string>
- <string name="navigate_upwards_label">Naviga su</string>
- <string name="butAction_label">Più azioni</string>
- <string name="status_playing_label">L\'episodio è in corso di ripoduzione</string>
- <string name="status_downloading_label">L\'episodio sta per essere scaricato</string>
+ <string name="navigate_upwards_label">Naviga verso l\'alto</string>
+ <string name="butAction_label">Ulteriori azioni</string>
+ <string name="status_playing_label">L\'episodio è in riproduzione</string>
+ <string name="status_downloading_label">L\'episodio sta venendo scaricato</string>
<string name="status_downloaded_label">L\'episodio è stato scaricato</string>
<string name="status_unread_label">L\'oggetto è nuovo</string>
<string name="in_queue_label">L\'episodio è in coda</string>
- <string name="new_episodes_count_label">Numero dei nuovi episodi</string>
+ <string name="new_episodes_count_label">Numero di episodi nuovi</string>
+ <string name="in_progress_episodes_count_label">Numero di episodi che hai iniziato ad ascoltare</string>
<string name="drag_handle_content_description">Trascina per cambiare la posizione di questo oggetto</string>
<string name="load_next_page_label">Carica la pagina successiva</string>
<!--Feed information screen-->
<string name="authentication_label">Autenticazione</string>
+ <string name="authentication_descr">Cambia il tuo nome utente e la tua password per questo podcast e i suoi episodi.</string>
<!--AntennaPodSP-->
+ <string name="sp_apps_importing_feeds_msg">Importazione di sottoscrizioni da applicazioni monouso in corso...</string>
</resources>
diff --git a/core/src/main/res/values-iw-rIL/strings.xml b/core/src/main/res/values-iw-rIL/strings.xml
index 78096eb5a..f014954e4 100644
--- a/core/src/main/res/values-iw-rIL/strings.xml
+++ b/core/src/main/res/values-iw-rIL/strings.xml
@@ -144,6 +144,12 @@
<string name="removed_from_queue">הסר פריט</string>
<string name="move_to_top_label">העבר למעלה</string>
<string name="move_to_bottom_label">העבר למטה</string>
+ <string name="sort">מיין</string>
+ <string name="alpha">בסדר אלפביתי</string>
+ <string name="date">תאריך</string>
+ <string name="duration">משך</string>
+ <string name="ascending">בסדר עולה</string>
+ <string name="descending">בסדר יורד</string>
<!--Flattr-->
<string name="flattr_auth_label">כניסה ל-Fattr</string>
<string name="flattr_auth_explanation">לחץ על הכפתור למטה כדי להתחיל את תהליך האימות. אתה תועבר למסך כניסת flattr בדפדפן שלך ותתבקש לתת לאנטנה-פוד רשות לתרום באמצעות flattr. לאחר שקבלת אישור, תוכל לחזור למסך זה באופן אוטומטי.</string>
@@ -186,7 +192,10 @@
<string name="services_label">שירותים</string>
<string name="flattr_label">Flattr</string>
<string name="pref_pauseOnHeadsetDisconnect_sum">השהה השמעה בניתוק האוזניות </string>
+ <string name="pref_unpauseOnHeadsetReconnect_sum">המשך את הניגון כשהאוזניות מחוברות מחדש</string>
<string name="pref_followQueue_sum">עבור לפריט הבא בתור כאשר הניגון מסתיים</string>
+ <string name="pref_auto_delete_sum">מחק פרק כהניגון מסתיים</string>
+ <string name="pref_auto_delete_title">מחיקה אוטומטית</string>
<string name="playback_pref">ניגון</string>
<string name="network_pref">רשת</string>
<string name="pref_autoUpdateIntervall_title">זמן בין עידכונים</string>
@@ -195,6 +204,7 @@
<string name="pref_followQueue_title">ניגון מתמשך</string>
<string name="pref_downloadMediaOnWifiOnly_title">הורדת מדיה דרך אינטרנט אלחוטי</string>
<string name="pref_pauseOnHeadsetDisconnect_title">ניתוק אוזניות</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">חיבור אוזניות מחדש</string>
<string name="pref_mobileUpdate_title">עידכון דרך רשת סלולרית</string>
<string name="pref_mobileUpdate_sum">אפשר עידכונים דרך רשת סלולרית</string>
<string name="refreshing_label">מרענן</string>
@@ -214,6 +224,8 @@
<string name="pref_automatic_download_sum">הגדר הורדה אטומטית של פרקים.</string>
<string name="pref_autodl_wifi_filter_title">אפשר סינון אינטרנט אלחוטי</string>
<string name="pref_autodl_wifi_filter_sum">אפשר הורדה אוטומטית דרך רשתות אלחוטייות נבחרות.</string>
+ <string name="pref_automatic_download_on_battery_title">הורדה כשלא טוען</string>
+ <string name="pref_automatic_download_on_battery_sum">אפשר הורדה אוטומטית כשהסוללה אינה נטענת</string>
<string name="pref_episode_cache_title">מטמון פרקים</string>
<string name="pref_theme_title_light">בהיר</string>
<string name="pref_theme_title_dark">כהה</string>
diff --git a/core/src/main/res/values-ja/strings.xml b/core/src/main/res/values-ja/strings.xml
index fd5039e33..f17e1cf61 100644
--- a/core/src/main/res/values-ja/strings.xml
+++ b/core/src/main/res/values-ja/strings.xml
@@ -144,6 +144,12 @@
<string name="removed_from_queue">アイテムを削除しました</string>
<string name="move_to_top_label">先頭に移動</string>
<string name="move_to_bottom_label">最後に移動</string>
+ <string name="sort">並べ替え</string>
+ <string name="alpha">アルファベット順</string>
+ <string name="date">日付</string>
+ <string name="duration">継続時間</string>
+ <string name="ascending">昇順</string>
+ <string name="descending">降順</string>
<!--Flattr-->
<string name="flattr_auth_label">Flattrにサインイン</string>
<string name="flattr_auth_explanation">認証処理を開始するには、下のボタンを押します。お使いのブラウザでflattrのログイン画面に転送され、AntennaPodにflattrする許可を与えるように求められます。あなたが許可を与えた後、自動的にこの画面に戻ります。</string>
@@ -184,18 +190,22 @@
<string name="queue_label">キュー</string>
<string name="services_label">サービス</string>
<string name="flattr_label">Flattr</string>
- <string name="pref_pauseOnHeadsetDisconnect_sum">ヘッドフォンの接続が切断された時、再生を一時停止</string>
- <string name="pref_followQueue_sum">再生が完了した時に次のキューのアイテムに移動</string>
+ <string name="pref_pauseOnHeadsetDisconnect_sum">ヘッドフォンの接続が切断された時、再生を一時停止します</string>
+ <string name="pref_unpauseOnHeadsetReconnect_sum">ヘッドフォンが再接続された時に再生を再開します</string>
+ <string name="pref_followQueue_sum">再生が完了した時に次のキューのアイテムに移動します</string>
+ <string name="pref_auto_delete_sum">再生が完了した時にエピソードを削除します</string>
+ <string name="pref_auto_delete_title">自動削除</string>
<string name="playback_pref">再生</string>
<string name="network_pref">ネットワーク</string>
<string name="pref_autoUpdateIntervall_title">更新間隔</string>
<string name="pref_autoUpdateIntervall_sum">フィードが自動的に更新される間隔を指定するか、または無効にしてください</string>
- <string name="pref_downloadMediaOnWifiOnly_sum">WiFi接続時のみメディアファイルをダウンロード</string>
+ <string name="pref_downloadMediaOnWifiOnly_sum">WiFi接続時のみメディアファイルをダウンロードします</string>
<string name="pref_followQueue_title">連続再生</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFiメディアダウンロード</string>
<string name="pref_pauseOnHeadsetDisconnect_title">ヘッドフォン切断</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">ヘッドフォン再接続</string>
<string name="pref_mobileUpdate_title">モバイル更新</string>
- <string name="pref_mobileUpdate_sum">モバイルデータ接続時に更新を許可する</string>
+ <string name="pref_mobileUpdate_sum">モバイルデータ接続時に更新を許可します</string>
<string name="refreshing_label">更新中</string>
<string name="flattr_settings_label">Flattr設定</string>
<string name="pref_flattr_auth_title">Flattrにサインイン</string>
@@ -213,6 +223,8 @@
<string name="pref_automatic_download_sum">エピソードの自動ダウンロードを構成します。</string>
<string name="pref_autodl_wifi_filter_title">Wi-Fiフィルターを有効にする</string>
<string name="pref_autodl_wifi_filter_sum">選択したWi-Fiネットワークに対してのみ自動ダウンロードを許可します。</string>
+ <string name="pref_automatic_download_on_battery_title">充電中以外の時にダウンロード</string>
+ <string name="pref_automatic_download_on_battery_sum">バッテリーを充電していない時に自動ダウンロードを許可します</string>
<string name="pref_episode_cache_title">エピソードキャッシュ</string>
<string name="pref_theme_title_light">ライト</string>
<string name="pref_theme_title_dark">ダーク</string>
diff --git a/core/src/main/res/values-ko/strings.xml b/core/src/main/res/values-ko/strings.xml
index a29de1582..b4fa23711 100644
--- a/core/src/main/res/values-ko/strings.xml
+++ b/core/src/main/res/values-ko/strings.xml
@@ -74,6 +74,7 @@
<string name="share_source_label">피드 링크 공유</string>
<string name="feed_delete_confirmation_msg">이 피드와 이 피드에서 다운로드한 모든 에피소드를 삭제하시려면 확인을 누르십시오.</string>
<string name="feed_remover_msg">피드 삭제하는 중</string>
+ <string name="load_complete_feed">전체 피드 새로고침</string>
<!--actions on feeditems-->
<string name="download_label">다운로드</string>
<string name="play_label">재생</string>
@@ -143,6 +144,12 @@
<string name="removed_from_queue">항목을 제거했습니다</string>
<string name="move_to_top_label">맨 위로 이동</string>
<string name="move_to_bottom_label">맨 아래로 이동</string>
+ <string name="sort">정렬</string>
+ <string name="alpha">사전순</string>
+ <string name="date">날짜</string>
+ <string name="duration">기간</string>
+ <string name="ascending">오름차순</string>
+ <string name="descending">내림차순</string>
<!--Flattr-->
<string name="flattr_auth_label">Flattr 로그인</string>
<string name="flattr_auth_explanation">인증 절차를 시작하려면 아래 버튼을 누르십시오. 브라우저의 Flattr 로그인 화면으로 이동하고, 안테나팟에 Flattr를 사용을 허락 여부를 물어봅니다. 허락을 하면 자동으로 이 화면으로 돌아옵니다.</string>
@@ -184,7 +191,10 @@
<string name="services_label">서비스</string>
<string name="flattr_label">Flattr</string>
<string name="pref_pauseOnHeadsetDisconnect_sum">헤드폰의 연결이 끊어졌을 때 재생을 일시 중지</string>
+ <string name="pref_unpauseOnHeadsetReconnect_sum">헤드폰 다시 연결할 때 재생 계속</string>
<string name="pref_followQueue_sum">재생을 마쳤을 때 다음 대기열로 이동</string>
+ <string name="pref_auto_delete_sum">재생이 끝나면 에피소드 삭제</string>
+ <string name="pref_auto_delete_title">자동 삭제</string>
<string name="playback_pref">재생</string>
<string name="network_pref">네트워크</string>
<string name="pref_autoUpdateIntervall_title">업데이트 주기</string>
@@ -193,6 +203,7 @@
<string name="pref_followQueue_title">연속 재생</string>
<string name="pref_downloadMediaOnWifiOnly_title">Wi-Fi 미디어 다운로드</string>
<string name="pref_pauseOnHeadsetDisconnect_title">헤드폰 연결 끊김</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">헤드폰 재연결</string>
<string name="pref_mobileUpdate_title">휴대전화망 업데이트</string>
<string name="pref_mobileUpdate_sum">휴대전화 데이터 연결을 통해 업데이트 허용</string>
<string name="refreshing_label">새로 고치는 중</string>
@@ -212,6 +223,8 @@
<string name="pref_automatic_download_sum">에피소드 자동 다운로드를 설정합니다.</string>
<string name="pref_autodl_wifi_filter_title">Wi-Fi 필터 사용</string>
<string name="pref_autodl_wifi_filter_sum">선택한 Wi-Fi 네트워크에 대해서만 자동 다운로드를 허용합니다.</string>
+ <string name="pref_automatic_download_on_battery_title">충전하지 않을 때 다운로드</string>
+ <string name="pref_automatic_download_on_battery_sum">배터리 충전 중이 아닐 때 자동 다운로드 허용</string>
<string name="pref_episode_cache_title">에피소드 임시 저장</string>
<string name="pref_theme_title_light">밝게</string>
<string name="pref_theme_title_dark">어둡게</string>
@@ -339,6 +352,7 @@
<string name="new_episodes_count_label">새 에피소드 개수</string>
<string name="in_progress_episodes_count_label">듣기를 시작한 에피소드 개수</string>
<string name="drag_handle_content_description">이 항목의 위치를 바꾸려면 드래그하십시오</string>
+ <string name="load_next_page_label">다음 페이지 읽기</string>
<!--Feed information screen-->
<string name="authentication_label">인증</string>
<string name="authentication_descr">이 팟캐스트와 에피소드에 대한 사용자 이름과 비밀번호를 바꿉니다.</string>
diff --git a/core/src/main/res/values-pl-rPL/strings.xml b/core/src/main/res/values-pl-rPL/strings.xml
index 34ef6e04c..bf9a640ce 100644
--- a/core/src/main/res/values-pl-rPL/strings.xml
+++ b/core/src/main/res/values-pl-rPL/strings.xml
@@ -144,6 +144,12 @@
<string name="removed_from_queue">Element usunięty</string>
<string name="move_to_top_label">Przesuń na górę</string>
<string name="move_to_bottom_label">Przesuń na dół</string>
+ <string name="sort">Sortuj</string>
+ <string name="alpha">Alfabetycznie</string>
+ <string name="date">Według daty</string>
+ <string name="duration">Według długości</string>
+ <string name="ascending">Rosnąco</string>
+ <string name="descending">Malejąco</string>
<!--Flattr-->
<string name="flattr_auth_label">Logowanie do Flattr</string>
<string name="flattr_auth_explanation">Naciśnij przycisk poniżej by zacząć proces autoryzacji. Zostaniesz przekierowany na stronę logowania do flattr w przeglądarce i zostaniesz poproszony o przyznanie zezwolenia AntennaPod-owi na flattr-owanie. Po daniu zezwolenia powrócisz do tej strony automatycznie.</string>
@@ -185,7 +191,10 @@
<string name="services_label">Usługi</string>
<string name="flattr_label">Flattr</string>
<string name="pref_pauseOnHeadsetDisconnect_sum">Wstrzymaj odtwarzanie kiedy słuchawki zostaną odłączone</string>
+ <string name="pref_unpauseOnHeadsetReconnect_sum">Wznów odtwarzanie kiedy słuchawki zostaną podłączone ponownie</string>
<string name="pref_followQueue_sum">Przeskocz do następnego elementu kolejki po zakończeniu odtwarzania</string>
+ <string name="pref_auto_delete_sum">Usuń odcinek kiedy jego odtwarzanie zostanie zakończone</string>
+ <string name="pref_auto_delete_title">Automatyczne usuwanie</string>
<string name="playback_pref">Odtwarzanie</string>
<string name="network_pref">Sieć</string>
<string name="pref_autoUpdateIntervall_title">Częstość aktualizacji</string>
@@ -194,6 +203,7 @@
<string name="pref_followQueue_title">Odtwarzanie ciągłe</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFi media pobrane</string>
<string name="pref_pauseOnHeadsetDisconnect_title">Słuchawki odłączone</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">Słuchawki podłączone ponownie</string>
<string name="pref_mobileUpdate_title">Aktualizacje mobilne</string>
<string name="pref_mobileUpdate_sum">Zezwól na aktualizacje poprzez sieć komórkową</string>
<string name="refreshing_label">Odświeżanie</string>
diff --git a/core/src/main/res/values-pt/strings.xml b/core/src/main/res/values-pt/strings.xml
index 3a0f300e6..7df1b35f4 100644
--- a/core/src/main/res/values-pt/strings.xml
+++ b/core/src/main/res/values-pt/strings.xml
@@ -144,6 +144,12 @@
<string name="removed_from_queue">Item removido</string>
<string name="move_to_top_label">Mover para o topo</string>
<string name="move_to_bottom_label">Mover para o fundo</string>
+ <string name="sort">Organização</string>
+ <string name="alpha">Alfabética</string>
+ <string name="date">Data</string>
+ <string name="duration">Duração</string>
+ <string name="ascending">Crescente</string>
+ <string name="descending">Decrescente</string>
<!--Flattr-->
<string name="flattr_auth_label">Sessão Flattr</string>
<string name="flattr_auth_explanation">Prima o botão abaixo para iniciar a autenticação. O seu navegador web abrirá o ecrã da sessão flattr e ser-lhe-á solicitada a permissão para o AntennaPod efetuar as alterações. Após ser dada a permissão, voltará novamente a este ecrã.</string>
@@ -185,7 +191,10 @@
<string name="services_label">Serviços</string>
<string name="flattr_label">Flattr</string>
<string name="pref_pauseOnHeadsetDisconnect_sum">Parar reprodução ao remover os auscultadores</string>
+ <string name="pref_unpauseOnHeadsetReconnect_sum">Continuar reprodução ao ligar os auscultadores</string>
<string name="pref_followQueue_sum">Ir para a faixa seguinte ao terminar a reprodução</string>
+ <string name="pref_auto_delete_sum">Eliminar episódio ao terminar a reprodução</string>
+ <string name="pref_auto_delete_title">Eliminação automática</string>
<string name="playback_pref">Reprodução</string>
<string name="network_pref">Rede</string>
<string name="pref_autoUpdateIntervall_title">Intervalo entre atualizações</string>
@@ -194,6 +203,7 @@
<string name="pref_followQueue_title">Reprodução contínua</string>
<string name="pref_downloadMediaOnWifiOnly_title">Transferência Wi-Fi</string>
<string name="pref_pauseOnHeadsetDisconnect_title">Auscultadores removidos</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">Auscultadores ligados</string>
<string name="pref_mobileUpdate_title">Atualizações móveis</string>
<string name="pref_mobileUpdate_sum">Permitir atualizações através da rede de dados</string>
<string name="refreshing_label">A atualizar</string>
@@ -213,6 +223,8 @@
<string name="pref_automatic_download_sum">Configure a transferência automática dos episódios.</string>
<string name="pref_autodl_wifi_filter_title">Ativar filtro Wi-Fi</string>
<string name="pref_autodl_wifi_filter_sum">Apenas permitir transferências automáticas através de redes sem fios.</string>
+ <string name="pref_automatic_download_on_battery_title">Transferência se não estiver a carregar</string>
+ <string name="pref_automatic_download_on_battery_sum">Permitir transferência automática se a bateria não estiver a ser carregada</string>
<string name="pref_episode_cache_title">Cache de episódios</string>
<string name="pref_theme_title_light">Claro</string>
<string name="pref_theme_title_dark">Escuro</string>
diff --git a/core/src/main/res/values-sv-rSE/strings.xml b/core/src/main/res/values-sv-rSE/strings.xml
index 187008426..888f08a1c 100644
--- a/core/src/main/res/values-sv-rSE/strings.xml
+++ b/core/src/main/res/values-sv-rSE/strings.xml
@@ -144,6 +144,12 @@
<string name="removed_from_queue">Föremålet avlägsnades</string>
<string name="move_to_top_label">Flytta längst upp</string>
<string name="move_to_bottom_label">Flytta längst ned</string>
+ <string name="sort">Sortering</string>
+ <string name="alpha">Alfabetiskt</string>
+ <string name="date">Datum</string>
+ <string name="duration">Längd</string>
+ <string name="ascending">Stigande</string>
+ <string name="descending">Fallande</string>
<!--Flattr-->
<string name="flattr_auth_label">Flattr inloggning</string>
<string name="flattr_auth_explanation">Tryck på knappen nedan för att starta autentiseringen. Du kommer att vidarebefordras till Flattrs inloggningsskärm i din webbläsare och uppmanas att ge AntennaPod tillstånd att Flattra saker. Efter att du har gett tillstånd, kommer du automatiskt tillbaka till den här skärmen.</string>
@@ -185,7 +191,10 @@
<string name="services_label">Tjänster</string>
<string name="flattr_label">Flattr</string>
<string name="pref_pauseOnHeadsetDisconnect_sum">Pausa uppspelningen när hörlurarna bortkopplas</string>
+ <string name="pref_unpauseOnHeadsetReconnect_sum">Fortsätt uppspelningen när hörlurarna återansluts</string>
<string name="pref_followQueue_sum">Hoppa till nästa i kön när uppspelningen är klar</string>
+ <string name="pref_auto_delete_sum">Ta bort episoden när uppspelningen är klar</string>
+ <string name="pref_auto_delete_title">Automatisk borttagning</string>
<string name="playback_pref">Uppspelning</string>
<string name="network_pref">Nätverk </string>
<string name="pref_autoUpdateIntervall_title">Uppdateringsintervall</string>
@@ -194,6 +203,7 @@
<string name="pref_followQueue_title">Kontinuerlig uppspelning</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFi nedladdning</string>
<string name="pref_pauseOnHeadsetDisconnect_title">Hörlurar bortkopplade</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">Hörlurar återanslutna</string>
<string name="pref_mobileUpdate_title">Mobila uppdateringar</string>
<string name="pref_mobileUpdate_sum">Tillåt uppdateringar via mobil dataanslutning</string>
<string name="refreshing_label">Uppdaterar</string>
@@ -213,6 +223,8 @@
<string name="pref_automatic_download_sum">Konfigurera automatisk nedladdning av episoder.</string>
<string name="pref_autodl_wifi_filter_title">Aktivera WiFi filtrering</string>
<string name="pref_autodl_wifi_filter_sum">Tillåt automatisk nedladdning endast för utvalda WiFi-nätverk.</string>
+ <string name="pref_automatic_download_on_battery_title">Nedladdning vid batteridrift</string>
+ <string name="pref_automatic_download_on_battery_sum">Tillåt automatisk nedladdning när batteriet inte laddas</string>
<string name="pref_episode_cache_title">Avsnittscache</string>
<string name="pref_theme_title_light">Ljust</string>
<string name="pref_theme_title_dark">Mörkt</string>
@@ -228,7 +240,7 @@
<string name="pref_gpodnet_setlogin_information_sum">Ändra inloggningsinformationen för ditt gpodder.net konto.</string>
<string name="pref_playback_speed_title">Uppspelningshastigheter</string>
<string name="pref_playback_speed_sum">Anpassa de tillgängliga hastigheterna för variabel uppspelningshastighet.</string>
- <string name="pref_seek_delta_title">Söktid</string>
+ <string name="pref_seek_delta_title">Söklängd</string>
<string name="pref_seek_delta_sum">Sök så här många sekunder vid snabbspolning bakåt eller framåt</string>
<string name="pref_gpodnet_sethostname_title">Sätt värdnamn</string>
<string name="pref_gpodnet_sethostname_use_default_host">Använd standardvärden</string>
diff --git a/core/src/main/res/values-uk-rUA/strings.xml b/core/src/main/res/values-uk-rUA/strings.xml
index 966dac3f9..08ce56f26 100644
--- a/core/src/main/res/values-uk-rUA/strings.xml
+++ b/core/src/main/res/values-uk-rUA/strings.xml
@@ -28,9 +28,9 @@
<string name="drawer_close">Сховати меню</string>
<!--Webview actions-->
<string name="open_in_browser_label">Відкрити в браузері</string>
- <string name="copy_url_label">Копія URL</string>
+ <string name="copy_url_label">Копіювати URL</string>
<string name="share_url_label">Поділитися URL</string>
- <string name="copied_url_msg">Копіювати URL в clipboard</string>
+ <string name="copied_url_msg">URL скопійовано в буфер</string>
<string name="go_to_position_label">До цієї позиції</string>
<!--Playback history-->
<string name="clear_history_label">Забути</string>
@@ -66,8 +66,8 @@
<string name="podcastdirectories_descr">В каталозі gpodder.net можливий пошук за назвою, категорією або популярністю.</string>
<string name="browse_gpoddernet_label">Переглянути gpodder.net</string>
<!--Actions on feeds-->
- <string name="mark_all_read_label">Все прочитано</string>
- <string name="mark_all_read_msg">Позначити всі епізоди як переглянуті</string>
+ <string name="mark_all_read_label">Позначити всі як переглянуті</string>
+ <string name="mark_all_read_msg">Позначено всі епізоди як переглянуті</string>
<string name="show_info_label">Інформація</string>
<string name="remove_feed_label">Видалити подкаст</string>
<string name="share_link_label">Поділитися URL сайту</string>
@@ -83,8 +83,8 @@
<string name="stream_label">Прослухати без завантаження</string>
<string name="remove_label">Видалити</string>
<string name="remove_episode_lable">Видалити епізод</string>
- <string name="mark_read_label">Прочитано</string>
- <string name="mark_unread_label">Непрочитано</string>
+ <string name="mark_read_label">Позначити як переглянутий</string>
+ <string name="mark_unread_label">Позначити як не переглянутий</string>
<string name="add_to_queue_label">Додати до черги</string>
<string name="remove_from_queue_label">Видалити з черги</string>
<string name="visit_website_label">Відкрити сайт</string>
@@ -103,7 +103,7 @@
<string name="download_error_http_data_error">Помилка HTTP</string>
<string name="download_error_error_unknown">Щось трапилось</string>
<string name="download_error_parser_exception">Помилка парсера</string>
- <string name="download_error_unsupported_type">Непідтримую такий канал</string>
+ <string name="download_error_unsupported_type">Не підтримую канали такого типа</string>
<string name="download_error_connection_error">Помилка з\'єднання</string>
<string name="download_error_unknown_host">Невідомий host</string>
<string name="download_error_unauthorized">Помилка автентифікації</string>
@@ -144,6 +144,12 @@
<string name="removed_from_queue">Видалено</string>
<string name="move_to_top_label">Догори</string>
<string name="move_to_bottom_label">Донизу</string>
+ <string name="sort">Впорядкувати</string>
+ <string name="alpha">За абеткою</string>
+ <string name="date">За датою</string>
+ <string name="duration">За тривалістю</string>
+ <string name="ascending">За зростанням</string>
+ <string name="descending">За спаданням</string>
<!--Flattr-->
<string name="flattr_auth_label">Увійти до Flattr</string>
<string name="flattr_auth_explanation">Нажміть цю кнопку для початку авторізації. Буде відкрито flattr в браузері, буде запит на дозвіл доступу Antennapod до flattr. Після надання доступу ви повернетесь до цього екрану автоматично</string>
@@ -159,12 +165,12 @@
<string name="access_revoked_title">Доступ відкликано</string>
<string name="access_revoked_info">Ви відкликали доступ AntennaPod до облікового запису. Для закінчення процессу вам потрібно видалити додаток з затвержденного списку в вашому облікову запису на сайті flattr</string>
<!--Flattr-->
- <string name="flattr_click_success">Flattr\'ed one thing!</string>
+ <string name="flattr_click_success">Підтримано через Flattr!</string>
<string name="flattr_click_success_count">Flattr\'ed %d things!</string>
- <string name="flattr_click_success_queue">Flattr\'ed: %s.</string>
+ <string name="flattr_click_success_queue">Підтримано через Flattr: %s.</string>
<string name="flattr_click_failure_count">Failed to flattr %d things!</string>
- <string name="flattr_click_failure">Not flattr\'ed: %s.</string>
- <string name="flattr_click_enqueued">Thing will be flattr\'ed later</string>
+ <string name="flattr_click_failure">Не підтримано через flattr: %s.</string>
+ <string name="flattr_click_enqueued">Буде підтримано через flattr пізніше</string>
<string name="flattring_thing">Flattring %s</string>
<string name="flattring_label">AntennaPod is flattring</string>
<string name="flattrd_label">AntennaPod has flattr\'ed</string>
@@ -176,43 +182,49 @@
<string name="no_playback_plugin_msg">Для керування швидкістю програвання потрібно встановити додаток.\n\nНатисніть \"Завантажити додаток\" для завантаження безкоштовного додатку з Play Store\n\nЯкщо при використанні plugin виникнуть будь які проблеми - це відповідальність автора додатка, а не автора AntennaPod.</string>
<string name="set_playback_speed_label">Швидкість програвання</string>
<!--Empty list labels-->
- <string name="no_items_label">Нічного в цьому списку</string>
+ <string name="no_items_label">Нічого в цьому списку</string>
<string name="no_feeds_label">Немає підписаних каналів </string>
<!--Preferences-->
<string name="other_pref">Інше</string>
- <string name="about_pref">О</string>
+ <string name="about_pref">Про програму</string>
<string name="queue_label">Черга</string>
<string name="services_label">Сервіси</string>
<string name="flattr_label">Flattr</string>
<string name="pref_pauseOnHeadsetDisconnect_sum">Зупинятись коли навушники витягнуті</string>
- <string name="pref_followQueue_sum">До наступної черги коли дограє до кінця</string>
- <string name="playback_pref">Грає</string>
+ <string name="pref_unpauseOnHeadsetReconnect_sum">Поновити відтворення коли навушники повторно під’єднано</string>
+ <string name="pref_followQueue_sum">Перейти до наступного епізода в черзі коли поточний закінчено</string>
+ <string name="pref_auto_delete_sum">Видалити епізод після повного відтворення</string>
+ <string name="pref_auto_delete_title">Автовидалення</string>
+ <string name="playback_pref">Відтворення</string>
<string name="network_pref">Мережа</string>
- <string name="pref_autoUpdateIntervall_title">Коли оновлювати</string>
- <string name="pref_autoUpdateIntervall_sum">Визначати як час для автооновлювання або відключити автооновлення</string>
+ <string name="pref_autoUpdateIntervall_title">Частота оновлень</string>
+ <string name="pref_autoUpdateIntervall_sum">Визначити інтервал часу для автооновлювання або відключити автооновлення</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Завантажувати тільки через Wifi</string>
<string name="pref_followQueue_title">Грати безперервно</string>
<string name="pref_downloadMediaOnWifiOnly_title">Завантаження через Wifi</string>
<string name="pref_pauseOnHeadsetDisconnect_title">Навушники витягнуті</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">Повторне під’єднання навушників</string>
<string name="pref_mobileUpdate_title">Мобільне оновлення</string>
<string name="pref_mobileUpdate_sum">Дозволити оновлення через оператора зв\'язку</string>
<string name="refreshing_label">Оновлення</string>
<string name="flattr_settings_label">Налаштування Flattr</string>
<string name="pref_flattr_auth_title">Увійти до Flattr</string>
- <string name="pref_flattr_auth_sum">Увійти в облікову flattr в flattr things напряму з додатку</string>
+ <string name="pref_flattr_auth_sum">Увійти в облікову flattr для підтримки авторів напряму з додатку</string>
<string name="pref_flattr_this_app_title">Flattr цій додаток</string>
<string name="pref_flattr_this_app_sum">Підтримайте розробку AntennaPod за допомогою flattr. Дякую!</string>
<string name="pref_revokeAccess_title">Відкликати доступ</string>
<string name="pref_revokeAccess_sum">Відкликати дозвіл на доступ до вашого flattr з цього додатку</string>
<string name="pref_auto_flattr_title">Automatic Flattr</string>
<string name="pref_auto_flattr_sum">Налаштування автоматичного заохочення авторів через сервіс flattr</string>
- <string name="user_interface_label">Зовнішній вид</string>
+ <string name="user_interface_label">Вигляд</string>
<string name="pref_set_theme_title">Обрати тему</string>
- <string name="pref_set_theme_sum">Змінити появу AntennaPod</string>
+ <string name="pref_set_theme_sum">Змінити вигляд AntennaPod</string>
<string name="pref_automatic_download_title">Автоматичне завантаження</string>
<string name="pref_automatic_download_sum">Налаштування автоматичного завантаження епізодів</string>
<string name="pref_autodl_wifi_filter_title">Увімкнути фільтр Wi-Fi</string>
<string name="pref_autodl_wifi_filter_sum">Дозволити автоматичне завантаження тільки в цих Wi-Fi мережах</string>
+ <string name="pref_automatic_download_on_battery_title">Завантаження без зарядного пристрою</string>
+ <string name="pref_automatic_download_on_battery_sum">Дозволити завантаження коли зарядний пристрій не підключено</string>
<string name="pref_episode_cache_title">Кеш епізодів</string>
<string name="pref_theme_title_light">Світла</string>
<string name="pref_theme_title_dark">Темна</string>
@@ -222,10 +234,10 @@
<string name="pref_update_interval_hours_manual">Інструкція</string>
<string name="pref_gpodnet_authenticate_title">Логін</string>
<string name="pref_gpodnet_authenticate_sum">Увійти до свого облікового запису gpodder.net для сінхронізації ваших каналів</string>
- <string name="pref_gpodnet_logout_title">Виход</string>
+ <string name="pref_gpodnet_logout_title">Вихід</string>
<string name="pref_gpodnet_logout_toast">Успішно закрили доступ</string>
<string name="pref_gpodnet_setlogin_information_title">Змінити інформацію для входу</string>
- <string name="pref_gpodnet_setlogin_information_sum">Змінити вашу інформацію для вашего gpodder.net облікового запису</string>
+ <string name="pref_gpodnet_setlogin_information_sum">Змінити інформацію щодо облікового запису gpodder.net</string>
<string name="pref_playback_speed_title">Швидкість програвання</string>
<string name="pref_playback_speed_sum">Налаштування швідкості доступно для змінної швидкості програвання</string>
<string name="pref_seek_delta_title">Час перемотки</string>
@@ -311,9 +323,9 @@
<string name="create_folder_msg">Створити папку з ім\'ям \"%1$s\"?</string>
<string name="create_folder_success">Створена нова папка</string>
<string name="create_folder_error_no_write_access">Не можу записати в цю папку</string>
- <string name="create_folder_error_already_exists">Папка вже є</string>
+ <string name="create_folder_error_already_exists">Папка вже існує</string>
<string name="create_folder_error">Не можу создати папку</string>
- <string name="folder_not_empty_dialog_title">В папці щось є</string>
+ <string name="folder_not_empty_dialog_title">Папка не є пустою</string>
<string name="folder_not_empty_dialog_msg">В папці щось є. Всі завантаження зберігаються в цю папку. Все рівно продовжувати?</string>
<string name="set_to_default_folder">Обрати папку по замовчанню</string>
<string name="pref_pausePlaybackForFocusLoss_sum">Призупиняти програвання замість зниження гучності коли інша програма хоче програти звук</string>
diff --git a/core/src/main/res/values/attrs.xml b/core/src/main/res/values/attrs.xml
index c46a2118f..f36119c8d 100644
--- a/core/src/main/res/values/attrs.xml
+++ b/core/src/main/res/values/attrs.xml
@@ -35,6 +35,7 @@
<attr name="av_pause_big" format="reference"/>
<attr name="av_ff_big" format="reference"/>
<attr name="av_rew_big" format="reference"/>
+ <attr name="ic_settings" format="reference"/>
<!-- Used in itemdescription -->
<attr name="non_transparent_background" format="reference"/>
diff --git a/core/src/main/res/values/colors.xml b/core/src/main/res/values/colors.xml
index ab48fafe7..e558a5c4e 100644
--- a/core/src/main/res/values/colors.xml
+++ b/core/src/main/res/values/colors.xml
@@ -11,11 +11,12 @@
<color name="download_failed_red">#CC0000</color>
<color name="status_progress">#E033B5E5</color>
<color name="status_playing">#E0EE5F52</color>
- <color name="overlay_dark">#262C31</color>
- <color name="overlay_light">#DDDDDD</color>
+ <color name="overlay_dark">#2C2C2C</color>
+ <color name="overlay_light">#FFFFFF</color>
<color name="swipe_refresh_secondary_color_light">#EDEDED</color>
<color name="swipe_refresh_secondary_color_dark">#060708</color>
<color name="new_indicator_green">#669900</color>
+ <color name="image_readability_tint">#80000000</color>
<!-- Use Gingerbread-orange -->
<color name="selection_background_color_dark">#FEBB20</color>
diff --git a/core/src/main/res/values/dimens.xml b/core/src/main/res/values/dimens.xml
index 38c14b024..81a55142a 100644
--- a/core/src/main/res/values/dimens.xml
+++ b/core/src/main/res/values/dimens.xml
@@ -33,4 +33,6 @@
<dimen name="listitem_icon_leftpadding">16dp</dimen>
<dimen name="listitem_icon_rightpadding">16dp</dimen>
+ <dimen name="audioplayer_playercontrols_length">64dp</dimen>
+
</resources> \ No newline at end of file
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index 86f46a330..277d7d3c0 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -159,6 +159,12 @@
<string name="removed_from_queue">Item removed</string>
<string name="move_to_top_label">Move to top</string>
<string name="move_to_bottom_label">Move to bottom</string>
+ <string name="sort">Sort</string>
+ <string name="alpha">Alphabetically</string>
+ <string name="date">Date</string>
+ <string name="duration">Duration</string>
+ <string name="ascending">Ascending</string>
+ <string name="descending">Descending</string>
<!-- Flattr -->
<string name="flattr_auth_label">Flattr sign-in</string>
@@ -205,7 +211,10 @@
<string name="services_label">Services</string>
<string name="flattr_label">Flattr</string>
<string name="pref_pauseOnHeadsetDisconnect_sum">Pause playback when the headphones are disconnected</string>
+ <string name="pref_unpauseOnHeadsetReconnect_sum">Resume playback when the headphones are reconnected</string>
<string name="pref_followQueue_sum">Jump to next queue item when playback completes</string>
+ <string name="pref_auto_delete_sum">Delete episode when playback completes</string>
+ <string name="pref_auto_delete_title">Auto Delete</string>
<string name="playback_pref">Playback</string>
<string name="network_pref">Network</string>
<string name="pref_autoUpdateIntervall_title">Update interval</string>
@@ -214,6 +223,7 @@
<string name="pref_followQueue_title">Continuous playback</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFi media download</string>
<string name="pref_pauseOnHeadsetDisconnect_title">Headphones disconnect</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">Headphones reconnect</string>
<string name="pref_mobileUpdate_title">Mobile updates</string>
<string name="pref_mobileUpdate_sum">Allow updates over the mobile data connection</string>
<string name="refreshing_label">Refreshing</string>
@@ -233,6 +243,8 @@
<string name="pref_automatic_download_sum">Configure the automatic download of episodes.</string>
<string name="pref_autodl_wifi_filter_title">Enable Wi-Fi filter</string>
<string name="pref_autodl_wifi_filter_sum">Allow automatic download only for selected Wi-Fi networks.</string>
+ <string name="pref_automatic_download_on_battery_title">Download when not charging</string>
+ <string name="pref_automatic_download_on_battery_sum">Allow automatic download when the battery is not charging</string>
<string name="pref_episode_cache_title">Episode cache</string>
<string name="pref_theme_title_light">Light</string>
<string name="pref_theme_title_dark">Dark</string>
diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml
index df7ae385c..a2f180395 100644
--- a/core/src/main/res/values/styles.xml
+++ b/core/src/main/res/values/styles.xml
@@ -40,6 +40,7 @@
<item name="attr/av_pause_big">@drawable/ic_pause_grey600_36dp</item>
<item name="attr/av_ff_big">@drawable/ic_fast_forward_grey600_36dp</item>
<item name="attr/av_rew_big">@drawable/ic_fast_rewind_grey600_36dp</item>
+ <item name="attr/ic_settings">@drawable/ic_settings_grey600_24dp</item>
</style>
<style name="Theme.AntennaPod.Dark" parent="@style/Theme.AppCompat">
@@ -80,6 +81,94 @@
<item name="attr/av_pause_big">@drawable/ic_pause_white_36dp</item>
<item name="attr/av_ff_big">@drawable/ic_fast_forward_white_36dp</item>
<item name="attr/av_rew_big">@drawable/ic_fast_rewind_white_36dp</item>
+ <item name="attr/ic_settings">@drawable/ic_settings_white_24dp</item>
+ </style>
+
+ <style name="Theme.AntennaPod.Light.NoTitle" parent="@style/Theme.AppCompat.Light.NoActionBar">
+ <item name="windowActionBar">false</item>
+ <item name="windowActionModeOverlay">true</item>
+ <item name="colorPrimary">@color/primary_light</item>
+ <item name="colorAccent">@color/color_accent</item>
+ <item name="attr/action_about">@drawable/ic_info_grey600_24dp</item>
+ <item name="attr/action_search">@drawable/ic_search_grey600_24dp</item>
+ <item name="attr/action_stream">@drawable/ic_settings_input_antenna_grey600_24dp</item>
+ <item name="attr/av_download">@drawable/ic_file_download_grey600_24dp</item>
+ <item name="attr/av_fast_forward">@drawable/ic_fast_forward_grey600_24dp</item>
+ <item name="attr/av_pause">@drawable/ic_pause_grey600_24dp</item>
+ <item name="attr/av_play">@drawable/ic_play_arrow_grey600_24dp</item>
+ <item name="attr/av_rewind">@drawable/ic_fast_rewind_grey600_24dp</item>
+ <item name="attr/content_discard">@drawable/ic_delete_grey600_24dp</item>
+ <item name="attr/content_new">@drawable/ic_add_grey600_24dp</item>
+ <item name="attr/device_access_time">@drawable/ic_timer_grey600_24dp</item>
+ <item name="attr/location_web_site">@drawable/ic_web_grey600_24dp</item>
+ <item name="attr/navigation_accept">@drawable/ic_done_grey600_24dp</item>
+ <item name="attr/navigation_cancel">@drawable/ic_cancel_grey600_24dp</item>
+ <item name="attr/navigation_expand">@drawable/ic_expand_more_grey600_36dp</item>
+ <item name="attr/navigation_refresh">@drawable/ic_refresh_grey600_24dp</item>
+ <item name="attr/navigation_up">@drawable/navigation_up</item>
+ <item name="attr/navigation_shownotes">@drawable/ic_description_grey600_36dp</item>
+ <item name="attr/navigation_chapters">@drawable/ic_toc_grey600_36dp</item>
+ <item name="attr/social_share">@drawable/ic_share_grey600_24dp</item>
+ <item name="attr/stat_playlist">@drawable/ic_list_grey600_24dp</item>
+ <item name="attr/type_audio">@drawable/ic_hearing_grey600_18dp</item>
+ <item name="attr/type_video">@drawable/ic_remove_red_eye_grey600_18dp</item>
+ <item name="attr/non_transparent_background">@color/white</item>
+ <item name="attr/overlay_background">@color/overlay_light</item>
+ <item name="attr/overlay_drawable">@drawable/overlay_drawable</item>
+ <item name="attr/dragview_background">@drawable/ic_drag_handle</item>
+ <item name="attr/dragview_float_background">@color/white</item>
+ <item name="attr/nav_drawer_background">@color/white</item>
+ <item name="attr/ic_action_overflow">@drawable/ic_more_vert_grey600_24dp</item>
+ <item name="attr/ic_new">@drawable/ic_new_releases_grey600_24dp</item>
+ <item name="attr/ic_history">@drawable/ic_history_grey600_24dp</item>
+ <item name="attr/av_play_big">@drawable/ic_play_arrow_grey600_36dp</item>
+ <item name="attr/av_pause_big">@drawable/ic_pause_grey600_36dp</item>
+ <item name="attr/av_ff_big">@drawable/ic_fast_forward_grey600_36dp</item>
+ <item name="attr/av_rew_big">@drawable/ic_fast_rewind_grey600_36dp</item>
+ <item name="attr/ic_settings">@drawable/ic_settings_grey600_24dp</item>
+ </style>
+
+ <style name="Theme.AntennaPod.Dark.NoTitle" parent="@style/Theme.AppCompat.NoActionBar">
+ <item name="windowActionBar">false</item>
+ <item name="windowActionModeOverlay">true</item>
+ <item name="colorAccent">@color/color_accent</item>
+ <item name="attr/action_about">@drawable/ic_info_white_24dp</item>
+ <item name="attr/action_search">@drawable/ic_search_white_24dp</item>
+ <item name="attr/action_stream">@drawable/ic_settings_input_antenna_white_24dp</item>
+ <item name="attr/av_download">@drawable/ic_file_download_white_24dp</item>
+ <item name="attr/av_fast_forward">@drawable/ic_fast_forward_white_24dp</item>
+ <item name="attr/av_pause">@drawable/ic_pause_white_24dp</item>
+ <item name="attr/av_play">@drawable/ic_play_arrow_white_24dp</item>
+ <item name="attr/av_rewind">@drawable/ic_fast_rewind_white_24dp</item>
+ <item name="attr/content_discard">@drawable/ic_delete_white_24dp</item>
+ <item name="attr/content_new">@drawable/ic_add_white_24dp</item>
+ <item name="attr/device_access_time">@drawable/ic_timer_white_24dp</item>
+ <item name="attr/location_web_site">@drawable/ic_web_white_24dp</item>
+ <item name="attr/navigation_accept">@drawable/ic_done_white_24dp</item>
+ <item name="attr/navigation_cancel">@drawable/ic_cancel_white_24dp</item>
+ <item name="attr/navigation_expand">@drawable/ic_expand_more_white_36dp</item>
+ <item name="attr/navigation_refresh">@drawable/ic_refresh_white_24dp</item>
+ <item name="attr/navigation_up">@drawable/navigation_up_dark</item>
+ <item name="attr/navigation_shownotes">@drawable/ic_description_white_36dp</item>
+ <item name="attr/navigation_chapters">@drawable/ic_toc_white_36dp</item>
+ <item name="attr/social_share">@drawable/ic_share_white_24dp</item>
+ <item name="attr/stat_playlist">@drawable/ic_list_white_24dp</item>
+ <item name="attr/type_audio">@drawable/ic_hearing_white_18dp</item>
+ <item name="attr/type_video">@drawable/ic_remove_red_eye_white_18dp</item>
+ <item name="attr/non_transparent_background">@color/black</item>
+ <item name="attr/overlay_background">@color/overlay_dark</item>
+ <item name="attr/overlay_drawable">@drawable/overlay_drawable_dark</item>
+ <item name="attr/dragview_background">@drawable/ic_drag_handle_dark</item>
+ <item name="attr/dragview_float_background">@color/black</item>
+ <item name="attr/nav_drawer_background">#3B3B3B</item>
+ <item name="attr/ic_action_overflow">@drawable/ic_more_vert_white_24dp</item>
+ <item name="attr/ic_new">@drawable/ic_new_releases_white_24dp</item>
+ <item name="attr/ic_history">@drawable/ic_history_white_24dp</item>
+ <item name="attr/av_play_big">@drawable/ic_play_arrow_white_36dp</item>
+ <item name="attr/av_pause_big">@drawable/ic_pause_white_36dp</item>
+ <item name="attr/av_ff_big">@drawable/ic_fast_forward_white_36dp</item>
+ <item name="attr/av_rew_big">@drawable/ic_fast_rewind_white_36dp</item>
+ <item name="attr/ic_settings">@drawable/ic_settings_white_24dp</item>
</style>
<style name="Theme.AntennaPod.VideoPlayer" parent="@style/Theme.AntennaPod.Dark">
@@ -157,4 +246,10 @@
<item name="android:text">@string/new_label</item>
</style>
+ <style name="BigBlurryBackground">
+ <item name="android:scaleType">centerCrop</item>
+ <item name="android:tint">@color/image_readability_tint</item>
+
+ </style>
+
</resources>