summaryrefslogtreecommitdiff
path: root/core/src/main
diff options
context:
space:
mode:
authorByteHamster <info@bytehamster.com>2019-05-28 17:56:05 +0200
committerByteHamster <info@bytehamster.com>2019-05-28 17:56:05 +0200
commit4443d629fc4592fdbe5a7b149e75f792c551588b (patch)
treed88abdbf9f83b27f648758f6f2909c402bc262d4 /core/src/main
parentcd5224d01b0c159ac027e75be006b70cb9c322ca (diff)
parent83a6d70387e8df95e04f198ef99f992aef674413 (diff)
downloadAntennaPod-4443d629fc4592fdbe5a7b149e75f792c551588b.zip
Merge branch 'develop' into work-manager
Diffstat (limited to 'core/src/main')
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java5
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java66
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java11
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java457
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java184
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java31
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java4
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java115
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/syndication/parsers/DurationParser.java37
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java5
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/StorageUtils.java14
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/TimeSpeedConverter.java22
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/comparator/InReverseChronologicalOrder.java21
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java53
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackServiceStarter.java9
-rw-r--r--core/src/main/res/drawable-hdpi/ic_widget_preview.pngbin8210 -> 19686 bytes
-rw-r--r--core/src/main/res/layout/player_widget.xml71
-rw-r--r--core/src/main/res/values-ca/strings.xml1
-rw-r--r--core/src/main/res/values-cs-rCZ/strings.xml1
-rw-r--r--core/src/main/res/values-da/strings.xml1
-rw-r--r--core/src/main/res/values-de/strings.xml22
-rw-r--r--core/src/main/res/values-el/strings.xml1
-rw-r--r--core/src/main/res/values-es/strings.xml89
-rw-r--r--core/src/main/res/values-et/strings.xml1
-rw-r--r--core/src/main/res/values-fr/strings.xml34
-rw-r--r--core/src/main/res/values-gl-rES/strings.xml85
-rw-r--r--core/src/main/res/values-hi-rIN/strings.xml1
-rw-r--r--core/src/main/res/values-hu/strings.xml1
-rw-r--r--core/src/main/res/values-it/strings.xml4
-rw-r--r--core/src/main/res/values-iw-rIL/strings.xml4
-rw-r--r--core/src/main/res/values-ja/strings.xml4
-rw-r--r--core/src/main/res/values-lt/strings.xml1
-rw-r--r--core/src/main/res/values-nb/strings.xml1
-rw-r--r--core/src/main/res/values-nl/strings.xml4
-rw-r--r--core/src/main/res/values-pl-rPL/strings.xml1
-rw-r--r--core/src/main/res/values-pt-rBR/strings.xml1
-rw-r--r--core/src/main/res/values-pt/strings.xml5
-rw-r--r--core/src/main/res/values-ru/strings.xml1
-rw-r--r--core/src/main/res/values-sv-rSE/strings.xml197
-rw-r--r--core/src/main/res/values-tr/strings.xml1
-rw-r--r--core/src/main/res/values-uk-rUA/strings.xml19
-rw-r--r--core/src/main/res/values-zh-rCN/strings.xml1
-rw-r--r--core/src/main/res/values/strings.xml8
-rw-r--r--core/src/main/res/values/styles.xml296
47 files changed, 1165 insertions, 731 deletions
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 7b625d883..1f01bb32b 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
@@ -73,6 +73,7 @@ public class UserPreferences {
private static final String PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS = "prefPauseForFocusLoss";
private static final String PREF_RESUME_AFTER_CALL = "prefResumeAfterCall";
public static final String PREF_VIDEO_BEHAVIOR = "prefVideoBehavior";
+ private static final String PREF_TIME_RESPECTS_SPEED = "prefPlaybackTimeRespectsSpeed";
// Network
private static final String PREF_ENQUEUE_DOWNLOADED = "prefEnqueueDownloaded";
@@ -876,4 +877,8 @@ public class UserPreferences {
.putString(PREF_BACK_BUTTON_GO_TO_PAGE, tag)
.apply();
}
+
+ public static boolean timeRespectsSpeed() {
+ return prefs.getBoolean(PREF_TIME_RESPECTS_SPEED, false);
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java b/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java
index 6dab9a561..1165d689a 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/PlayerWidgetJobService.java
@@ -6,7 +6,9 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.graphics.Bitmap;
import android.os.Build;
+import android.os.Bundle;
import android.os.IBinder;
import android.support.annotation.NonNull;
import android.support.v4.app.SafeJobIntentService;
@@ -15,12 +17,19 @@ import android.view.KeyEvent;
import android.view.View;
import android.widget.RemoteViews;
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.request.RequestOptions;
+
+import java.util.concurrent.TimeUnit;
+
import de.danoeh.antennapod.core.R;
+import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.receiver.MediaButtonReceiver;
import de.danoeh.antennapod.core.receiver.PlayerWidget;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.service.playback.PlayerStatus;
import de.danoeh.antennapod.core.util.Converter;
+import de.danoeh.antennapod.core.util.TimeSpeedConverter;
import de.danoeh.antennapod.core.util.playback.Playable;
/**
@@ -69,10 +78,25 @@ public class PlayerWidgetJobService extends SafeJobIntentService {
}
}
+ /**
+ * Returns number of cells needed for given size of the widget.
+ *
+ * @param size Widget size in dp.
+ * @return Size in number of cells.
+ */
+ private static int getCellsForSize(int size) {
+ int n = 2;
+ while (70 * n - 30 < size) {
+ ++n;
+ }
+ return n - 1;
+ }
+
private void updateViews() {
ComponentName playerWidget = new ComponentName(this, PlayerWidget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
+ int[] widgetIds = manager.getAppWidgetIds(playerWidget);
RemoteViews views = new RemoteViews(getPackageName(), R.layout.player_widget);
PendingIntent startMediaplayer = PendingIntent.getActivity(this, 0,
PlaybackService.getPlayerActivityIntent(this), 0);
@@ -95,7 +119,24 @@ public class PlayerWidgetJobService extends SafeJobIntentService {
if (media != null) {
views.setOnClickPendingIntent(R.id.layout_left, startMediaplayer);
+ try {
+ Bitmap icon = null;
+ int iconSize = getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
+ icon = Glide.with(PlayerWidgetJobService.this)
+ .asBitmap()
+ .load(media.getImageLocation())
+ .apply(RequestOptions.diskCacheStrategyOf(ApGlideSettings.AP_DISK_CACHE_STRATEGY))
+ .submit(iconSize, iconSize)
+ .get(500, TimeUnit.MILLISECONDS);
+ views.setImageViewBitmap(R.id.imgvCover, icon);
+ } catch (Throwable tr) {
+ Log.e(TAG, "Error loading the media icon for the widget", tr);
+ views.setImageViewResource(R.id.imgvCover, R.mipmap.ic_launcher_foreground);
+ }
+
views.setTextViewText(R.id.txtvTitle, media.getEpisodeTitle());
+ views.setViewVisibility(R.id.txtvTitle, View.VISIBLE);
+ views.setViewVisibility(R.id.txtNoPlaying, View.GONE);
String progressString;
if (playbackService != null) {
@@ -129,13 +170,28 @@ public class PlayerWidgetJobService extends SafeJobIntentService {
// start the app if they click anything
views.setOnClickPendingIntent(R.id.layout_left, startAppPending);
views.setOnClickPendingIntent(R.id.butPlay, startAppPending);
- views.setViewVisibility(R.id.txtvProgress, View.INVISIBLE);
- views.setTextViewText(R.id.txtvTitle,
- this.getString(R.string.no_media_playing_label));
+ views.setViewVisibility(R.id.txtvProgress, View.GONE);
+ views.setViewVisibility(R.id.txtvTitle, View.GONE);
+ views.setViewVisibility(R.id.txtNoPlaying, View.VISIBLE);
+ views.setImageViewResource(R.id.imgvCover, R.mipmap.ic_launcher_foreground);
views.setImageViewResource(R.id.butPlay, R.drawable.ic_play_arrow_white_24dp);
}
- manager.updateAppWidget(playerWidget, views);
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
+ for (int id : widgetIds) {
+ Bundle options = manager.getAppWidgetOptions(id);
+ int minWidth = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
+ int columns = getCellsForSize(minWidth);
+ if (columns < 3) {
+ views.setViewVisibility(R.id.layout_center, View.INVISIBLE);
+ } else {
+ views.setViewVisibility(R.id.layout_center, View.VISIBLE);
+ }
+ manager.updateAppWidget(id, views);
+ }
+ } else {
+ manager.updateAppWidget(playerWidget, views);
+ }
}
/**
@@ -152,6 +208,8 @@ public class PlayerWidgetJobService extends SafeJobIntentService {
private String getProgressString(int position, int duration) {
if (position > 0 && duration > 0) {
+ position = TimeSpeedConverter.convert(position);
+ duration = TimeSpeedConverter.convert(duration);
return Converter.getDurationStringLong(position) + " / "
+ Converter.getDurationStringLong(duration);
} else {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
index 96c413b41..787d465d8 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java
@@ -20,6 +20,7 @@ import android.util.Pair;
import android.webkit.URLUtil;
import org.apache.commons.io.FileUtils;
+import org.greenrobot.eventbus.EventBus;
import org.xml.sax.SAXException;
import java.io.File;
@@ -71,7 +72,6 @@ import de.danoeh.antennapod.core.util.ChapterUtils;
import de.danoeh.antennapod.core.util.DownloadError;
import de.danoeh.antennapod.core.util.InvalidFeedException;
import de.danoeh.antennapod.core.util.gui.NotificationUtils;
-import de.greenrobot.event.EventBus;
/**
* Manages the download of feedfiles in the app. Downloads can be enqueued via the startService intent.
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
index 28889cee3..7988526d9 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
@@ -1088,11 +1088,12 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
mp -> genericSeekCompleteListener();
private void genericSeekCompleteListener() {
+ Log.d(TAG, "genericSeekCompleteListener");
+ if (seekLatch != null) {
+ seekLatch.countDown();
+ }
+
Runnable r = () -> {
- Log.d(TAG, "genericSeekCompleteListener");
- if(seekLatch != null) {
- seekLatch.countDown();
- }
playerLock.lock();
if (playerStatus == PlayerStatus.PLAYING) {
callback.onPlaybackStart(media, getPosition());
@@ -1106,7 +1107,7 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
if (useCallerThread) {
r.run();
} else {
- new Thread(r).start();
+ executor.submit(r);
}
}
}
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 7fe93a162..d4be0013f 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
@@ -25,7 +25,6 @@ import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
import android.support.v4.app.NotificationCompat;
-import android.support.v4.content.ContextCompat;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaBrowserServiceCompat;
import android.support.v4.media.MediaDescriptionCompat;
@@ -72,15 +71,10 @@ import de.danoeh.antennapod.core.util.QueueAccess;
import de.danoeh.antennapod.core.util.gui.NotificationUtils;
import de.danoeh.antennapod.core.util.playback.ExternalMedia;
import de.danoeh.antennapod.core.util.playback.Playable;
-import de.greenrobot.event.EventBus;
+import org.greenrobot.eventbus.EventBus;
/**
* Controls the MediaPlayer that plays a FeedMedia-file
- *
- * Callers should connect to the service with either:
- * - .bindService()
- * - ContextCompat.startForegroundService(), optionally with arguments, such as media to be played, in intent extras
- *
*/
public class PlaybackService extends MediaBrowserServiceCompat {
/**
@@ -95,7 +89,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
/**
* True if cast session should disconnect.
*/
- private static final String EXTRA_CAST_DISCONNECT = "extra.de.danoeh.antennapod.core.service.castDisconnect";
+ public static final String EXTRA_CAST_DISCONNECT = "extra.de.danoeh.antennapod.core.service.castDisconnect";
/**
* True if media should be streamed.
*/
@@ -199,6 +193,10 @@ public class PlaybackService extends MediaBrowserServiceCompat {
*/
public static boolean isRunning = false;
/**
+ * 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
*/
private static boolean transientPause = false;
@@ -266,6 +264,9 @@ public class PlaybackService extends MediaBrowserServiceCompat {
Log.d(TAG, "Service created.");
isRunning = true;
+ PlaybackServiceNotificationBuilder notificationBuilder = new PlaybackServiceNotificationBuilder(this);
+ startForeground(NOTIFICATION_ID, notificationBuilder.build());
+
registerReceiver(autoStateUpdated, new IntentFilter("com.google.android.gms.car.media.STATUS"));
registerReceiver(headsetDisconnected, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
registerReceiver(shutdownReceiver, new IntentFilter(ACTION_SHUTDOWN_PLAYBACK_SERVICE));
@@ -319,30 +320,13 @@ public class PlaybackService extends MediaBrowserServiceCompat {
EventBus.getDefault().post(new ServiceEvent(ServiceEvent.Action.SERVICE_STARTED));
}
- private NotificationCompat.Builder createBasicNotification() {
- final int smallIcon = ClientConfig.playbackServiceCallbacks.getNotificationIconResource(getApplicationContext());
-
- final PendingIntent pIntent = PendingIntent.getActivity(this, 0,
- PlaybackService.getPlayerActivityIntent(this),
- PendingIntent.FLAG_UPDATE_CURRENT);
-
- return new NotificationCompat.Builder(
- this, NotificationUtils.CHANNEL_ID_PLAYING)
- .setContentTitle(getString(R.string.app_name))
- .setContentText("Service is running") // Just in case the notification is not updated (should not occur)
- .setOngoing(false)
- .setContentIntent(pIntent)
- .setWhen(0) // we don't need the time
- .setSmallIcon(smallIcon)
- .setPriority(NotificationCompat.PRIORITY_MIN);
- }
-
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "Service is about to be destroyed");
stopForeground(true);
isRunning = false;
+ started = false;
currentMediaType = MediaType.UNKNOWN;
PreferenceManager.getDefaultSharedPreferences(this)
@@ -364,6 +348,11 @@ public class PlaybackService extends MediaBrowserServiceCompat {
taskManager.shutdown();
}
+ private void stopService() {
+ stopForeground(true);
+ stopSelf();
+ }
+
@Override
public BrowserRoot onGetRoot(@NonNull String clientPackageName, int clientUid, Bundle rootHints) {
Log.d(TAG, "OnGetRoot: clientPackageName=" + clientPackageName +
@@ -421,7 +410,10 @@ public class PlaybackService extends MediaBrowserServiceCompat {
// Child List
try {
for (FeedItem feedItem : taskManager.getQueue()) {
- mediaItems.add(feedItem.getMedia().getMediaItem());
+ FeedMedia media = feedItem.getMedia();
+ if (media != null) {
+ mediaItems.add(media.getMediaItem());
+ }
}
} catch (InterruptedException e) {
e.printStackTrace();
@@ -457,32 +449,39 @@ public class PlaybackService extends MediaBrowserServiceCompat {
final boolean castDisconnect = intent.getBooleanExtra(EXTRA_CAST_DISCONNECT, false);
Playable playable = intent.getParcelableExtra(EXTRA_PLAYABLE);
if (keycode == -1 && playable == null && !castDisconnect) {
- // Typical cases when the service was started with no argument
- // - when it is first bound, and then moved to startedState, as in <code>serviceManager.moveServiceToStartedState()</code>
- // - callers (e.g., Controller) explicitly
- Log.d(TAG, "PlaybackService was started with no arguments.");
+ Log.e(TAG, "PlaybackService was started with no arguments");
+ stopService();
return Service.START_NOT_STICKY;
}
- if (keycode != -1) {
- Log.d(TAG, "Received media button event");
- boolean handled = handleKeycode(keycode, true);
- if (!handled) {
- // Just silently ignores unsupported keycode. Whether the service will
- // continue to run is solely dependent on whether it is playing some media.
- return Service.START_NOT_STICKY;
- }
- } else if (!flavorHelper.castDisconnect(castDisconnect) && playable != null) {
- boolean stream = intent.getBooleanExtra(EXTRA_SHOULD_STREAM, true);
- boolean startWhenPrepared = intent.getBooleanExtra(EXTRA_START_WHEN_PREPARED, false);
- boolean prepareImmediately = intent.getBooleanExtra(EXTRA_PREPARE_IMMEDIATELY, false);
- sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, 0);
- //If the user asks to play External Media, the casting session, if on, should end.
- flavorHelper.castDisconnect(playable instanceof ExternalMedia);
- if (playable instanceof FeedMedia) {
- playable = DBReader.getFeedMedia(((FeedMedia) playable).getId());
+ if ((flags & Service.START_FLAG_REDELIVERY) != 0) {
+ Log.d(TAG, "onStartCommand is a redelivered intent, calling stopForeground now.");
+ stopForeground(true);
+ } else {
+ if (keycode != -1) {
+ Log.d(TAG, "Received media button event");
+ boolean handled = handleKeycode(keycode, true);
+ if (!handled) {
+ stopService();
+ return Service.START_NOT_STICKY;
+ }
+ } else if (!flavorHelper.castDisconnect(castDisconnect) && playable != null) {
+ started = true;
+ boolean stream = intent.getBooleanExtra(EXTRA_SHOULD_STREAM,
+ true);
+ boolean startWhenPrepared = intent.getBooleanExtra(EXTRA_START_WHEN_PREPARED, false);
+ boolean prepareImmediately = intent.getBooleanExtra(EXTRA_PREPARE_IMMEDIATELY, false);
+ sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, 0);
+ //If the user asks to play External Media, the casting session, if on, should end.
+ flavorHelper.castDisconnect(playable instanceof ExternalMedia);
+ if (playable instanceof FeedMedia) {
+ playable = DBReader.getFeedMedia(((FeedMedia) playable).getId());
+ }
+ mediaPlayer.playMediaObject(playable, stream, startWhenPrepared, prepareImmediately);
+ } else {
+ Log.d(TAG, "Did not handle intent to PlaybackService: " + intent);
+ Log.d(TAG, "Extras: " + intent.getExtras());
}
- mediaPlayer.playMediaObject(playable, stream, startWhenPrepared, prepareImmediately);
}
return Service.START_NOT_STICKY;
@@ -556,23 +555,12 @@ public class PlaybackService extends MediaBrowserServiceCompat {
mediaPlayer.seekDelta(-UserPreferences.getRewindSecs() * 1000);
return true;
case KeyEvent.KEYCODE_MEDIA_STOP:
- // The logic gives UI illusion of stop by removing notification
- // In the UI within AntennaPod, including widgets, it is seen as PAUSE, e.g.,
- // users can still user on-screen widget to resume playing.
if (status == PlayerStatus.PLAYING) {
- // Implementation note: Use of a state in serviceManager to tell it to
- // show stop state UI (i.e., stopForeground(true)) is a bit awkward.
- //
- // More intuitive API would be for mediaPlayer.pause() returns a Future that
- // returns after pause, including the related async notification work completes.
- // However, it has its own complication, that mediaPlayer.pause() does not
- // really know when all the related work completes, as they are buried into
- // (asynchronous) callbacks.
- serviceManager.treatNextPauseAsStopOnUI();
mediaPlayer.pause(true, true);
- } else {
- serviceManager.showUIForStopState();
+ started = false;
}
+
+ stopForeground(true); // gets rid of persistent notification
return true;
default:
Log.d(TAG, "Unhandled key code: " + keycode);
@@ -588,6 +576,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
Playable playable = Playable.PlayableUtils.createInstanceFromPreferences(getApplicationContext());
if (playable != null) {
mediaPlayer.playMediaObject(playable, false, true, true);
+ started = true;
PlaybackService.this.updateMediaSessionMetadata(playable);
}
}
@@ -602,9 +591,10 @@ public class PlaybackService extends MediaBrowserServiceCompat {
}
public void notifyVideoSurfaceAbandoned() {
- Log.v(TAG, "notifyVideoSurfaceAbandoned()");
mediaPlayer.pause(true, false);
mediaPlayer.resetVideoSurface();
+ setupNotification(getPlayable());
+ stopForeground(!UserPreferences.isPersistNotify());
}
private final PlaybackServiceTaskManager.PSTMCallback taskManagerCallback = new PlaybackServiceTaskManager.PSTMCallback() {
@@ -667,15 +657,27 @@ public class PlaybackService extends MediaBrowserServiceCompat {
break;
case PAUSED:
+ if ((UserPreferences.isPersistNotify() || isCasting) &&
+ android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ // do not remove notification on pause based on user pref and whether android version supports expanded notifications
+ // Change [Play] button to [Pause]
+ setupNotification(newInfo);
+ } else if (!UserPreferences.isPersistNotify() && !isCasting) {
+ // remove notification on pause
+ stopForeground(true);
+ }
writePlayerStatusPlaybackPreferences();
break;
case STOPPED:
//writePlaybackPreferencesNoMediaPlaying();
+ //stopService();
break;
case PLAYING:
writePlayerStatusPlaybackPreferences();
+ setupNotification(newInfo);
+ started = true;
// set sleep timer if auto-enabled
if (newInfo.oldPlayerStatus != null && newInfo.oldPlayerStatus != PlayerStatus.SEEKING &&
SleepTimerPreferences.autoEnable() && !sleepTimerActive()) {
@@ -686,6 +688,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
case ERROR:
writePlaybackPreferencesNoMediaPlaying();
+ stopService();
break;
}
@@ -698,7 +701,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
@Override
public void shouldStop() {
- serviceManager.stopService();
+ stopService();
}
@Override
@@ -747,6 +750,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
}
sendNotificationBroadcast(NOTIFICATION_TYPE_ERROR, what);
writePlaybackPreferencesNoMediaPlaying();
+ stopService();
return true;
}
@@ -830,6 +834,9 @@ public class PlaybackService extends MediaBrowserServiceCompat {
if (stopPlaying) {
taskManager.cancelPositionSaver();
writePlaybackPreferencesNoMediaPlaying();
+ if (!isCasting) {
+ stopForeground(true);
+ }
}
if (mediaType == null) {
sendNotificationBroadcast(NOTIFICATION_TYPE_PLAYBACK_END, 0);
@@ -1043,7 +1050,6 @@ public class PlaybackService extends MediaBrowserServiceCompat {
private void updateMediaSession(final PlayerStatus playerStatus) {
PlaybackStateCompat.Builder sessionState = new PlaybackStateCompat.Builder();
- @PlaybackStateCompat.State
int state;
if (playerStatus != null) {
switch (playerStatus) {
@@ -1107,9 +1113,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
flavorHelper.mediaSessionSetExtraForWear(mediaSession);
- final PlaybackStateCompat sessionStateBuilt = sessionState.build();
- mediaSession.setPlaybackState(sessionStateBuilt);
- serviceManager.onPlaybackStateChange(sessionStateBuilt);
+ mediaSession.setPlaybackState(sessionState.build());
}
private static boolean useSkipToPreviousForRewindInLockscreen() {
@@ -1163,7 +1167,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI, imageLocation);
}
}
- if (!Thread.currentThread().isInterrupted() && isStarted()) {
+ if (!Thread.currentThread().isInterrupted() && started) {
mediaSession.setSessionActivity(PendingIntent.getActivity(this, 0,
PlaybackService.getPlayerActivityIntent(this),
PendingIntent.FLAG_UPDATE_CURRENT));
@@ -1186,190 +1190,69 @@ public class PlaybackService extends MediaBrowserServiceCompat {
*/
private Thread notificationSetupThread;
- private synchronized void setupNotification(final Playable playable, boolean treatPauseAsStop) {
+ /**
+ * Prepares notification and starts the service in the foreground.
+ */
+ private void setupNotification(final PlaybackServiceMediaPlayer.PSMPInfo info) {
+ setupNotification(info.playable);
+ }
+
+ private synchronized void setupNotification(final Playable playable) {
if (notificationSetupThread != null) {
notificationSetupThread.interrupt();
}
if (playable == null) {
- Log.d(TAG, "setupNotification: playable is null");
- if (!isStarted()) {
- serviceManager.stopService();
+ Log.d(TAG, "setupNotification: playable is null" + Log.getStackTraceString(new Exception()));
+ if (!started) {
+ stopService();
}
return;
}
Runnable notificationSetupTask = new Runnable() {
- Bitmap icon = null;
-
@Override
public void run() {
- Log.d(TAG, "notificationSetupTask: Starting background work");
+ Log.d(TAG, "Starting background work");
if (mediaPlayer == null) {
Log.d(TAG, "notificationSetupTask: mediaPlayer is null");
- if (!isStarted()) {
- serviceManager.stopService();
+ if (!started) {
+ stopService();
}
return;
}
-
- int iconSize = getResources().getDimensionPixelSize(
- android.R.dimen.notification_large_icon_width);
- try {
- icon = Glide.with(PlaybackService.this)
- .asBitmap()
- .load(playable.getImageLocation())
- .apply(RequestOptions.diskCacheStrategyOf(ApGlideSettings.AP_DISK_CACHE_STRATEGY))
- .apply(new RequestOptions().centerCrop())
- .submit(iconSize, iconSize)
- .get();
- } catch (Throwable tr) {
- Log.e(TAG, "Error loading the media icon for the notification", tr);
- }
-
- if (icon == null) {
- icon = BitmapFactory.decodeResource(getApplicationContext().getResources(),
- ClientConfig.playbackServiceCallbacks.getNotificationIconResource(getApplicationContext()));
- }
-
PlayerStatus playerStatus = mediaPlayer.getPlayerStatus();
- Log.v(TAG, "notificationSetupTask: playerStatus=" + playerStatus);
-
- if (!Thread.currentThread().isInterrupted() && isStarted()) {
- String contentText = playable.getEpisodeTitle();
- String contentTitle = playable.getFeedTitle();
- Notification notification;
-
- // Builder is v7, even if some not overwritten methods return its parent's v4 interface
- NotificationCompat.Builder notificationBuilder = createBasicNotification();
- notificationBuilder.setContentTitle(contentTitle)
- .setContentText(contentText)
- .setPriority(UserPreferences.getNotifyPriority())
- .setLargeIcon(icon); // set notification priority
- IntList compactActionList = new IntList();
-
- int numActions = 0; // we start and 0 and then increment by 1 for each call to addAction
-
- if (isCasting) {
- Intent stopCastingIntent = new Intent(PlaybackService.this, PlaybackService.class);
- stopCastingIntent.putExtra(EXTRA_CAST_DISCONNECT, true);
- PendingIntent stopCastingPendingIntent = PendingIntent.getService(PlaybackService.this,
- numActions, stopCastingIntent, PendingIntent.FLAG_UPDATE_CURRENT);
- notificationBuilder.addAction(R.drawable.ic_media_cast_disconnect,
- getString(R.string.cast_disconnect_label),
- stopCastingPendingIntent);
- numActions++;
- }
-
- // always let them rewind
- PendingIntent rewindButtonPendingIntent = getPendingIntentForMediaAction(
- KeyEvent.KEYCODE_MEDIA_REWIND, numActions);
- notificationBuilder.addAction(android.R.drawable.ic_media_rew,
- getString(R.string.rewind_label),
- rewindButtonPendingIntent);
- if (UserPreferences.showRewindOnCompactNotification()) {
- compactActionList.add(numActions);
- }
- numActions++;
-
- if (playerStatus == PlayerStatus.PLAYING) {
- PendingIntent pauseButtonPendingIntent = getPendingIntentForMediaAction(
- KeyEvent.KEYCODE_MEDIA_PAUSE, numActions);
- notificationBuilder.addAction(android.R.drawable.ic_media_pause, //pause action
- getString(R.string.pause_label),
- pauseButtonPendingIntent);
- compactActionList.add(numActions++);
- } else {
- PendingIntent playButtonPendingIntent = getPendingIntentForMediaAction(
- KeyEvent.KEYCODE_MEDIA_PLAY, numActions);
- notificationBuilder.addAction(android.R.drawable.ic_media_play, //play action
- getString(R.string.play_label),
- playButtonPendingIntent);
- compactActionList.add(numActions++);
- }
-
- // ff follows play, then we have skip (if it's present)
- PendingIntent ffButtonPendingIntent = getPendingIntentForMediaAction(
- KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, numActions);
- notificationBuilder.addAction(android.R.drawable.ic_media_ff,
- getString(R.string.fast_forward_label),
- ffButtonPendingIntent);
- if (UserPreferences.showFastForwardOnCompactNotification()) {
- compactActionList.add(numActions);
- }
- numActions++;
-
- if (UserPreferences.isFollowQueue()) {
- PendingIntent skipButtonPendingIntent = getPendingIntentForMediaAction(
- KeyEvent.KEYCODE_MEDIA_NEXT, numActions);
- notificationBuilder.addAction(android.R.drawable.ic_media_next,
- getString(R.string.skip_episode_label),
- skipButtonPendingIntent);
- if (UserPreferences.showSkipOnCompactNotification()) {
- compactActionList.add(numActions);
- }
- numActions++;
- }
-
- PendingIntent stopButtonPendingIntent = getPendingIntentForMediaAction(
- KeyEvent.KEYCODE_MEDIA_STOP, numActions);
- notificationBuilder.setStyle(new android.support.v4.media.app.NotificationCompat.MediaStyle()
- .setMediaSession(mediaSession.getSessionToken())
- .setShowActionsInCompactView(compactActionList.toArray())
- .setShowCancelButton(true)
- .setCancelButtonIntent(stopButtonPendingIntent))
- .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
- .setColor(NotificationCompat.COLOR_DEFAULT);
+ PlaybackServiceNotificationBuilder notificationBuilder =
+ new PlaybackServiceNotificationBuilder(PlaybackService.this);
+ notificationBuilder.addMetadata(playable, mediaSession.getSessionToken(), playerStatus, isCasting);
+
+ if (!notificationBuilder.isIconCached(playable)) {
+ // To make sure that the notification is shown instantly
+ notificationBuilder.loadDefaultIcon();
+ startForeground(NOTIFICATION_ID, notificationBuilder.build());
+ }
+ notificationBuilder.loadIcon(playable);
- notification = notificationBuilder.build();
+ if (!Thread.currentThread().isInterrupted() && started) {
+ Notification notification = notificationBuilder.build();
if (playerStatus == PlayerStatus.PLAYING ||
playerStatus == PlayerStatus.PREPARING ||
playerStatus == PlayerStatus.SEEKING ||
isCasting) {
- Log.v(TAG, "notificationSetupTask: make service foreground");
startForeground(NOTIFICATION_ID, notification);
- } else if (playerStatus == PlayerStatus.PAUSED) {
- if (treatPauseAsStop) {
- stopForeground(true);
- } else if ((UserPreferences.isPersistNotify() || isCasting) &&
- android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- // do not remove notification on pause based on user pref and whether android version supports expanded notifications
- // Change [Play] button to [Pause]
- leaveNotificationAsBackground(notification);
- } else if (!UserPreferences.isPersistNotify() && !isCasting) {
- // remove notification on pause
- stopForeground(true);
- }
} else {
- leaveNotificationAsBackground(notification);
+ stopForeground(false);
+ NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+ mNotificationManager.notify(NOTIFICATION_ID, notification);
}
Log.d(TAG, "Notification set up");
}
}
-
- private void leaveNotificationAsBackground(@NonNull Notification notification) {
- stopForeground(false);
- NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
- mNotificationManager.notify(NOTIFICATION_ID, notification);
- }
-
};
notificationSetupThread = new Thread(notificationSetupTask);
notificationSetupThread.start();
}
- private PendingIntent getPendingIntentForMediaAction(int keycodeValue, int requestCode) {
- Intent intent = new Intent(
- PlaybackService.this, PlaybackService.class);
- intent.putExtra(
- MediaButtonReceiver.EXTRA_KEYCODE,
- keycodeValue);
- return PendingIntent
- .getService(PlaybackService.this, requestCode,
- intent,
- PendingIntent.FLAG_UPDATE_CURRENT);
- }
-
/**
* Persists the current position and last played time of the media file.
*
@@ -1547,7 +1430,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
@Override
public void onReceive(Context context, Intent intent) {
if (TextUtils.equals(intent.getAction(), ACTION_SHUTDOWN_PLAYBACK_SERVICE)) {
- serviceManager.stopService();
+ stopService();
}
}
@@ -1845,6 +1728,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
void saveCurrentPosition(boolean fromMediaPlayer, Playable playable, int position);
+ void setupNotification(boolean connected, PlaybackServiceMediaPlayer.PSMPInfo info);
+
MediaSessionCompat getMediaSession();
Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter);
@@ -1884,6 +1769,24 @@ public class PlaybackService extends MediaBrowserServiceCompat {
}
@Override
+ public void setupNotification(boolean connected, PlaybackServiceMediaPlayer.PSMPInfo info) {
+ if (connected) {
+ PlaybackService.this.setupNotification(info);
+ } else {
+ PlayerStatus status = info.playerStatus;
+ if ((status == PlayerStatus.PLAYING ||
+ status == PlayerStatus.SEEKING ||
+ status == PlayerStatus.PREPARING ||
+ UserPreferences.isPersistNotify()) &&
+ android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ PlaybackService.this.setupNotification(info);
+ } else if (!UserPreferences.isPersistNotify()) {
+ PlaybackService.this.stopForeground(true);
+ }
+ }
+ }
+
+ @Override
public MediaSessionCompat getMediaSession() {
return PlaybackService.this.mediaSession;
}
@@ -1898,116 +1801,4 @@ public class PlaybackService extends MediaBrowserServiceCompat {
PlaybackService.this.unregisterReceiver(receiver);
}
};
-
- private boolean isStarted() {
- return serviceManager.serviceInStartedState;
- }
-
- /**
- * The helper that manages PlaybackService's foreground service life cycle and the associated
- * notification control.
- *
- * The logic is adapted from a sample app from The Android Open Source Project.
- * See https://github.com/googlesamples/android-MediaBrowserService/blob/6cf01be9ef82ca2dd653f03e2a4af0b075cc0021/Application/src/main/java/com/example/android/mediasession/service/MusicService.java#L211
- *
- */
- private class ServiceManager {
- private boolean serviceInStartedState;
- private boolean toTreatNextPauseAsStopOnUI = false;
-
- /**
- *
- * Entry point method for callers. Upon PlaybackState changes,
- * the manager start/stop the PlaybackService as well as relevant notification
- */
- void onPlaybackStateChange(PlaybackStateCompat state) {
- // Report the state to the MediaSession.
-
- Log.v(TAG, "onPlaybackStateChange(" + (state != null ? state.getState() : "null") + ")");
- try {
- // Manage the started state of this service.
- switch (state.getState()) {
- case PlaybackStateCompat.STATE_CONNECTING:
- // move the service to started, aka, making it foreground
- // upon STATE_CONNECTING, i.e., in preparing to play a media.
- // This is done so that in case the preparation takes a long time, e.g.,
- // streaming over a slow network,
- // the service won't be killed by the system prematurely.
- moveServiceToStartedState(state);
- break;
- case PlaybackStateCompat.STATE_PLAYING:
- moveServiceToStartedState(state);
- break;
- case PlaybackStateCompat.STATE_PAUSED:
- updateNotificationForPause(state);
- break;
- case PlaybackStateCompat.STATE_STOPPED:
- moveServiceOutOfStartedState(state);
- break;
- case PlaybackStateCompat.STATE_ERROR:
- moveServiceOutOfStartedState(state);
- break;
- }
- } finally {
- if (toTreatNextPauseAsStopOnUI) {
- Log.v(TAG, "onPlaybackStateChange() - toTreatNextPauseAsStopOnUI enabled. The actual state (should be PAUSED, aka 2): " + state.getState());
- toTreatNextPauseAsStopOnUI = false;
- }
- }
- }
-
- /**
- * Tell service manager that on the next state change, if the state is STATE_PAUSED,
- * give UI treatment as if it is stopped.
- *
- * @see #handleKeycode(int, boolean) the use case
- */
- public void treatNextPauseAsStopOnUI() {
- this.toTreatNextPauseAsStopOnUI = true;
- }
-
- public void showUIForStopState() {
- Log.v(TAG, "serviceManager.showUIForStopState()");
- stopForeground(true); // gets rid of persistent notification, to give the UI illusion of STOP
- }
-
- public void stopService() {
- stopForeground(true);
- stopSelf();
- serviceInStartedState = false;
- }
-
- private void moveServiceToStartedState(PlaybackStateCompat state) {
- if (!serviceInStartedState) {
- ContextCompat.startForegroundService(
- PlaybackService.this,
- new Intent(PlaybackService.this, PlaybackService.class));
- serviceInStartedState = true;
- }
-
- doSetupNotification();
- }
-
- private void updateNotificationForPause(PlaybackStateCompat state) {
- doSetupNotification();
- }
-
- private void moveServiceOutOfStartedState(PlaybackStateCompat state) {
- stopService();
- }
-
- private void doSetupNotification() {
- if (mediaPlayer != null && mediaPlayer.getPlayable() != null) {
- // it updates notification and set foreground status
- // based on player status (similar to PlaybackState)
- setupNotification(mediaPlayer.getPlayable(), toTreatNextPauseAsStopOnUI);
- } else {
- // should not happen unless there are bugs.
- Log.e(TAG, "doSetupNotification() - unexpectedly there is no playable. No notification setup done. mediaPlayer." + mediaPlayer);
- }
- }
- }
-
- private final ServiceManager serviceManager = new ServiceManager();
-
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java
new file mode 100644
index 000000000..9a1e8e7ef
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceNotificationBuilder.java
@@ -0,0 +1,184 @@
+package de.danoeh.antennapod.core.service.playback;
+
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.support.annotation.NonNull;
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.media.session.MediaSessionCompat;
+import android.util.Log;
+import android.view.KeyEvent;
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.request.RequestOptions;
+import de.danoeh.antennapod.core.ClientConfig;
+import de.danoeh.antennapod.core.R;
+import de.danoeh.antennapod.core.glide.ApGlideSettings;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.receiver.MediaButtonReceiver;
+import de.danoeh.antennapod.core.util.IntList;
+import de.danoeh.antennapod.core.util.gui.NotificationUtils;
+import de.danoeh.antennapod.core.util.playback.Playable;
+
+public class PlaybackServiceNotificationBuilder extends NotificationCompat.Builder {
+ private static final String TAG = "PlaybackSrvNotification";
+ private static Bitmap defaultIcon = null;
+
+ private Context context;
+
+ public PlaybackServiceNotificationBuilder(@NonNull Context context) {
+ super(context, NotificationUtils.CHANNEL_ID_PLAYING);
+ this.context = context;
+
+ final int smallIcon = ClientConfig.playbackServiceCallbacks.getNotificationIconResource(context);
+
+ final PendingIntent pIntent = PendingIntent.getActivity(context, 0,
+ PlaybackService.getPlayerActivityIntent(context),
+ PendingIntent.FLAG_UPDATE_CURRENT);
+
+ setContentTitle(context.getString(R.string.app_name));
+ setContentText("Service is running"); // Just in case the notification is not updated (should not occur)
+ setOngoing(false);
+ setContentIntent(pIntent);
+ setWhen(0); // we don't need the time
+ setSmallIcon(smallIcon);
+ setPriority(NotificationCompat.PRIORITY_MIN);
+ }
+
+ public void addMetadata(Playable playable, MediaSessionCompat.Token mediaSessionToken, PlayerStatus playerStatus, boolean isCasting) {
+ Log.v(TAG, "notificationSetupTask: playerStatus=" + playerStatus);
+ setContentTitle(playable.getFeedTitle());
+ setContentText(playable.getEpisodeTitle());
+ setPriority(UserPreferences.getNotifyPriority());
+ addActions(mediaSessionToken, playerStatus, isCasting);
+ setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
+ setColor(NotificationCompat.COLOR_DEFAULT);
+ }
+
+ public boolean isIconCached(Playable playable) {
+ int iconSize = context.getResources().getDimensionPixelSize(android.R.dimen.notification_large_icon_width);
+ try {
+ Bitmap icon = Glide.with(context)
+ .asBitmap()
+ .load(playable.getImageLocation())
+ .apply(RequestOptions.diskCacheStrategyOf(ApGlideSettings.AP_DISK_CACHE_STRATEGY))
+ .apply(new RequestOptions()
+ .centerCrop()
+ .onlyRetrieveFromCache(true))
+ .submit(iconSize, iconSize)
+ .get();
+ return icon != null;
+ } catch (Throwable tr) {
+ return false;
+ }
+ }
+
+ public void loadIcon(Playable playable) {
+ Bitmap icon = null;
+ int iconSize = context.getResources().getDimensionPixelSize(android.R.dimen.notification_large_icon_width);
+ try {
+ icon = Glide.with(context)
+ .asBitmap()
+ .load(playable.getImageLocation())
+ .apply(RequestOptions.diskCacheStrategyOf(ApGlideSettings.AP_DISK_CACHE_STRATEGY))
+ .apply(new RequestOptions().centerCrop())
+ .submit(iconSize, iconSize)
+ .get();
+ } catch (Throwable tr) {
+ Log.e(TAG, "Error loading the media icon for the notification", tr);
+ }
+
+ if (icon == null) {
+ loadDefaultIcon();
+ } else {
+ setLargeIcon(icon);
+ }
+ }
+
+ public void loadDefaultIcon() {
+ if (defaultIcon == null) {
+ defaultIcon = BitmapFactory.decodeResource(context.getResources(),
+ ClientConfig.playbackServiceCallbacks.getNotificationIconResource(context));
+ }
+ setLargeIcon(defaultIcon);
+ }
+
+ private void addActions(MediaSessionCompat.Token mediaSessionToken, PlayerStatus playerStatus, boolean isCasting) {
+ IntList compactActionList = new IntList();
+
+ int numActions = 0; // we start and 0 and then increment by 1 for each call to addAction
+
+ if (isCasting) {
+ Intent stopCastingIntent = new Intent(context, PlaybackService.class);
+ stopCastingIntent.putExtra(PlaybackService.EXTRA_CAST_DISCONNECT, true);
+ PendingIntent stopCastingPendingIntent = PendingIntent.getService(context,
+ numActions, stopCastingIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+ addAction(R.drawable.ic_media_cast_disconnect,
+ context.getString(R.string.cast_disconnect_label),
+ stopCastingPendingIntent);
+ numActions++;
+ }
+
+ // always let them rewind
+ PendingIntent rewindButtonPendingIntent = getPendingIntentForMediaAction(
+ KeyEvent.KEYCODE_MEDIA_REWIND, numActions);
+ addAction(android.R.drawable.ic_media_rew, context.getString(R.string.rewind_label), rewindButtonPendingIntent);
+ if (UserPreferences.showRewindOnCompactNotification()) {
+ compactActionList.add(numActions);
+ }
+ numActions++;
+
+ if (playerStatus == PlayerStatus.PLAYING) {
+ PendingIntent pauseButtonPendingIntent = getPendingIntentForMediaAction(
+ KeyEvent.KEYCODE_MEDIA_PAUSE, numActions);
+ addAction(android.R.drawable.ic_media_pause, //pause action
+ context.getString(R.string.pause_label),
+ pauseButtonPendingIntent);
+ compactActionList.add(numActions++);
+ } else {
+ PendingIntent playButtonPendingIntent = getPendingIntentForMediaAction(
+ KeyEvent.KEYCODE_MEDIA_PLAY, numActions);
+ addAction(android.R.drawable.ic_media_play, //play action
+ context.getString(R.string.play_label),
+ playButtonPendingIntent);
+ compactActionList.add(numActions++);
+ }
+
+ // ff follows play, then we have skip (if it's present)
+ PendingIntent ffButtonPendingIntent = getPendingIntentForMediaAction(
+ KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, numActions);
+ addAction(android.R.drawable.ic_media_ff, context.getString(R.string.fast_forward_label), ffButtonPendingIntent);
+ if (UserPreferences.showFastForwardOnCompactNotification()) {
+ compactActionList.add(numActions);
+ }
+ numActions++;
+
+ if (UserPreferences.isFollowQueue()) {
+ PendingIntent skipButtonPendingIntent = getPendingIntentForMediaAction(
+ KeyEvent.KEYCODE_MEDIA_NEXT, numActions);
+ addAction(android.R.drawable.ic_media_next,
+ context.getString(R.string.skip_episode_label),
+ skipButtonPendingIntent);
+ if (UserPreferences.showSkipOnCompactNotification()) {
+ compactActionList.add(numActions);
+ }
+ numActions++;
+ }
+
+ PendingIntent stopButtonPendingIntent = getPendingIntentForMediaAction(
+ KeyEvent.KEYCODE_MEDIA_STOP, numActions);
+ setStyle(new android.support.v4.media.app.NotificationCompat.MediaStyle()
+ .setMediaSession(mediaSessionToken)
+ .setShowActionsInCompactView(compactActionList.toArray())
+ .setShowCancelButton(true)
+ .setCancelButtonIntent(stopButtonPendingIntent));
+ }
+
+ private PendingIntent getPendingIntentForMediaAction(int keycodeValue, int requestCode) {
+ Intent intent = new Intent(context, PlaybackService.class);
+ intent.putExtra(MediaButtonReceiver.EXTRA_KEYCODE, keycodeValue);
+ return PendingIntent .getService(context, requestCode,
+ intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ }
+} \ No newline at end of file
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java
index 730ae7734..68839023e 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceTaskManager.java
@@ -16,9 +16,11 @@ import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.util.playback.Playable;
-import de.greenrobot.event.EventBus;
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
import io.reactivex.Completable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
@@ -77,6 +79,7 @@ public class PlaybackServiceTaskManager {
EventBus.getDefault().register(this);
}
+ @Subscribe
public void onEvent(QueueEvent event) {
Log.d(TAG, "onEvent(QueueEvent " + event +")");
cancelQueueLoader();
@@ -162,7 +165,7 @@ public class PlaybackServiceTaskManager {
* Starts the widget updater task. If the widget updater is already active, nothing will happen.
*/
public synchronized void startWidgetUpdater() {
- if (!isWidgetUpdaterActive()) {
+ if (!isWidgetUpdaterActive() && !schedExecutor.isShutdown()) {
Runnable widgetUpdater = callback::onWidgetUpdaterTick;
widgetUpdater = useMainThreadIfNecessary(widgetUpdater);
widgetUpdaterFuture = schedExecutor.scheduleWithFixedDelay(widgetUpdater, WIDGET_UPDATER_NOTIFICATION_INTERVAL,
@@ -320,7 +323,7 @@ public class PlaybackServiceTaskManager {
private final boolean shakeToReset;
private final boolean vibrate;
private ShakeListener shakeListener;
- private Handler handler;
+ private final Handler handler;
public SleepTimer(long waitingTime, boolean shakeToReset, boolean vibrate) {
super();
@@ -328,7 +331,21 @@ public class PlaybackServiceTaskManager {
this.timeLeft = waitingTime;
this.shakeToReset = shakeToReset;
this.vibrate = vibrate;
- this.handler = new Handler(); // Use the same thread for callbacks (ExoPlayer)
+
+ if (UserPreferences.useExoplayer() && Looper.myLooper() == Looper.getMainLooper()) {
+ // Run callbacks in main thread so they can call ExoPlayer methods themselves
+ this.handler = new Handler();
+ } else {
+ this.handler = null;
+ }
+ }
+
+ private void postCallback(Runnable r) {
+ if (handler == null) {
+ r.run();
+ } else {
+ handler.post(r);
+ }
}
@Override
@@ -354,7 +371,7 @@ public class PlaybackServiceTaskManager {
if(shakeListener == null && shakeToReset) {
shakeListener = new ShakeListener(context, this);
}
- handler.post(callback::onSleepTimerAlmostExpired);
+ postCallback(callback::onSleepTimerAlmostExpired);
notifiedAlmostExpired = true;
}
if (timeLeft <= 0) {
@@ -364,7 +381,7 @@ public class PlaybackServiceTaskManager {
shakeListener = null;
}
if (!Thread.currentThread().isInterrupted()) {
- handler.post(callback::onSleepTimerExpired);
+ postCallback(callback::onSleepTimerExpired);
} else {
Log.d(TAG, "Sleep timer interrupted");
}
@@ -382,7 +399,7 @@ public class PlaybackServiceTaskManager {
}
public void onShake() {
- handler.post(() -> {
+ postCallback(() -> {
setSleepTimer(waitingTime, shakeToReset, vibrate);
callback.onSleepTimerReset();
});
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 f7226729a..c55acb6ef 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
@@ -8,6 +8,7 @@ import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.util.Log;
+import org.greenrobot.eventbus.EventBus;
import org.shredzone.flattr4j.model.Flattr;
import java.io.File;
@@ -48,7 +49,6 @@ import de.danoeh.antennapod.core.util.Permutor;
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 de.greenrobot.event.EventBus;
/**
* Provides methods for writing data to AntennaPod's database.
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java
index 4093c41a5..c6620a90e 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedSearcher.java
@@ -14,7 +14,7 @@ import java.util.concurrent.FutureTask;
import de.danoeh.antennapod.core.R;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.SearchResult;
-import de.danoeh.antennapod.core.util.comparator.SearchResultValueComparator;
+import de.danoeh.antennapod.core.util.comparator.InReverseChronologicalOrder;
/**
* Performs search on Feeds and FeedItems
@@ -76,7 +76,7 @@ public class FeedSearcher {
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
- Collections.sort(result, new SearchResultValueComparator());
+ Collections.sort(result, new InReverseChronologicalOrder());
return result;
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
index 1daa43025..405c246c9 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
@@ -39,7 +39,7 @@ import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.util.LongIntMap;
import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
-import de.greenrobot.event.EventBus;
+import org.greenrobot.eventbus.EventBus;
// TODO Remove media column from feeditem table
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java
index b3b8a40ce..1e069a1f0 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSITunes.java
@@ -5,9 +5,9 @@ import android.util.Log;
import org.xml.sax.Attributes;
-import java.util.concurrent.TimeUnit;
-
+import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.syndication.handler.HandlerState;
+import de.danoeh.antennapod.core.syndication.parsers.DurationParser;
public class NSITunes extends Namespace {
@@ -22,7 +22,6 @@ public class NSITunes extends Namespace {
private static final String SUBTITLE = "subtitle";
private static final String SUMMARY = "summary";
-
@Override
public SyndElement handleElementStart(String localName, HandlerState state,
Attributes attributes) {
@@ -44,65 +43,75 @@ public class NSITunes extends Namespace {
@Override
public void handleElementEnd(String localName, HandlerState state) {
- if(state.getContentBuf() == null) {
+ if (state.getContentBuf() == null) {
return;
}
- SyndElement secondElement = state.getSecondTag();
- String second = secondElement.getName();
if (AUTHOR.equals(localName)) {
- if (state.getFeed() != null) {
- String author = state.getContentBuf().toString();
- state.getFeed().setAuthor(author);
- }
+ parseAuthor(state);
} else if (DURATION.equals(localName)) {
- String durationStr = state.getContentBuf().toString();
- if(TextUtils.isEmpty(durationStr)) {
- return;
- }
- String[] parts = durationStr.trim().split(":");
- try {
- int durationMs = 0;
- if (parts.length == 2) {
- durationMs += TimeUnit.MINUTES.toMillis(Long.parseLong(parts[0])) +
- TimeUnit.SECONDS.toMillis((long)Float.parseFloat(parts[1]));
- } else if (parts.length >= 3) {
- durationMs += TimeUnit.HOURS.toMillis(Long.parseLong(parts[0])) +
- TimeUnit.MINUTES.toMillis(Long.parseLong(parts[1])) +
- TimeUnit.SECONDS.toMillis((long)Float.parseFloat(parts[2]));
- } else {
- return;
- }
- state.getTempObjects().put(DURATION, durationMs);
- } catch (NumberFormatException e) {
- Log.e(NSTAG, "Duration \"" + durationStr + "\" could not be parsed");
- }
+ parseDuration(state);
} else if (SUBTITLE.equals(localName)) {
- String subtitle = state.getContentBuf().toString();
- if (TextUtils.isEmpty(subtitle)) {
- return;
- }
- if (state.getCurrentItem() != null) {
- if (TextUtils.isEmpty(state.getCurrentItem().getDescription())) {
- state.getCurrentItem().setDescription(subtitle);
- }
- } else {
- if (state.getFeed() != null && TextUtils.isEmpty(state.getFeed().getDescription())) {
- state.getFeed().setDescription(subtitle);
- }
- }
+ parseSubtitle(state);
} else if (SUMMARY.equals(localName)) {
- String summary = state.getContentBuf().toString();
- if (TextUtils.isEmpty(summary)) {
- return;
+ SyndElement secondElement = state.getSecondTag();
+ parseSummary(state, secondElement.getName());
+ }
+ }
+
+ private void parseAuthor(HandlerState state) {
+ if (state.getFeed() != null) {
+ String author = state.getContentBuf().toString();
+ state.getFeed().setAuthor(author);
+ }
+ }
+
+ private void parseDuration(HandlerState state) {
+ String durationStr = state.getContentBuf().toString();
+ if (TextUtils.isEmpty(durationStr)) {
+ return;
+ }
+
+ try {
+ long durationMs = DurationParser.inMillis(durationStr);
+ state.getTempObjects().put(DURATION, (int) durationMs);
+ } catch (NumberFormatException e) {
+ Log.e(NSTAG, String.format("Duration '%s' could not be parsed", durationStr));
+ }
+ }
+
+ private void parseSubtitle(HandlerState state) {
+ String subtitle = state.getContentBuf().toString();
+ if (TextUtils.isEmpty(subtitle)) {
+ return;
+ }
+ if (state.getCurrentItem() != null) {
+ if (TextUtils.isEmpty(state.getCurrentItem().getDescription())) {
+ state.getCurrentItem().setDescription(subtitle);
}
- if (state.getCurrentItem() != null &&
- (TextUtils.isEmpty(state.getCurrentItem().getDescription()) ||
- state.getCurrentItem().getDescription().length() * 1.25 < summary.length())) {
- state.getCurrentItem().setDescription(summary);
- } else if (NSRSS20.CHANNEL.equals(second) && state.getFeed() != null) {
- state.getFeed().setDescription(summary);
+ } else {
+ if (state.getFeed() != null && TextUtils.isEmpty(state.getFeed().getDescription())) {
+ state.getFeed().setDescription(subtitle);
}
}
}
+
+ private void parseSummary(HandlerState state, String secondElementName) {
+ String summary = state.getContentBuf().toString();
+ if (TextUtils.isEmpty(summary)) {
+ return;
+ }
+
+ FeedItem currentItem = state.getCurrentItem();
+ String description = getDescription(currentItem);
+ if (currentItem != null && description.length() * 1.25 < summary.length()) {
+ currentItem.setDescription(summary);
+ } else if (NSRSS20.CHANNEL.equals(secondElementName) && state.getFeed() != null) {
+ state.getFeed().setDescription(summary);
+ }
+ }
+
+ private String getDescription(FeedItem item) {
+ return (item != null && item.getDescription() != null) ? item.getDescription() : "";
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/parsers/DurationParser.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/parsers/DurationParser.java
new file mode 100644
index 000000000..8b036c6a9
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/parsers/DurationParser.java
@@ -0,0 +1,37 @@
+package de.danoeh.antennapod.core.syndication.parsers;
+
+import static java.util.concurrent.TimeUnit.HOURS;
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+public class DurationParser {
+ public static long inMillis(String durationStr) throws NumberFormatException {
+ String[] parts = durationStr.trim().split(":");
+
+ if (parts.length == 1) {
+ return toMillis(parts[0]);
+ } else if (parts.length == 2) {
+ return toMillis("0", parts[0], parts[1]);
+ } else if (parts.length == 3) {
+ return toMillis(parts[0], parts[1], parts[2]);
+ } else {
+ throw new NumberFormatException();
+ }
+ }
+
+ private static long toMillis(String hours, String minutes, String seconds) {
+ return HOURS.toMillis(Long.parseLong(hours))
+ + MINUTES.toMillis(Long.parseLong(minutes))
+ + toMillis(seconds);
+ }
+
+ private static long toMillis(String seconds) {
+ if (seconds.contains(".")) {
+ float value = Float.parseFloat(seconds);
+ float millis = value % 1;
+ return SECONDS.toMillis((long) value) + (long) (millis * 1000);
+ } else {
+ return SECONDS.toMillis(Long.parseLong(seconds));
+ }
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java
index 9bdd375ce..d9431bc5d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java
@@ -68,6 +68,11 @@ public class NetworkUtils {
}
}
}
+ } else if (networkInfo.getType() == ConnectivityManager.TYPE_ETHERNET) {
+ Log.d(TAG, "Device is connected to Ethernet");
+ if (networkInfo.isConnected()) {
+ return true;
+ }
} else {
if (!UserPreferences.isEnableAutodownloadOnMobile()) {
Log.d(TAG, "Auto Download not enabled on Mobile");
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/StorageUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/StorageUtils.java
index 3a6bf5755..414b5c781 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/StorageUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/StorageUtils.java
@@ -74,4 +74,18 @@ public class StorageUtils {
}
return availableBlocks * blockSize;
}
+
+ public static long getTotalSpaceAvailable(String path) {
+ StatFs stat = new StatFs(path);
+ long blockCount;
+ long blockSize;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ blockCount = stat.getBlockCountLong();
+ blockSize = stat.getBlockSizeLong();
+ } else {
+ blockCount = stat.getBlockCount();
+ blockSize = stat.getBlockSize();
+ }
+ return blockCount * blockSize;
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/TimeSpeedConverter.java b/core/src/main/java/de/danoeh/antennapod/core/util/TimeSpeedConverter.java
new file mode 100644
index 000000000..5fea8238b
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/TimeSpeedConverter.java
@@ -0,0 +1,22 @@
+package de.danoeh.antennapod.core.util;
+
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+
+public class TimeSpeedConverter {
+ private TimeSpeedConverter() {
+
+ }
+
+ /** Convert millisecond according to the current playback speed
+ * @param time: time to convert
+ * @return converted time (can be < 0 if time is < 0)
+ */
+ public static int convert(int time) {
+ boolean timeRespectsSpeed = UserPreferences.timeRespectsSpeed();
+ if (time > 0 && timeRespectsSpeed) {
+ float speed = Float.parseFloat(UserPreferences.getPlaybackSpeed());
+ return (int)(time / speed);
+ }
+ return time;
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/comparator/InReverseChronologicalOrder.java b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/InReverseChronologicalOrder.java
new file mode 100644
index 000000000..80246af8f
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/comparator/InReverseChronologicalOrder.java
@@ -0,0 +1,21 @@
+package de.danoeh.antennapod.core.util.comparator;
+
+import java.util.Comparator;
+
+import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.feed.SearchResult;
+
+public class InReverseChronologicalOrder implements Comparator<SearchResult> {
+ /**
+ * Compare items and sort it on chronological order.
+ */
+ @Override
+ public int compare(SearchResult o1, SearchResult o2) {
+ if ((o1.getComponent() instanceof FeedItem) && (o2.getComponent() instanceof FeedItem)) {
+ FeedItem item1 = (FeedItem) o1.getComponent();
+ FeedItem item2 = (FeedItem) o2.getComponent();
+ return item2.getPubDate().compareTo(item1.getPubDate());
+ }
+ return 0;
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
index 4d5ed449b..6191d4491 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java
@@ -12,6 +12,7 @@ import android.media.MediaPlayer;
import android.os.Build;
import android.os.IBinder;
import android.support.annotation.NonNull;
+import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
@@ -25,6 +26,7 @@ import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.core.R;
+import de.danoeh.antennapod.core.event.ServiceEvent;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.MediaType;
@@ -36,6 +38,7 @@ import de.danoeh.antennapod.core.service.playback.PlayerStatus;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.Optional;
+import de.danoeh.antennapod.core.util.TimeSpeedConverter;
import de.danoeh.antennapod.core.util.playback.Playable.PlayableUtils;
import io.reactivex.Maybe;
import io.reactivex.MaybeOnSubscribe;
@@ -43,6 +46,9 @@ import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
/**
* Communicates with the playback service. GUI classes should use this class to
@@ -69,6 +75,7 @@ public abstract class PlaybackController {
private boolean mediaInfoLoaded = false;
private boolean released = false;
private boolean initialized = false;
+ private boolean eventsRegistered = false;
private Disposable serviceBinder;
private Disposable mediaLoader;
@@ -95,7 +102,11 @@ public abstract class PlaybackController {
/**
* Creates a new connection to the playbackService.
*/
- public void init() {
+ public synchronized void init() {
+ if (!eventsRegistered) {
+ EventBus.getDefault().register(this);
+ eventsRegistered = true;
+ }
if (PlaybackService.isRunning) {
initServiceRunning();
} else {
@@ -103,8 +114,14 @@ public abstract class PlaybackController {
}
}
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ public void onEventMainThread(ServiceEvent event) {
+ if (event.action == ServiceEvent.Action.SERVICE_STARTED) {
+ init();
+ }
+ }
+
private synchronized void initServiceRunning() {
- Log.v(TAG, "initServiceRunning()");
if (initialized) {
return;
}
@@ -165,6 +182,10 @@ public abstract class PlaybackController {
media = null;
released = true;
+ if (eventsRegistered) {
+ EventBus.getDefault().unregister(this);
+ eventsRegistered = false;
+ }
}
/**
@@ -189,13 +210,20 @@ public abstract class PlaybackController {
.observeOn(AndroidSchedulers.mainThread())
.subscribe(optionalIntent -> {
boolean bound = false;
- if (optionalIntent.isPresent()) {
- Log.d(TAG, "Calling bind service");
- bound = activity.bindService(optionalIntent.get(), mConnection, 0);
+ if (!PlaybackService.started) {
+ if (optionalIntent.isPresent()) {
+ Log.d(TAG, "Calling start service");
+ ContextCompat.startForegroundService(activity, optionalIntent.get());
+ bound = activity.bindService(optionalIntent.get(), mConnection, 0);
+ } else {
+ status = PlayerStatus.STOPPED;
+ setupGUI();
+ handleStatus();
+ }
} else {
- status = PlayerStatus.STOPPED;
- setupGUI();
- handleStatus();
+ Log.d(TAG, "PlaybackService is running, trying to connect without start command.");
+ bound = activity.bindService(new Intent(activity, PlaybackService.class),
+ mConnection, 0);
}
Log.d(TAG, "Result for service binding: " + bound);
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
@@ -214,7 +242,6 @@ public abstract class PlaybackController {
return Optional.empty();
}
-
boolean fileExists = media.localFileAvailable();
boolean lastIsStream = PlaybackPreferences.getCurrentEpisodeIsStream();
if (!fileExists && !lastIsStream && media instanceof FeedMedia) {
@@ -540,8 +567,8 @@ public abstract class PlaybackController {
if (fromUser && playbackService != null && media != null) {
float prog = progress / ((float) seekBar.getMax());
int duration = media.getDuration();
- txtvPosition.setText(Converter
- .getDurationStringLong((int) (prog * duration)));
+ int position = TimeSpeedConverter.convert((int) (prog * duration));
+ txtvPosition.setText(Converter.getDurationStringLong(position));
return prog;
}
return 0;
@@ -582,8 +609,7 @@ public abstract class PlaybackController {
.startWhenPrepared(true)
.streamIfLastWasStream()
.start();
- Log.d(TAG, "Play/Pause button was pressed, but playbackservice was null - " +
- "it is likely to have been released by Android system. Restarting it.");
+ Log.w(TAG, "Play/Pause button was pressed, but playbackservice was null!");
return;
}
switch (status) {
@@ -760,7 +786,6 @@ public abstract class PlaybackController {
}
public void notifyVideoSurfaceAbandoned() {
- Log.v(TAG, "notifyVideoSurfaceAbandoned() - hasPlaybackService=" + (playbackService != null));
if (playbackService != null) {
playbackService.notifyVideoSurfaceAbandoned();
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackServiceStarter.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackServiceStarter.java
index 64cf61457..f7d2ee409 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackServiceStarter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackServiceStarter.java
@@ -2,15 +2,14 @@ package de.danoeh.antennapod.core.util.playback;
import android.content.Context;
import android.content.Intent;
+import android.media.MediaPlayer;
+import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
-import android.util.Log;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
public class PlaybackServiceStarter {
- private static final String TAG = "PlaybackServiceStarter";
-
private final Context context;
private final Playable media;
private boolean startWhenPrepared = false;
@@ -67,10 +66,6 @@ public class PlaybackServiceStarter {
launchIntent.putExtra(PlaybackService.EXTRA_SHOULD_STREAM, shouldStream);
launchIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY, prepareImmediately);
- if (media == null) {
- Log.e(TAG, "getIntent() - media is unexpectedly null. intent:" + launchIntent);
- }
-
return launchIntent;
}
diff --git a/core/src/main/res/drawable-hdpi/ic_widget_preview.png b/core/src/main/res/drawable-hdpi/ic_widget_preview.png
index 85a537154..3c1e08a31 100644
--- a/core/src/main/res/drawable-hdpi/ic_widget_preview.png
+++ b/core/src/main/res/drawable-hdpi/ic_widget_preview.png
Binary files differ
diff --git a/core/src/main/res/layout/player_widget.xml b/core/src/main/res/layout/player_widget.xml
index 4c98895a0..daf661002 100644
--- a/core/src/main/res/layout/player_widget.xml
+++ b/core/src/main/res/layout/player_widget.xml
@@ -12,7 +12,7 @@
<ImageButton
android:id="@+id/butPlay"
android:contentDescription="@string/play_label"
- android:layout_width="56dp"
+ android:layout_width="@android:dimen/app_icon_size"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_margin="12dp"
@@ -26,26 +26,55 @@
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@id/butPlay"
android:background="@drawable/borderless_button_dark"
- android:gravity="center_vertical"
- android:orientation="vertical" >
-
- <TextView
- android:id="@+id/txtvTitle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_margin="8dp"
- android:maxLines="1"
- android:text="@string/no_media_playing_label"
- android:textColor="@color/white"
- android:textSize="@dimen/text_size_medium"
- android:textStyle="bold" />
-
- <TextView
- android:id="@+id/txtvProgress"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_margin="8dp"
- android:textColor="@color/white" />
+ android:gravity="fill_horizontal"
+ android:orientation="horizontal" >
+
+ <ImageView
+ android:id="@+id/imgvCover"
+ android:layout_width="@android:dimen/app_icon_size"
+ android:layout_height="match_parent"
+ android:layout_alignParentLeft="true"
+ android:layout_margin="12dp"
+ android:layout_toLeftOf="@id/layout_center" />
+
+ <LinearLayout
+ android:id="@+id/layout_center"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentRight="true"
+ android:gravity="center_vertical"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/txtNoPlaying"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginVertical="12dp"
+ android:maxLines="3"
+ android:text="@string/no_media_playing_label"
+ android:textColor="@color/white"
+ android:textSize="@dimen/text_size_medium"
+ android:textStyle="bold" />
+
+ <TextView
+ android:id="@+id/txtvTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginVertical="8dp"
+ android:maxLines="1"
+ android:textColor="@color/white"
+ android:textSize="@dimen/text_size_medium"
+ android:textStyle="bold"
+ android:visibility="gone" />
+
+ <TextView
+ android:id="@+id/txtvProgress"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginVertical="8dp"
+ android:textColor="@color/white"
+ android:visibility="gone" />
+ </LinearLayout>
</LinearLayout>
</RelativeLayout>
diff --git a/core/src/main/res/values-ca/strings.xml b/core/src/main/res/values-ca/strings.xml
index b9b346ba0..6983d140e 100644
--- a/core/src/main/res/values-ca/strings.xml
+++ b/core/src/main/res/values-ca/strings.xml
@@ -643,6 +643,7 @@
<string name="proxy_host_empty_error">El host no pot estar buit</string>
<string name="proxy_host_invalid_error">El host no és una adreça IP o domini vàlid</string>
<string name="proxy_port_invalid_error">El port no és vàlid</string>
+ <!--Subscriptions fragment-->
<!--Database import/export-->
<string name="import_export">Importa/exporta la base de dades</string>
<string name="import_export_warning">Podeu fer servir aquesta funcionalitat experimental per a transferir les vostres subscripcions i episodis reproduïts a un altre dispositiu.\n\nNomés podreu importar la base de dades fent servir la mateixa versió de l\'AntennaPod. En cas contrari, aquesta funcionalitat es comportarà de forma imprevisible.\n\nDesprés d\'importar-los, els episodis es poden mostrar com a baixats tot i no estar disponibles. Premeu el botó per a reproduir-los per a que l\'AntennaPod ho detecti.</string>
diff --git a/core/src/main/res/values-cs-rCZ/strings.xml b/core/src/main/res/values-cs-rCZ/strings.xml
index 70f642e82..390730abb 100644
--- a/core/src/main/res/values-cs-rCZ/strings.xml
+++ b/core/src/main/res/values-cs-rCZ/strings.xml
@@ -587,6 +587,7 @@
<string name="proxy_host_empty_error">Host nesmí být prázdný</string>
<string name="proxy_host_invalid_error">Host není platná IP nebo doména</string>
<string name="proxy_port_invalid_error">Neplatný port</string>
+ <!--Subscriptions fragment-->
<!--Database import/export-->
<!--Casting-->
<string name="cast_media_route_menu_title">Přehrát na...</string>
diff --git a/core/src/main/res/values-da/strings.xml b/core/src/main/res/values-da/strings.xml
index 646485494..565f53a6d 100644
--- a/core/src/main/res/values-da/strings.xml
+++ b/core/src/main/res/values-da/strings.xml
@@ -644,6 +644,7 @@
<string name="proxy_host_empty_error">Vært kan ikke være tom</string>
<string name="proxy_host_invalid_error">Vært er ikke en gyldig IP-adresse eller et gyldigt domæne</string>
<string name="proxy_port_invalid_error">Port ikke gyldig</string>
+ <!--Subscriptions fragment-->
<!--Database import/export-->
<string name="import_export">Database-import/eksport</string>
<string name="label_import">Import</string>
diff --git a/core/src/main/res/values-de/strings.xml b/core/src/main/res/values-de/strings.xml
index a6859363f..8962daa00 100644
--- a/core/src/main/res/values-de/strings.xml
+++ b/core/src/main/res/values-de/strings.xml
@@ -137,8 +137,8 @@
<string name="load_complete_feed">Kompletten Feed aktualisieren</string>
<string name="hide_episodes_title">Episoden verbergen</string>
<string name="batch_edit">Stapelbearbeitung</string>
- <string name="select_all_above">Alles oben auswählen</string>
- <string name="select_all_below">Alles unten auswählen</string>
+ <string name="select_all_above">Alles oberhalb auswählen</string>
+ <string name="select_all_below">Alles unterhalb auswählen</string>
<string name="hide_unplayed_episodes_label">Ungespielt</string>
<string name="hide_paused_episodes_label">Pausiert</string>
<string name="hide_played_episodes_label">Gespielt</string>
@@ -319,7 +319,7 @@
<string name="enable_sonic">Sonic aktivieren</string>
<!--Empty list labels-->
<string name="no_items_header_label">Leere Abspielliste</string>
- <string name="no_items_label">Du kannst Episoden zur Abspielliste hinzufügen, indem du sie herunterlädst oder lange antippst.</string>
+ <string name="no_items_label">Du kannst Episoden hinzufügen, indem du sie herunterlädst oder sie lange antippst und \"Zur Abspielliste hinzufügen\" auswählst.</string>
<string name="no_feeds_label">Du hast noch keine Feeds abonniert.</string>
<string name="no_chapters_label">Diese Episode hat keine Kapitel.</string>
<string name="no_shownotes_label">Episode hat keine Shownotizen.</string>
@@ -457,7 +457,7 @@
<string name="pref_gpodnet_sethostname_title">Hostname ändern</string>
<string name="pref_gpodnet_sethostname_use_default_host">Standard-Host verwenden</string>
<string name="pref_expandNotify_title">Hohe Benachrichtigungspriorität</string>
- <string name="pref_expandNotify_sum">Das öffnet normalerweise die Benachrichtigungen um Wiedergabe Buttons zu zeigen</string>
+ <string name="pref_expandNotify_sum">Dies erweitert normalerweise die Benachrichtigung und zeigt so die Wiedergabe-Buttons an.</string>
<string name="pref_persistNotify_title">Persistente Wiedergabesteuerung</string>
<string name="pref_persistNotify_sum">Zeige Wiedergabebedienelemente in der Benachrichtigung und im Lockscreen an, während die Wiedergabe pausiert ist.</string>
<string name="pref_compact_notification_buttons_title">Lockscreen-Wiedergabetasten festlegen</string>
@@ -497,15 +497,15 @@
<string name="stop_playback">Wiedergabe anhalten</string>
<string name="continue_playback">Audiowiedergabe fortsetzen</string>
<string name="behavior">Verhalten</string>
- <string name="pref_back_button_behavior_title">Zurück Button Verhalten</string>
- <string name="pref_back_button_behavior_sum">Verändere das Verhalten vom Zurück Button</string>
+ <string name="pref_back_button_behavior_title">Verhalten des Zurück-Buttons</string>
+ <string name="pref_back_button_behavior_sum">Verändere das Verhalten vom Zurück-Button</string>
<string name="back_button_default">Standard</string>
- <string name="back_button_open_drawer">Öffne Navigationsschublade</string>
- <string name="back_button_double_tap">Doppel Tap zum verlassen</string>
+ <string name="back_button_open_drawer">Öffne Seitenleiste</string>
+ <string name="back_button_double_tap">Doppelt tippen zum Verlassen</string>
<string name="back_button_show_prompt">Bestätigen zum Verlassen</string>
<string name="close_prompt">Bist du sicher, dass du AntennaPod schließen möchtest?</string>
- <string name="double_tap_toast">Tap Zurück Button noch einmal zum Verlassen</string>
- <string name="back_button_go_to_page">Gehe zu Seite</string>
+ <string name="double_tap_toast">Zurück-Button erneut tippen zum Verlassen</string>
+ <string name="back_button_go_to_page">Gehe zu Seite…</string>
<string name="back_button_go_to_page_title">Seite auswählen</string>
<string name="pref_delete_removes_from_queue_title">Löschen entfernt aus Abspielliste</string>
<string name="pref_delete_removes_from_queue_sum">Entferne Episoden automatisch aus der Abspielliste, wenn sie gelöscht werden.</string>
@@ -714,6 +714,8 @@
<string name="proxy_host_empty_error">Host darf nicht leer sein</string>
<string name="proxy_host_invalid_error">Host ist keine gültige IP oder Domain</string>
<string name="proxy_port_invalid_error">Port ungültig</string>
+ <!--Subscriptions fragment-->
+ <string name="subscription_num_columns">Spaltenanzahl</string>
<!--Database import/export-->
<string name="import_export">Datenbankimport/-export</string>
<string name="import_export_warning">Diese experimentelle Funktion kann dazu benutzt werden, deine Abonnements und abgespielten Episoden auf ein anderes Gerät zu übertragen.\n\nExportierte Datenbanken können nur mit der gleichen AntennaPod-Version wieder importiert werden, andernfalls kann dies zu unerwartetem Verhalten führen.\n\nNach dem Importieren können Episoden als heruntergeladen angezeigt werden, obwohl sie dies nicht sind. Einfach den Abspielknopf der Episoden drücken, damit AntennaPod das erkennt.</string>
diff --git a/core/src/main/res/values-el/strings.xml b/core/src/main/res/values-el/strings.xml
index 06367dd94..2e1c6cd33 100644
--- a/core/src/main/res/values-el/strings.xml
+++ b/core/src/main/res/values-el/strings.xml
@@ -349,6 +349,7 @@
<!--Rating dialog-->
<!--Audio controls-->
<!--proxy settings-->
+ <!--Subscriptions fragment-->
<!--Database import/export-->
<!--Casting-->
<!--<string name="cast_failed_to_connect">Could not connect to the device</string>-->
diff --git a/core/src/main/res/values-es/strings.xml b/core/src/main/res/values-es/strings.xml
index c9fcca51b..69feafba7 100644
--- a/core/src/main/res/values-es/strings.xml
+++ b/core/src/main/res/values-es/strings.xml
@@ -24,7 +24,7 @@
<string name="gpodnet_auth_label">Iniciar sesión en gpodder.net</string>
<string name="free_space_label">%1$s libre</string>
<string name="episode_cache_full_title">Almacenamiento de episodios completo</string>
- <string name="episode_cache_full_message">Se ha alcanzado el límite de almacenamiento de episodios. Puedes aumentar el tamaño en opciones.</string>
+ <string name="episode_cache_full_message">Se ha alcanzado el límite de almacenamiento de episodios. Puede aumentar el tamaño en opciones.</string>
<string name="synchronizing">Sincronizando…</string>
<!--Statistics fragment-->
<string name="total_time_listened_to_podcasts">Tiempo total de reproducción de pódcast:</string>
@@ -95,16 +95,21 @@
<string name="episode_cleanup_never">Nunca</string>
<string name="episode_cleanup_queue_removal">Cuando no esté en la cola</string>
<string name="episode_cleanup_after_listening">Después de acabar</string>
+ <plurals name="episode_cleanup_hours_after_listening">
+ <item quantity="one">1 hora después de acabar</item>
+ <item quantity="other">%d horas después de acabar</item>
+ </plurals>
<plurals name="episode_cleanup_days_after_listening">
<item quantity="one">1 día después de acabar</item>
<item quantity="other">%d días después de acabar</item>
</plurals>
+ <string name="num_selected_label">%dseleccionado</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">URL del canal</string>
<string name="etxtFeedurlHint">www.ejemplo.com/feed</string>
<string name="txtvfeedurl_label">Añadir pódcast por URL</string>
<string name="podcastdirectories_label">Buscar pódcast en el directorio</string>
- <string name="podcastdirectories_descr">Para nuevos pódcast, puedes buscar en iTunes o fyyd, o explorar en gpodder.net por nombre, categoría o popularidad.</string>
+ <string name="podcastdirectories_descr">Para nuevos pódcast, puede buscar en iTunes o fyyd, o explorar en gpodder.net por nombre, categoría o popularidad.</string>
<string name="browse_gpoddernet_label">Explorar en gpodder.net</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Marcar todos como reproducidos</string>
@@ -144,10 +149,14 @@
<string name="hide_has_media_label">Tiene multimedia</string>
<string name="hide_is_favorite_label">Es favorito</string>
<string name="filtered_label">Filtrados</string>
- <string name="refresh_failed_msg">{fa-exclamation-circle} Error en última actualización</string>
+ <string name="refresh_failed_msg">{fa-exclamation-circle} Error en la última actualización</string>
<string name="open_podcast">Abrir pódcast</string>
<!--actions on feeditems-->
<string name="download_label">Descargar</string>
+ <plurals name="downloading_batch_label">
+ <item quantity="one">Descargando %d episodio.</item>
+ <item quantity="other">Descargando %d episodios.</item>
+ </plurals>
<string name="play_label">Reproducir</string>
<string name="pause_label">Pausar</string>
<string name="stop_label">Detener</string>
@@ -155,14 +164,35 @@
<string name="remove_label">Eliminar</string>
<string name="delete_label">Borrar</string>
<string name="delete_failed">No se puede borrar el fichero. Reiniciar el dispositivo podría ayudar.</string>
+ <string name="delete_episode_label">Borrar Episodio</string>
+ <plurals name="deleted_episode_batch_label">
+ <item quantity="one">%depisodio borrado.</item>
+ <item quantity="other">%depisodios borrados.</item>
+ </plurals>
<string name="mark_as_seen_label">Marcar como visto</string>
<string name="marked_as_seen_label">Marcado como visto</string>
<string name="mark_read_label">Marcar como reproducido</string>
<string name="marked_as_read_label">Marcado como reproducido</string>
+ <plurals name="marked_read_batch_label">
+ <item quantity="one">%depisodio marcado como reproducido.</item>
+ <item quantity="other">%depisodios marcados como reproducidos.</item>
+ </plurals>
<string name="mark_unread_label">Marcar como no reproducido</string>
+ <plurals name="marked_unread_batch_label">
+ <item quantity="one">%d episodio marcado como no reproducido.</item>
+ <item quantity="other">%d episodios marcados como no reproducidos.</item>
+ </plurals>
<string name="add_to_queue_label">Añadir a la cola</string>
<string name="added_to_queue_label">Añadido a la cola</string>
+ <plurals name="added_to_queue_batch_label">
+ <item quantity="one">%d episodio añadido a la cola.</item>
+ <item quantity="other">%d episodios añadidos a la cola.</item>
+ </plurals>
<string name="remove_from_queue_label">Eliminar de la cola</string>
+ <plurals name="removed_from_queue_batch_label">
+ <item quantity="one">%d episodio eliminado de la cola.</item>
+ <item quantity="other">%d episodios eliminados de la cola.</item>
+ </plurals>
<string name="add_to_favorite_label">Añadir a favoritos</string>
<string name="added_to_favorites">Añadido a favoritos</string>
<string name="remove_from_favorite_label">Eliminar de favoritos</string>
@@ -214,6 +244,7 @@
<string name="download_type_media">Archivo multimedia</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="null_value_podcast_error">No se proporcionó ningún pódcast que pudiera mostrarse.</string>
<string name="authentication_notification_title">Autenticación requerida</string>
<string name="authentication_notification_msg">El recurso solicitado requiere un usuario y contraseña</string>
<string name="confirm_mobile_download_dialog_title">Confirmar descarga por red móvil</string>
@@ -287,9 +318,25 @@
<string name="set_playback_speed_label">Velocidades de reproducción</string>
<string name="enable_sonic">Activar Sonic</string>
<!--Empty list labels-->
+ <string name="no_items_header_label">Sin episodios en la cola</string>
+ <string name="no_items_label">Añada un episodio descargándolo o presione prolongadamente un episodio y seleccione \"Añadir a la cola\".</string>
<string name="no_feeds_label">No se ha suscrito a ningún pódcast.</string>
<string name="no_chapters_label">Este episodio no tiene capítulos.</string>
<string name="no_shownotes_label">Este episodio no tiene notas del programa.</string>
+ <string name="no_run_downloads_head_label">No hay descargas en ejecución</string>
+ <string name="no_run_downloads_label">Puede descargar episodios en la pantalla de detalles del pódcast.</string>
+ <string name="no_comp_downloads_head_label">No hay episodios descargados</string>
+ <string name="no_comp_downloads_label">Puede descargar episodios en la pantalla de detalles del pódcast.</string>
+ <string name="no_log_downloads_head_label">Sin registro de descargas</string>
+ <string name="no_log_downloads_label">Los registros de descargas aparecerán aquí cuando estén disponibles.</string>
+ <string name="no_history_head_label">Sin historial</string>
+ <string name="no_history_label">Después de escuchar un episodio, aparecerá aquí.</string>
+ <string name="no_all_episodes_head_label">Sin episodios</string>
+ <string name="no_all_episodes_label">Cuando añada un pódcast, los episodios aparecerán aquí.</string>
+ <string name="no_new_episodes_head_label">Sin episodios nuevos</string>
+ <string name="no_new_episodes_label">Cuando lleguen nuevos episodios, aparecerán aquí.</string>
+ <string name="no_fav_episodes_head_label">Sin episodios favoritos</string>
+ <string name="no_fav_episodes_label">Puede añadir episodios a los favoritos presionándolos durante un tiempo prolongado.</string>
<!--Preferences-->
<string name="storage_pref">Almacenamiento</string>
<string name="project_pref">Proyecto</string>
@@ -302,6 +349,7 @@
<string name="automation">Automatización</string>
<string name="download_pref_details">Detalles</string>
<string name="import_export_pref">Importar/Exportar</string>
+ <string name="import_export_search_keywords">copia de seguridad, restaurar, backup, restore</string>
<string name="appearance">Apariencia</string>
<string name="external_elements">Elementos externos</string>
<string name="interruptions">Interrupciones</string>
@@ -343,6 +391,9 @@
<string name="pref_unpauseOnBluetoothReconnect_title">Reconectar con Bluetooth</string>
<string name="pref_mobileUpdate_title">Actualizaciones por red móvil</string>
<string name="pref_mobileUpdate_sum">Permitir actualizaciones por la red de datos móvil</string>
+ <string name="pref_mobileUpdate_nothing">Nada</string>
+ <string name="pref_mobileUpdate_images">Solo imágenes</string>
+ <string name="pref_mobileUpdate_everything">Todo</string>
<string name="refreshing_label">Actualizando</string>
<string name="flattr_settings_label">Ajustes de Flattr</string>
<string name="pref_flattr_auth_title">Identificarse en Flattr</string>
@@ -412,13 +463,13 @@
<string name="pref_compact_notification_buttons_title">Configurar botones en la pantalla de bloqueo</string>
<string name="pref_compact_notification_buttons_sum">Cambiar los botones en la pantalla de bloqueo. El botón reproducir/pausar siempre está incluido.</string>
<string name="pref_compact_notification_buttons_dialog_title">Seleccionar máximo %1$d elementos</string>
- <string name="pref_compact_notification_buttons_dialog_error">Sólo puedes seleccionar un máximo de %1$d elementos.</string>
+ <string name="pref_compact_notification_buttons_dialog_error">Sólo puede seleccionar un máximo de %1$d elementos.</string>
<string name="pref_lockscreen_background_title">Establecer fondo de pantalla de bloqueo</string>
<string name="pref_lockscreen_background_sum">Establecer el fondo de pantalla de bloqueo desde la imagen del episodio. Como efecto secundario, esto también mostrarán las imagen de aplicaciones de terceros.</string>
<string name="pref_showDownloadReport_title">Mostrar informe de descarga</string>
<string name="pref_showDownloadReport_sum">Si la descarga falla, generar un informe con los detalles del fallo</string>
<string name="pref_expand_notify_unsupport_toast">Las versiones de Android anteriores a la 4.1 no soportan notificaciones expandidas</string>
- <string name="pref_queueAddToFront_sum">Agregar nuevos episodios al principio de la cola.</string>
+ <string name="pref_queueAddToFront_sum">Añadir nuevos episodios al principio de la cola.</string>
<string name="pref_queueAddToFront_title">Poner al principio de la cola.</string>
<string name="pref_smart_mark_as_played_disabled">Deshabilitado</string>
<string name="pref_image_cache_size_title">Tamaño del almacenamiento de imágenes</string>
@@ -437,9 +488,10 @@
<string name="pref_cast_title">Soporte para Chromecast</string>
<string name="pref_cast_message_play_flavor">Habilitar soporte para reproducción remota en dispositivos Cast (como Chromecast, altavoces o Android TV)</string>
<string name="pref_cast_message_free_flavor">Chromecast requiere librerías propietarias de terceros que están deshabilitadas en esta versión de AntennaPod</string>
- <string name="pref_enqueue_downloaded_title">Agregar descargados a la cola</string>
- <string name="pref_enqueue_downloaded_summary">Agregar episodios descargados a la cola</string>
+ <string name="pref_enqueue_downloaded_title">Añadir descargados a la cola</string>
+ <string name="pref_enqueue_downloaded_summary">Añadir episodios descargados a la cola</string>
<string name="media_player_builtin">Reproductor Android integrado</string>
+ <string name="pref_skip_silence_title">Saltar silencio en audio</string>
<string name="pref_videoBehavior_title">Al salir del vídeo</string>
<string name="pref_videoBehavior_sum">Comportamiento al salir de la reproducción de video</string>
<string name="stop_playback">Parar reproducción</string>
@@ -451,10 +503,12 @@
<string name="back_button_open_drawer">Abrir el cajón de navegación</string>
<string name="back_button_double_tap">Tocar dos veces para salir</string>
<string name="back_button_show_prompt">Confirmar para salir</string>
- <string name="close_prompt">¿Estás seguro de que quieres cerrar AntennaPod?</string>
+ <string name="close_prompt">¿Está seguro de que quiere cerrar AntennaPod?</string>
<string name="double_tap_toast">Pulsar el botón de nuevo para salir</string>
<string name="back_button_go_to_page">Ir a la página...</string>
<string name="back_button_go_to_page_title">Seleccionar página</string>
+ <string name="pref_delete_removes_from_queue_title">Eliminar quita de la cola</string>
+ <string name="pref_delete_removes_from_queue_sum">Quitar automáticamente un episodio de la cola cuando se elimina.</string>
<!--Auto-Flattr dialog-->
<string name="auto_flattr_enable">Habilitar Flattr automático</string>
<string name="auto_flattr_after_percent">Valorar con Flattr el episodio cuando se haya reproducido el %d por ciento</string>
@@ -475,13 +529,13 @@
<string name="opml_import_option">Opción %1$d</string>
<string name="opml_import_explanation_1">Elegir un una ruta del sistema de ficheros local.</string>
<string name="opml_import_explanation_2">Usar una aplicación externa tipo Dropbox, Google Drive o su gestor de ficheros favorito para abrir un archivo OPML.</string>
- <string name="opml_import_explanation_3">Muchas aplicaciones como Google Mail, Dropbox, Google Drive y la mayoría de gestores de ficheros pueden <i>abrir</i> archivos OPML <i>de</i> AntennaPod.</string>
+ <string name="opml_import_explanation_3">Muchas aplicaciones como Google Mail, Dropbox, Google Drive y la mayoría de gestores de ficheros pueden <i>abrir</i> archivos OPML <i>con</i> AntennaPod.</string>
<string name="start_import_label">Comenzar la importación</string>
<string name="opml_import_label">Importar de OPML</string>
<string name="opml_directory_error">¡ERROR!</string>
<string name="reading_opml_label">Leyendo el archivo OPML</string>
<string name="opml_reader_error">Error al leer el documento OPML:</string>
- <string name="opml_import_error_no_file">¡Debes seleccionar un archivo!</string>
+ <string name="opml_import_error_no_file">¡Debe seleccionar un archivo!</string>
<string name="select_all_label">Seleccionar todo</string>
<string name="deselect_all_label">Deseleccionar todo</string>
<string name="select_options_label">Seleccionar…</string>
@@ -528,9 +582,9 @@
<string name="gpodnet_suggestions_header">SUGERENCIAS</string>
<string name="gpodnet_search_hint">Buscar en gpodder.net</string>
<string name="gpodnetauth_login_title">Iniciar sesión</string>
- <string name="gpodnetauth_login_descr">Bienvenidoinicio de sesión de gpodder.net. Primero, escriba sus datos de inicio de sesión:</string>
+ <string name="gpodnetauth_login_descr">Bienvenido al inicio de sesión de gpodder.net. Primero, escriba sus datos de inicio de sesión:</string>
<string name="gpodnetauth_login_butLabel">Iniciar sesión</string>
- <string name="gpodnetauth_login_register">Si aún no tienes una cuenta, puedes crearla en:\nhttps://gpodder.net/register/</string>
+ <string name="gpodnetauth_login_register">Si aún no tiene una cuenta, puede crearla en:\nhttps://gpodder.net/register/</string>
<string name="username_label">Usuario</string>
<string name="password_label">Contraseña</string>
<string name="gpodnetauth_device_title">Selección del dispositivo</string>
@@ -539,8 +593,8 @@
<string name="gpodnetauth_device_caption">Descripción</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>
+ <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>
<string name="gpodnetauth_device_caption_errorEmpty">El texto no puede estar en blanco</string>
<string name="gpodnetauth_device_butChoose">Elegir</string>
<string name="gpodnetauth_finish_title">¡Inicio de sesión correcto!</string>
@@ -557,10 +611,10 @@
<string name="selected_folder_label">Carpeta seleccionada</string>
<string name="create_folder_label">Crear carpeta</string>
<string name="choose_data_directory">Elegir carpeta de datos</string>
- <string name="choose_data_directory_message">Por favor elige la raíz de la carpeta de datos. AntennaPod creará los subdirectorios apropiados.</string>
+ <string name="choose_data_directory_message">Elija la raíz de la carpeta de datos. AntennaPod creará los subdirectorios apropiados.</string>
<string name="choose_data_directory_permission_rationale">Necesita acceso al almacenamiento externo para cambiar la carpeta de datos</string>
<string name="create_folder_msg">¿Crear carpeta con nombre \"%1$s\"?</string>
- <string name="create_folder_success">Carpeta creada</string>
+ <string name="create_folder_success">Carpeta nueva creada</string>
<string name="create_folder_error_no_write_access">No se puede escribir en esta carpeta</string>
<string name="create_folder_error_already_exists">Ya existe la carpeta</string>
<string name="create_folder_error">No se ha podido crear la carpeta</string>
@@ -647,6 +701,7 @@
<string name="audio_effects">Efectos de audio</string>
<string name="stereo_to_mono">Mezclar: de estéreo a mono</string>
<string name="sonic_only">Solo Sonic</string>
+ <string name="exoplayer_only">Sólo ExoPlayer</string>
<!--proxy settings-->
<string name="proxy_type_label">Tipo</string>
<string name="host_label">Host</string>
@@ -659,6 +714,8 @@
<string name="proxy_host_empty_error">El host no puede estar en blanco</string>
<string name="proxy_host_invalid_error">El host no es una dirección IP o dominio válido</string>
<string name="proxy_port_invalid_error">Puerto no válido</string>
+ <!--Subscriptions fragment-->
+ <string name="subscription_num_columns">Número de columnas</string>
<!--Database import/export-->
<string name="import_export">Importar/Exportar base de datos</string>
<string name="import_export_warning">Esta función experimental se puede usar para transferir sus suscripciones y episodios reproducidos a otro dispositivo.\n\nLas bases de datos exportadas solo se pueden importar cuando se usa la misma versión de AntennaPod. En otro caso, esta función podría provocar un comportamiento inesperado.\n\nDespués de la importación, los episodios podrían mostrarse como descargados cuando no lo están. Presione el botón de reproducción de los episodios para que AntennaPod lo detecte.</string>
diff --git a/core/src/main/res/values-et/strings.xml b/core/src/main/res/values-et/strings.xml
index fd48b698f..99e61a5fa 100644
--- a/core/src/main/res/values-et/strings.xml
+++ b/core/src/main/res/values-et/strings.xml
@@ -481,6 +481,7 @@
<string name="proxy_host_empty_error">Hostinimi ei saa olla tühi</string>
<string name="proxy_host_invalid_error">Se pole korrektne IP aadress või domeen</string>
<string name="proxy_port_invalid_error">Port pole korrektne</string>
+ <!--Subscriptions fragment-->
<!--Database import/export-->
<string name="import_export">Andmebaasi importimine/eksportimine</string>
<string name="label_import">Impordi</string>
diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml
index df00e67c5..42fe07f68 100644
--- a/core/src/main/res/values-fr/strings.xml
+++ b/core/src/main/res/values-fr/strings.xml
@@ -40,7 +40,7 @@
<string name="drawer_feed_order_unplayed_episodes">Trier par compteur</string>
<string name="drawer_feed_order_alphabetical">Trier alphabétiquement</string>
<string name="drawer_feed_order_last_update">Trier par date de publication</string>
- <string name="drawer_feed_order_most_played">Trier par nombre d\'épisodes lus</string>
+ <string name="drawer_feed_order_most_played">Trier par nombre lus</string>
<string name="drawer_feed_counter_new_unplayed">Nombre de nouveaux épisodes non-lus</string>
<string name="drawer_feed_counter_new">Nombre de nouveaux épisodes</string>
<string name="drawer_feed_counter_unplayed">Nombre d\'épisodes non-lus</string>
@@ -108,7 +108,7 @@
<string name="feedurl_label">Lien du flux</string>
<string name="etxtFeedurlHint">www.example.com/feed</string>
<string name="txtvfeedurl_label">Ajouter un podcast à partir de son lien</string>
- <string name="podcastdirectories_label">Trouver le podcast dans la bibliothèque</string>
+ <string name="podcastdirectories_label">Trouver un podcast</string>
<string name="podcastdirectories_descr">Pour de nouveaux podcasts vous pouvez chercher iTunes ou fyyd ou parcourir gpodder.net par nom, catégorie ou popularité.</string>
<string name="browse_gpoddernet_label">Chercher sur gpodder.net</string>
<!--Actions on feeds-->
@@ -139,9 +139,9 @@
<string name="batch_edit">Edition groupée</string>
<string name="select_all_above">Sélectionner avec ceux au-dessus</string>
<string name="select_all_below">Sélectionner avec ceux en-dessous</string>
- <string name="hide_unplayed_episodes_label">Non lus</string>
+ <string name="hide_unplayed_episodes_label">Non lu</string>
<string name="hide_paused_episodes_label">En pause</string>
- <string name="hide_played_episodes_label">Lus</string>
+ <string name="hide_played_episodes_label">Lu</string>
<string name="hide_queued_episodes_label">Dans la liste de lecture</string>
<string name="hide_not_queued_episodes_label">Pas dans la liste de lecture</string>
<string name="hide_downloaded_episodes_label">Téléchargé</string>
@@ -216,7 +216,7 @@
<string name="download_error_file_error">Accès au fichier impossible</string>
<string name="download_error_http_data_error">Erreur de données HTTP</string>
<string name="download_error_error_unknown">Erreur inconnue</string>
- <string name="download_error_parser_exception">Exception de l\'analyseur</string>
+ <string name="download_error_parser_exception">Message d\'erreur</string>
<string name="download_error_unsupported_type">Type de flux non géré</string>
<string name="download_error_connection_error">Erreur de connexion</string>
<string name="download_error_unknown_host">Hôte inconnu</string>
@@ -319,16 +319,16 @@
<string name="enable_sonic">Activer Sonic</string>
<!--Empty list labels-->
<string name="no_items_header_label">Aucun épisode dans la liste de lecture</string>
- <string name="no_items_label">Vous pouvez ajouter des épisodes à la liste de lecture par une pression longue ou en les téléchargeant.</string>
+ <string name="no_items_label">Pour ajouter un épisode, téléchargez le ou faites une pression longue dessus et taper sur \"Ajouter à la liste de lecture\".</string>
<string name="no_feeds_label">Vous n\'êtes encore abonné à aucun podcast.</string>
- <string name="no_chapters_label">Cet épisode n\'a pas de chapitres.</string>
+ <string name="no_chapters_label">Cet épisode n\'a pas de chapitre.</string>
<string name="no_shownotes_label">Aucune notes pour cet épisode.</string>
<string name="no_run_downloads_head_label">Aucun téléchargement en cours</string>
<string name="no_run_downloads_label">Vous pouvez télécharger des épisodes à partir du détail d\'un podcast.</string>
<string name="no_comp_downloads_head_label">Aucun épisode téléchargé</string>
<string name="no_comp_downloads_label">Vous pouvez télécharger des épisodes à partir du détail d\'un podcast.</string>
- <string name="no_log_downloads_head_label">Aucun téléchargement historisé</string>
- <string name="no_log_downloads_label">L\'historique des téléchargements apparaîtra dès qu\'il ne sera pas vide. </string>
+ <string name="no_log_downloads_head_label">Aucun téléchargement dans l\'historique</string>
+ <string name="no_log_downloads_label">L\'historique des téléchargements apparaîtra quand il ne sera plus vide. </string>
<string name="no_history_head_label">Aucun historique</string>
<string name="no_history_label">Après avoir écouté un épisode il apparaîtra ici.</string>
<string name="no_all_episodes_head_label">Aucun épisode</string>
@@ -358,8 +358,8 @@
<string name="pref_episode_cleanup_title">Nettoyage des épisodes</string>
<string name="pref_episode_cleanup_summary">Les épisodes qui ne sont pas dans la liste de lecture et qui ne sont pas marqués comme favoris peuvent être supprimés si l\'espace est insuffisant pour le téléchargement automatique de nouveaux épisodes</string>
<string name="pref_pauseOnDisconnect_sum">Interrompre la lecture lorsque le casque ou le bluetooth sont déconnectés</string>
- <string name="pref_unpauseOnHeadsetReconnect_sum">Reprendre la lecture quand les écouteurs sont connectés</string>
- <string name="pref_unpauseOnBluetoothReconnect_sum">Reprendre la lecture quand le Bluetooth se connecte</string>
+ <string name="pref_unpauseOnHeadsetReconnect_sum">Reprendre la lecture quand des écouteurs sont branchés</string>
+ <string name="pref_unpauseOnBluetoothReconnect_sum">Reprendre la lecture quand le Bluetooth se reconnecte</string>
<string name="pref_hardwareForwardButtonSkips_title">Le bouton \"saut avant\" saute l\'épisode</string>
<string name="pref_hardwareForwardButtonSkips_sum">Passer à l\'épisode suivant au lieu de faire un saut avant quand \"saut avant\" est pressé sur un périphérique bluetooth</string>
<string name="pref_hardwarePreviousButtonRestarts_title">Le bouton \"saut arrière\" redémarre l\'épisode</string>
@@ -456,7 +456,7 @@
<string name="pref_rewind_sum">Nombre de secondes à sauter quand le bouton \"saut arrière\" est pressé</string>
<string name="pref_gpodnet_sethostname_title">Choisir un nom de domaine</string>
<string name="pref_gpodnet_sethostname_use_default_host">Utiliser le nom de domaine par défaut</string>
- <string name="pref_expandNotify_title">Haute priorité de notification</string>
+ <string name="pref_expandNotify_title">Priorité haute de notification</string>
<string name="pref_expandNotify_sum">Permet, généralement, d\'étendre la notification pour montrer les boutons de lecture</string>
<string name="pref_persistNotify_title">Boutons de lecture permanents</string>
<string name="pref_persistNotify_sum">Garder les notifications et les boutons de lecture sur l\'écran de verouillage quand la lecture est en pause</string>
@@ -491,13 +491,13 @@
<string name="pref_enqueue_downloaded_title">Ajouter à la liste après téléchargement</string>
<string name="pref_enqueue_downloaded_summary">Mettre les épisodes dans la la liste de lecture après téléchargement</string>
<string name="media_player_builtin">Lecteur natif d\'Android</string>
- <string name="pref_skip_silence_title">Sauter les silences audios</string>
+ <string name="pref_skip_silence_title">Supprimer les silences audios</string>
<string name="pref_videoBehavior_title">Sorti du lecteur pendant une vidéo</string>
<string name="pref_videoBehavior_sum">Définir ce qu\'il se passe si une vidéo est quittée pendant sa lecture</string>
<string name="stop_playback">Arrêter la lecture</string>
<string name="continue_playback">Continuer la lecture</string>
<string name="behavior">Comportement</string>
- <string name="pref_back_button_behavior_title">Comportement Bouton Retour</string>
+ <string name="pref_back_button_behavior_title">Comportement du bouton retour</string>
<string name="pref_back_button_behavior_sum">Change le comportement du bouton retour</string>
<string name="back_button_default">Défaut</string>
<string name="back_button_open_drawer">Ouvrir le volet de navigation</string>
@@ -508,7 +508,7 @@
<string name="back_button_go_to_page">Aller à la page...</string>
<string name="back_button_go_to_page_title">Sélectionner une page</string>
<string name="pref_delete_removes_from_queue_title">Supprimer retire de la liste de lecture</string>
- <string name="pref_delete_removes_from_queue_sum">Retirer l\'épisode de la liste de lecture quand il est supprimé.</string>
+ <string name="pref_delete_removes_from_queue_sum">Retirer de la liste de lecture les épisodes quand ils sont supprimés.</string>
<!--Auto-Flattr dialog-->
<string name="auto_flattr_enable">Activer le paiement flattr automatique</string>
<string name="auto_flattr_after_percent">Lancer un paiement flattr quand %d pourcent de l\'épisode a été lu</string>
@@ -661,7 +661,7 @@
<string name="filter">Filtrer</string>
<string name="search_fyyd_label">Chercher sur fyyd</string>
<!--Episodes apply actions-->
- <string name="all_label">Tout</string>
+ <string name="all_label">Tous</string>
<string name="selected_all_label">Tous les épisodes ont été sélectionné</string>
<string name="none_label">Aucun</string>
<string name="deselected_all_label">Tous les épisodes ont été désélectionné</string>
@@ -714,6 +714,8 @@
<string name="proxy_host_empty_error">Hôte ne peut pas être vide</string>
<string name="proxy_host_invalid_error">L\'hôte n\'est pas une adresse IP ou un domaine valide</string>
<string name="proxy_port_invalid_error">Port non valide</string>
+ <!--Subscriptions fragment-->
+ <string name="subscription_num_columns">Nombre de colonnes</string>
<!--Database import/export-->
<string name="import_export">Import / Export de la base de données</string>
<string name="import_export_warning">Cette fonction expérimentale peut-être utilisée pour transférer vos abonnements et épisodes lus sur un autre appareil.\n\nLes bases de données exportées peuvent uniquement être importées sur la même version d\'AntennaPod. Dans le cas contraire, des dysfonctionnements peuvent apparaître.\n\nAprès import, il est possible que des épisodes apparaissent téléchargés alors qu\'ils ne le sont pas. Appuyer sur le bouton de lecture pour qu\'AntennaPod le détecte.</string>
diff --git a/core/src/main/res/values-gl-rES/strings.xml b/core/src/main/res/values-gl-rES/strings.xml
index 5bfe69bdc..369d39d4c 100644
--- a/core/src/main/res/values-gl-rES/strings.xml
+++ b/core/src/main/res/values-gl-rES/strings.xml
@@ -69,7 +69,7 @@
<string name="error_msg_prefix">Produciuse un fallo:</string>
<string name="needs_storage_permission">Precísase o permiso de almacenamento para esta operación</string>
<string name="refresh_label">Actualizar</string>
- <string name="external_storage_error_msg">Non se dispón de almacenamento externo. Por favor asegúrese de que o almacenamento externo está montado e así o aplicativo poderá funcionar correctamente.</string>
+ <string name="external_storage_error_msg">Non se dispón de almacenamento externo. Por favor asegúrese de que o almacenamento externo está montado e así a aplicación poderá funcionar correctamente.</string>
<string name="chapters_label">Capítulos</string>
<string name="chapter_duration">Duración: %1$s</string>
<string name="shownotes_label">Notas do episodio</string>
@@ -95,10 +95,15 @@
<string name="episode_cleanup_never">Nunca</string>
<string name="episode_cleanup_queue_removal">Cando non esté na cola</string>
<string name="episode_cleanup_after_listening">Tras rematar</string>
+ <plurals name="episode_cleanup_hours_after_listening">
+ <item quantity="one">1 hora tras rematar</item>
+ <item quantity="other">%d horas tras rematar</item>
+ </plurals>
<plurals name="episode_cleanup_days_after_listening">
<item quantity="one">1 día despois de rematar</item>
<item quantity="other">%d días despois de rematar</item>
</plurals>
+ <string name="num_selected_label">%d escollido</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">URL da fonte</string>
<string name="etxtFeedurlHint">www.example.com/feed</string>
@@ -148,6 +153,10 @@
<string name="open_podcast">Abrir podcast</string>
<!--actions on feeditems-->
<string name="download_label">Descargar</string>
+ <plurals name="downloading_batch_label">
+ <item quantity="one">Descargando %d episodio</item>
+ <item quantity="other">Descargando %d episodios</item>
+ </plurals>
<string name="play_label">Reproducir</string>
<string name="pause_label">Pausar</string>
<string name="stop_label">Parar</string>
@@ -155,14 +164,35 @@
<string name="remove_label">Eliminar</string>
<string name="delete_label">Borrar</string>
<string name="delete_failed">Non se puido eliminar o ficheiro. Reiniciar o dispositivo podería axudar.</string>
+ <string name="delete_episode_label">Eliminar episodio</string>
+ <plurals name="deleted_episode_batch_label">
+ <item quantity="one">%d episodio eliminado.</item>
+ <item quantity="other">%d episodios eliminados.</item>
+ </plurals>
<string name="mark_as_seen_label">Marcar como visto</string>
<string name="marked_as_seen_label">Marcar como visto</string>
<string name="mark_read_label">Marcar como reproducido</string>
<string name="marked_as_read_label">Marcado como reproducido</string>
+ <plurals name="marked_read_batch_label">
+ <item quantity="one">%d episodio marcado como reproducido.</item>
+ <item quantity="other">%d episodios marcados como reproducidos.</item>
+ </plurals>
<string name="mark_unread_label">Marcar como non reproducido</string>
+ <plurals name="marked_unread_batch_label">
+ <item quantity="one">%d episodio marcado como non reproducido.</item>
+ <item quantity="other">%d episodios marcados como non reproducidos.</item>
+ </plurals>
<string name="add_to_queue_label">Engadir a cola</string>
<string name="added_to_queue_label">Engadido a cola</string>
+ <plurals name="added_to_queue_batch_label">
+ <item quantity="one">%d episodio engadido a cola.</item>
+ <item quantity="other">%d episodios engadidos a cola.</item>
+ </plurals>
<string name="remove_from_queue_label">Quitar da cola</string>
+ <plurals name="removed_from_queue_batch_label">
+ <item quantity="one">%d episodio eliminado da cola.</item>
+ <item quantity="other">%d episodios elimnados da cola.</item>
+ </plurals>
<string name="add_to_favorite_label">Engadir a favoritos</string>
<string name="added_to_favorites">Engadido a favoritos</string>
<string name="remove_from_favorite_label">Quitar dos favoritos</string>
@@ -214,6 +244,7 @@
<string name="download_type_media">Ficheiro de medios</string>
<string name="download_type_image">Imaxe</string>
<string name="download_request_error_dialog_message_prefix">Houbo un fallo intentando descargar o ficheiro:\u0020</string>
+ <string name="null_value_podcast_error">Non se proporcionou ningún podcast que se poida mostrar.</string>
<string name="authentication_notification_title">Precísase autenticación</string>
<string name="authentication_notification_msg">O recurso solicitado require un usuario e contrasinal</string>
<string name="confirm_mobile_download_dialog_title">Confirme a descarga con datos do móbil</string>
@@ -259,15 +290,15 @@
<string name="flattr_auth_explanation">Pulse o botón inferior para iniciar o proceso de autenticación. Será redireccionado a pantalla de conexión en Flattr no seu navegador e pediralle permiso para que AntennaPod poida acceder. Despois de dar permiso, voltará a esta pantalla de xeito automático.</string>
<string name="authenticate_label">Autenticar</string>
<string name="return_home_label">Voltar ao inicio</string>
- <string name="flattr_auth_success">Autenticouse correctamente! Xa pode enviar valoracións a Flattr desde o aplicativo.</string>
+ <string name="flattr_auth_success">Autenticouse correctamente! Xa pode enviar valoracións a Flattr desde a aplicación.</string>
<string name="no_flattr_token_title">Non se atopou o testemuño de Flattr</string>
<string name="no_flattr_token_notification_msg">A súa conta de Flattr non semella estar conectada a AntennaPod. Toque aquí para autenticarse.</string>
- <string name="no_flattr_token_msg">A súa conta de Flattr non semella estar conectada a AntennaPod. Ben pode conectar a súa conta a AntennaPod para interactuar en Flattr desde o aplicativo ou ben pode visitar o sitio web do elemento e darlle ao flattr desde alí.</string>
+ <string name="no_flattr_token_msg">A súa conta de Flattr non semella estar conectada a AntennaPod. Ben pode conectar a súa conta a AntennaPod para interactuar en Flattr desde a aplicación ou ben pode visitar o sitio web do elemento e darlle ao flattr desde alí.</string>
<string name="authenticate_now_label">Autenticar</string>
<string name="action_forbidden_title">Acción non permitida</string>
<string name="action_forbidden_msg">AntennaPod non ten permiso para esta acción. A razón podería ser que o testemuño de acceso de AntennaPod ou a súa conta fosen rexeitados. Pode voltar a autenticarse ou visitar o sitio web do elemento.</string>
<string name="access_revoked_title">Acceso rexeitado</string>
- <string name="access_revoked_info">Eliminou correctamente o token de acceso de AntennaPod á súa conta. Para completar o proceso deberá eliminar este aplicativo da lista de aplicativos autorizados nos axustes da súa conta na web de Flattr.</string>
+ <string name="access_revoked_info">Eliminou correctamente o token de acceso de AntennaPod á súa conta. Para completar o proceso deberá eliminar esta aplicación da lista de aplicacións autorizadas nos axustes da súa conta na web de Flattr.</string>
<!--Flattr-->
<string name="flattr_click_success">Flateraches algo!</string>
<string name="flattr_click_success_count">Flateraches %d cousas!</string>
@@ -287,9 +318,25 @@
<string name="set_playback_speed_label">Velocidade de reproducións</string>
<string name="enable_sonic">Habilitar Sonic</string>
<!--Empty list labels-->
+ <string name="no_items_header_label">Sen episodios na cola</string>
+ <string name="no_items_label">Engada un episodio descargándoo, ou manteña preso un episodio e escolla \"Engadir a cola\".</string>
<string name="no_feeds_label">Aínda non está subscrito a ningún podcast.</string>
<string name="no_chapters_label">Este episodio non ten capítulos.</string>
<string name="no_shownotes_label">Este episodio non ten notas de episodio.</string>
+ <string name="no_run_downloads_head_label">Sen descargas activas</string>
+ <string name="no_run_downloads_label">Pode descargar episodios na pantalla con detalles do episodio.</string>
+ <string name="no_comp_downloads_head_label">Sen episodios descargados</string>
+ <string name="no_comp_downloads_label">Pode descargar episodios na pantalla de detalles do podcast.</string>
+ <string name="no_log_downloads_head_label">Sen rexistro da descarga</string>
+ <string name="no_log_downloads_label">Os rexistros de descarga aparecerán aquí se están dispoñibles.</string>
+ <string name="no_history_head_label">Sen Historial</string>
+ <string name="no_history_label">Tras a escoita de un episodio, aparecerá aquí.</string>
+ <string name="no_all_episodes_head_label">Sen episodios</string>
+ <string name="no_all_episodes_label">Cando engade un podcast, os episodios mostraranse aquí.</string>
+ <string name="no_new_episodes_head_label">Sen episodios novos</string>
+ <string name="no_new_episodes_label">Cando reciba novos episodios, mostraranse aquí.</string>
+ <string name="no_fav_episodes_head_label">Sen episodios favoritos</string>
+ <string name="no_fav_episodes_label">Pode engadir episodios aos favoritos manténdoos pulsados.</string>
<!--Preferences-->
<string name="storage_pref">Almacenamento</string>
<string name="project_pref">Proxecto</string>
@@ -302,6 +349,7 @@
<string name="automation">Automatizado</string>
<string name="download_pref_details">Detalles</string>
<string name="import_export_pref">Importar/Exportar</string>
+ <string name="import_export_search_keywords">respaldar, restaurar</string>
<string name="appearance">Aspecto</string>
<string name="external_elements">Elementos externos</string>
<string name="interruptions">Interrupcións</string>
@@ -343,14 +391,17 @@
<string name="pref_unpauseOnBluetoothReconnect_title">Reconexión bluetooth</string>
<string name="pref_mobileUpdate_title">Actualizacións Móbil</string>
<string name="pref_mobileUpdate_sum">Permitir actualizacións sobre a rede de datos do móbil</string>
+ <string name="pref_mobileUpdate_nothing">Nada</string>
+ <string name="pref_mobileUpdate_images">Só imaxes</string>
+ <string name="pref_mobileUpdate_everything">Todo</string>
<string name="refreshing_label">Actualizando</string>
<string name="flattr_settings_label">Axustes Flattr</string>
<string name="pref_flattr_auth_title">Conexión Flattr</string>
- <string name="pref_flattr_auth_sum">Conéctese a súa conta Flattr para interactuar desde o aplicativo.</string>
- <string name="pref_flattr_this_app_title">Flattr este aplicativo</string>
+ <string name="pref_flattr_auth_sum">Conéctese a súa conta Flattr para interactuar desde a aplicación..</string>
+ <string name="pref_flattr_this_app_title">Flattr esta App</string>
<string name="pref_flattr_this_app_sum">Axude ao desenvolvemento de AntennaPod comentandoo en Flattr. Grazas!</string>
<string name="pref_revokeAccess_title">Retirar acceso</string>
- <string name="pref_revokeAccess_sum">Retirar o permiso de acceso a súa conta Flattr en este aplicativo.</string>
+ <string name="pref_revokeAccess_sum">Retirar o permiso de acceso a súa conta Flattr en esta aplicación..</string>
<string name="pref_auto_flattr_title">Flattr automático</string>
<string name="pref_auto_flattr_sum">Configure o flattr automático</string>
<string name="user_interface_label">Interface de usuaria</string>
@@ -414,7 +465,7 @@
<string name="pref_compact_notification_buttons_dialog_title">Escolla un máximo de %1$d elementos</string>
<string name="pref_compact_notification_buttons_dialog_error">Só pode selecionar un máximo de %1$d elementos.</string>
<string name="pref_lockscreen_background_title">Establecer fondo da pantalla de bloqueo</string>
- <string name="pref_lockscreen_background_sum">Establecer o fondo de pantalla de bloqueo coa imaxe do episodio actual. Como consecuencia, esto tamén mostrará a imaxe en aplicativos de terceiros.</string>
+ <string name="pref_lockscreen_background_sum">Establecer o fondo de pantalla de bloqueo coa imaxe do episodio actual. Como consecuencia, esto tamén mostrará a imaxe en aplicacións de terceiros.</string>
<string name="pref_showDownloadReport_title">Mostrar informe de descarga</string>
<string name="pref_showDownloadReport_sum">Si falla a descarga, xerar un informe que informe dos detalles do fallo.</string>
<string name="pref_expand_notify_unsupport_toast">As versións de Android anteriores a 4.1 non teñen soporte para notificacións expandidas.</string>
@@ -424,7 +475,7 @@
<string name="pref_image_cache_size_title">Tamaño da caché de imaxes</string>
<string name="pref_image_cache_size_sum">Tamaño da caché en disco para as imaxes.</string>
<string name="crash_report_title">Informe de Desgracias</string>
- <string name="crash_report_sum">Enviar por email o informe de fallo xeral no aplicativo</string>
+ <string name="crash_report_sum">Enviar por correo-e o informe de fallo xeral na aplicación</string>
<string name="send_email">Enviar email</string>
<string name="experimental_pref">En probas</string>
<string name="pref_media_player_message">Escolla o reprodutor de medios para reproducir ficheiros</string>
@@ -440,6 +491,7 @@
<string name="pref_enqueue_downloaded_title">Foron descargados os elementos da cola</string>
<string name="pref_enqueue_downloaded_summary">Engadir os episodios descargados a cola</string>
<string name="media_player_builtin">Reprodutor android nativo</string>
+ <string name="pref_skip_silence_title">Saltar silencio no Audio</string>
<string name="pref_videoBehavior_title">Ao saír do vídeo</string>
<string name="pref_videoBehavior_sum">Comportamento cando saia do vídeo</string>
<string name="stop_playback">Para a reprodución</string>
@@ -455,6 +507,8 @@
<string name="double_tap_toast">Tocar o botón Atrás outra vez para saír</string>
<string name="back_button_go_to_page">Ir á páxina...</string>
<string name="back_button_go_to_page_title">Seleccionar páxina</string>
+ <string name="pref_delete_removes_from_queue_title">Eliminar quita da Cola</string>
+ <string name="pref_delete_removes_from_queue_sum">Eliminar automáticamente un episodio da cola cando se elimina.</string>
<!--Auto-Flattr dialog-->
<string name="auto_flattr_enable">Hablitar o flattring automático</string>
<string name="auto_flattr_after_percent">Flattr o episodio tan pronto como o %d por cento foi reproducido</string>
@@ -475,7 +529,7 @@
<string name="opml_import_option">Opción %1$d</string>
<string name="opml_import_explanation_1">Escolla unha ruta de ficheiro concreta no sistema de ficheiros local.</string>
<string name="opml_import_explanation_2">Utilice unha aplicación externa como Dropbox, Google Drive ou o seu xestor de ficheiros para abrir un ficheiro OPML.</string>
- <string name="opml_import_explanation_3">Moitos aplicativos como Google Mail, Dropbox, Google Drive e a maioría dos xestores de ficheiros poden <i>abrir</i> ficheiros OPML <i>con</i> AntennaPod.</string>
+ <string name="opml_import_explanation_3">Moitas aplicacións, como Google Mail, Dropbox, Google Drive e a maioría dos xestores de ficheiros poden <i>abrir</i> ficheiros OPML <i>con</i> AntennaPod.</string>
<string name="start_import_label">Iniciar a importación</string>
<string name="opml_import_label">Importar OPML</string>
<string name="opml_directory_error">FALLO!</string>
@@ -486,7 +540,7 @@
<string name="deselect_all_label">Deseleccionar todo</string>
<string name="select_options_label">Seleccionar...</string>
<string name="choose_file_from_filesystem">Desde sistema local de ficheiros</string>
- <string name="choose_file_from_external_application">Utilizar aplicativo externo</string>
+ <string name="choose_file_from_external_application">Utilizar aplicacións externa</string>
<string name="opml_export_label">Exportar OPML</string>
<string name="html_export_label">Exportar HTML</string>
<string name="exporting_label">Exportando...</string>
@@ -570,7 +624,7 @@
<string name="folder_not_empty_dialog_title">O cartafol non está baldeiro</string>
<string name="folder_not_empty_dialog_msg">O cartafol escollido non está baldeiro. As descargas de medios e outros ficheiros situaranse directamente en este cartafol. Proceder de todos xeitos?</string>
<string name="set_to_default_folder">Escolla o cartafol por omisión</string>
- <string name="pref_pausePlaybackForFocusLoss_sum">Pausar a reprodución en lugar de baixar o volume cando outro aplicativo quere reproducir un son.</string>
+ <string name="pref_pausePlaybackForFocusLoss_sum">Pausar a reprodución en lugar de baixar o volume cando outra aplicación quere reproducir un son.</string>
<string name="pref_pausePlaybackForFocusLoss_title">Pausa para interrupcións</string>
<string name="pref_resumeAfterCall_sum">Retomar a reprodución despois de rematar a chamada telefónica</string>
<string name="pref_resumeAfterCall_title">Retomar despois da chamada</string>
@@ -602,7 +656,7 @@
<!--Progress information-->
<string name="progress_upgrading_database">Actualizando a base de datos</string>
<!--AntennaPodSP-->
- <string name="sp_apps_importing_feeds_msg">Importando as subscricións desde aplicativos de propósito único...</string>
+ <string name="sp_apps_importing_feeds_msg">Importando as subscricións desde aplicacións de propósito único...</string>
<string name="search_itunes_label">Buscar en iTunes</string>
<string name="filter">Filtrado</string>
<string name="search_fyyd_label">Buscar en fyyd</string>
@@ -647,6 +701,7 @@
<string name="audio_effects">Efectos de son</string>
<string name="stereo_to_mono">Comprimir: stereo a mono</string>
<string name="sonic_only">Só Sonic</string>
+ <string name="exoplayer_only">Só ExoPlayer</string>
<!--proxy settings-->
<string name="proxy_type_label">Tipo</string>
<string name="host_label">Servidor</string>
@@ -659,6 +714,8 @@
<string name="proxy_host_empty_error">Servidor non pode quedar baldeiro</string>
<string name="proxy_host_invalid_error">O servidor indicado non é un dominio ou IP válidos</string>
<string name="proxy_port_invalid_error">Porto non válido</string>
+ <!--Subscriptions fragment-->
+ <string name="subscription_num_columns">Número de columnas</string>
<!--Database import/export-->
<string name="import_export">Importar/Exportar base de datos</string>
<string name="import_export_warning">Esta función experimental utilízase para transferir as súas subscricións e episodios reproducidos noutro dispositivo.\n\nAs bases de datos exportadas só se poden importar se utiliza a misma versión de AntennaPod. De todos xeitos, esta función pode comportarse de xeito raro.\n\nDespois de importar, os episodios poderían ser mostrados como descargados sin telo sido. Simplemente pulse o botón de reprodución dos episodios para que AntennaPod detecte esto.</string>
@@ -677,7 +734,7 @@
<!--<string name="cast_failed_to_connect">Could not connect to the device</string>-->
<string name="cast_failed_setting_volume">Non se puido establecer o volume</string>
<string name="cast_failed_no_connection">Non hai conexión ao dispositivo de emisión</string>
- <string name="cast_failed_no_connection_trans">Perdeuse a conexión ao dispositivo de emisión. O aplicativo está a intentar restablecela se fose posible. Por favor, agarde uns segundos e inténteo de novo.</string>
+ <string name="cast_failed_no_connection_trans">Perdeuse a conexión ao dispositivo de emisión. A aplicación está a intentar restablecela se fose posible. Por favor, agarde uns segundos e inténteo de novo.</string>
<string name="cast_failed_perform_action">Non se puido completar a acción</string>
<string name="cast_failed_status_request">Fallo de sincronización co dispositivo de emisión</string>
<string name="cast_failed_seek">Non se puido cambiar a posición no dispositivo de emisión</string>
diff --git a/core/src/main/res/values-hi-rIN/strings.xml b/core/src/main/res/values-hi-rIN/strings.xml
index 849626e45..17a26e125 100644
--- a/core/src/main/res/values-hi-rIN/strings.xml
+++ b/core/src/main/res/values-hi-rIN/strings.xml
@@ -399,6 +399,7 @@
<!--Rating dialog-->
<!--Audio controls-->
<!--proxy settings-->
+ <!--Subscriptions fragment-->
<!--Database import/export-->
<!--Casting-->
<!--<string name="cast_failed_to_connect">Could not connect to the device</string>-->
diff --git a/core/src/main/res/values-hu/strings.xml b/core/src/main/res/values-hu/strings.xml
index 012d2830f..7c252a0db 100644
--- a/core/src/main/res/values-hu/strings.xml
+++ b/core/src/main/res/values-hu/strings.xml
@@ -363,6 +363,7 @@
<string name="proxy_test_failed">Teszt sikertelen</string>
<string name="proxy_host_empty_error">Kiszolgáló nem lehet üres</string>
<string name="proxy_port_invalid_error">Port nem helyes</string>
+ <!--Subscriptions fragment-->
<!--Database import/export-->
<string name="import_export">Adatbázis importálása/exportálása</string>
<string name="label_import">Importálás</string>
diff --git a/core/src/main/res/values-it/strings.xml b/core/src/main/res/values-it/strings.xml
index d88d19d36..31f252d3e 100644
--- a/core/src/main/res/values-it/strings.xml
+++ b/core/src/main/res/values-it/strings.xml
@@ -124,7 +124,7 @@
<string name="feed_info_label">Info podcast</string>
<string name="feed_settings_label">Impostazioni podcast</string>
<string name="rename_feed_label">Rinomina podcast</string>
- <string name="remove_feed_label">Cancella podcast</string>
+ <string name="remove_feed_label">Rimuovi podcast</string>
<string name="share_label">Condividi...</string>
<string name="share_link_label">Condividi URL Episodio</string>
<string name="share_link_with_position_label">Condividi URL dell\'episodio con la posizione</string>
@@ -319,7 +319,6 @@
<string name="enable_sonic">Abilita Sonic</string>
<!--Empty list labels-->
<string name="no_items_header_label">Nessun episodio in coda</string>
- <string name="no_items_label">Puoi aggiungere episodi alla coda tenendo premuto o scaricandoli.</string>
<string name="no_feeds_label">Non sei ancora abbonato a nessun podcast. </string>
<string name="no_chapters_label">Questo episodio non ha capitoli.</string>
<string name="no_shownotes_label">Questo episodio non ha note.</string>
@@ -714,6 +713,7 @@
<string name="proxy_host_empty_error">L\'host non può essere vuoto</string>
<string name="proxy_host_invalid_error">L\'host non è un IP o un dominio valido</string>
<string name="proxy_port_invalid_error">Porta non valida</string>
+ <!--Subscriptions fragment-->
<!--Database import/export-->
<string name="import_export">Importa/Esporta database</string>
<string name="import_export_warning">Questa funzione sperimentale può essere usata per trasferire le sottoscrizioni e gli episoti completati ad un altro dispositivo.\n\nIl database potrà essere importato solo se si usa la stessa versione di AntennaPod, altrimenti potrebbero generarsi comportamenti anomali.\n\nDopo l\'importazione, gli episodi potrebbero essere mostrati come scaricati anche se non lo sono. Basta premere Play per farli riconoscere ad AntennaPod.</string>
diff --git a/core/src/main/res/values-iw-rIL/strings.xml b/core/src/main/res/values-iw-rIL/strings.xml
index d062a4490..e9d14b899 100644
--- a/core/src/main/res/values-iw-rIL/strings.xml
+++ b/core/src/main/res/values-iw-rIL/strings.xml
@@ -337,7 +337,7 @@
<string name="enable_sonic">הפעלת Sonic</string>
<!--Empty list labels-->
<string name="no_items_header_label">אין פרקים בתור</string>
- <string name="no_items_label">ניתן להוסיף פרקים לתור בלחיצה ארוכה או על ידי הורדתם.</string>
+ <string name="no_items_label">ניתן להוסיף פרק על ידי הורדתו או ללחוץ על פרק לחיצה ארוכה ולבחור ב־„הוספה לתור”.</string>
<string name="no_feeds_label">לא נרשמת לאף פודקאסט עדיין.</string>
<string name="no_chapters_label">לפרק זה אין פרקים.</string>
<string name="no_shownotes_label">לפרק זה אין הערות פרק.</string>
@@ -738,6 +738,8 @@
<string name="proxy_host_empty_error">המארח לא יכול להישאר ריק</string>
<string name="proxy_host_invalid_error">כתובת המארח אינה כתובת IP או שם מתחם תקניים</string>
<string name="proxy_port_invalid_error">הפתחה אינה תקנית</string>
+ <!--Subscriptions fragment-->
+ <string name="subscription_num_columns">מספר העמודות</string>
<!--Database import/export-->
<string name="import_export">ייבוא/ייצוא מסד נתונים</string>
<string name="import_export_warning">תכונה ניסיונית זו יכולה לשמש לטובת העברת המינויים והפרקים שניגנת להתקן אחר.\n\nניתן לייבא מסדי נתונים שיוצאו רק לאותה הגרסה של אנטנה־פּוֹד. אחרת, תכונה זו עשויה לגרור התנהגות בלתי צפויה.\n\nלאחר הייבוא, יתכן שחלק מהפרקים יופיעו כאילו כבר הורדת אותם למרות שבפועל לא עשית זאת. עליך פשוט ללחוץ על כפתור הנגינה של הפרקים כדי שאנטנה־פּוֹד יוכל לזהות זאת.</string>
diff --git a/core/src/main/res/values-ja/strings.xml b/core/src/main/res/values-ja/strings.xml
index 9f647e152..f749de958 100644
--- a/core/src/main/res/values-ja/strings.xml
+++ b/core/src/main/res/values-ja/strings.xml
@@ -310,7 +310,7 @@
<string name="enable_sonic">Sonic を有効にする</string>
<!--Empty list labels-->
<string name="no_items_header_label">エピソードはキューにありません</string>
- <string name="no_items_label">長押しまたはダウンロードしてキューにエピソードを追加できます。</string>
+ <string name="no_items_label">エピソードをダウンロードして追加するか、エピソードを長押しして \"キューに追加\" を選択してください。</string>
<string name="no_feeds_label">まだポッドキャストを何も購読していません。</string>
<string name="no_chapters_label">このエピソードにチャプターはありません。</string>
<string name="no_shownotes_label">このエピソードにショーノートはありません。</string>
@@ -702,6 +702,8 @@
<string name="proxy_host_empty_error">ホストは空にできません</string>
<string name="proxy_host_invalid_error">ホストが有効なIPアドレスやドメインではありません</string>
<string name="proxy_port_invalid_error">ポートが正しくありません</string>
+ <!--Subscriptions fragment-->
+ <string name="subscription_num_columns">カラムの数</string>
<!--Database import/export-->
<string name="import_export">データベースのインポート/エクスポート</string>
<string name="import_export_warning">この実験的な機能を使用すると、サブスクリプションと再生したエピソードを別のデバイスに転送できます。\n\nエクスポートされたデータベースは、同じバージョンのAntennaPodを使用する場合にのみインポートできます。 それ以外の場合、この機能は予期しない動作につながります。\n\nインポートした後、エピソードはダウンロードされたものとして表示されることがあります。 エピソードの再生ボタンを押すだけで、AntennaPodがこれを検出します。</string>
diff --git a/core/src/main/res/values-lt/strings.xml b/core/src/main/res/values-lt/strings.xml
index bec8cb96b..f0820eba4 100644
--- a/core/src/main/res/values-lt/strings.xml
+++ b/core/src/main/res/values-lt/strings.xml
@@ -669,6 +669,7 @@
<string name="proxy_host_empty_error">Serverio laukelis negali būti tuščias</string>
<string name="proxy_host_invalid_error">Serverio laukelyje nurodytas netaisyklingas IP adresas ar sritis</string>
<string name="proxy_port_invalid_error">Netinkamas prievadas</string>
+ <!--Subscriptions fragment-->
<!--Database import/export-->
<string name="import_export">Duomenų bazės importas/eksportas</string>
<string name="import_export_warning">Šis eksperimentinė funkcija leidžia perkelti jūsų prenumeratas bei duomenis apie perklausytus epizodus į kitą įrenginį.
diff --git a/core/src/main/res/values-nb/strings.xml b/core/src/main/res/values-nb/strings.xml
index 70d011981..53489e180 100644
--- a/core/src/main/res/values-nb/strings.xml
+++ b/core/src/main/res/values-nb/strings.xml
@@ -556,6 +556,7 @@
<string name="proxy_host_empty_error">Vert kan ikke være tom</string>
<string name="proxy_host_invalid_error">Vert er ikke en gyldig IP adresse eller domene</string>
<string name="proxy_port_invalid_error">Ikke gyldig port</string>
+ <!--Subscriptions fragment-->
<!--Database import/export-->
<string name="import_export">Database import/eksport</string>
<string name="label_import">Importer</string>
diff --git a/core/src/main/res/values-nl/strings.xml b/core/src/main/res/values-nl/strings.xml
index 8c7858c27..90d081bb7 100644
--- a/core/src/main/res/values-nl/strings.xml
+++ b/core/src/main/res/values-nl/strings.xml
@@ -319,7 +319,7 @@
<string name="enable_sonic">Sonic inschakelen</string>
<!--Empty list labels-->
<string name="no_items_header_label">Geen afleveringen in wachtrij</string>
- <string name="no_items_label">Je kunt afleveringen toevoegen aan de wachtrij door ze lang ingedrukt te houden of te downloaden.</string>
+ <string name="no_items_label">Voeg een aflevering toe door deze te downloaden of houd een aflevering lang ingedrukt en kies \'Toevoegen aan wachtrij\'.</string>
<string name="no_feeds_label">Je hebt nog geen abonnement op een podcast.</string>
<string name="no_chapters_label">Deze aflevering bevat geen hoofdstukken.</string>
<string name="no_shownotes_label">Deze aflevering bevat geen shownotities.</string>
@@ -714,6 +714,8 @@
<string name="proxy_host_empty_error">Host mag niet blanco zijn</string>
<string name="proxy_host_invalid_error">Host is geen geldig IP-adres of domeinnaam</string>
<string name="proxy_port_invalid_error">Ongeldig poortnummer</string>
+ <!--Subscriptions fragment-->
+ <string name="subscription_num_columns">Aantal kolommen</string>
<!--Database import/export-->
<string name="import_export">Databank im-/exporteren</string>
<string name="import_export_warning">Met deze experimentele functie kun je je abonnementen en afgespeelde afleveringen overzetten naar een ander apparaat.\n\nGeëxporteerde databanken kunnen alleen worden geïmporteerd in dezelfde versie van AntennaPod, anders kunnen zich problemen voordoen.\n\nNa het importeren kunnen afleveringen als \'gedownload\' aangemerkt zijn, terwijl dit niet het geval is. Druk op de afspeelknop om AntennaPod dit te laten detecteren.</string>
diff --git a/core/src/main/res/values-pl-rPL/strings.xml b/core/src/main/res/values-pl-rPL/strings.xml
index 73fdb17a8..53bce3911 100644
--- a/core/src/main/res/values-pl-rPL/strings.xml
+++ b/core/src/main/res/values-pl-rPL/strings.xml
@@ -626,6 +626,7 @@ https://gpodder.net/register/</string>
<string name="proxy_host_empty_error">Host nie może być pusty!</string>
<string name="proxy_host_invalid_error">Host nie jest prawidłowym adresem IP albo domeną</string>
<string name="proxy_port_invalid_error">Błędny port</string>
+ <!--Subscriptions fragment-->
<!--Database import/export-->
<string name="import_export">Import/Export bazy danych</string>
<string name="import_export_warning">Ta eksperymentalna funkcja może zostać użyta do przeniesienia Twoich subskrypcji i już obejrzanych odcinków na inne urządzenie.\n\n Wyeksportowana baza może zostać zaimportowana jedynie taką samą wersją programu AntennaPod. W innym przypadku może to spowodować nieprzewidziane zachowanie programu.\n\n Po zaimportowaniu, odcinki mogą być pokazane jako pobrane pomimo tego iż nie zostały pobrane. Wystarczy kliknąć odtwórz odcinek aby AntennaPod wykrył poprawny stan pliku.</string>
diff --git a/core/src/main/res/values-pt-rBR/strings.xml b/core/src/main/res/values-pt-rBR/strings.xml
index eb7d47ea4..0f85d9eaf 100644
--- a/core/src/main/res/values-pt-rBR/strings.xml
+++ b/core/src/main/res/values-pt-rBR/strings.xml
@@ -659,6 +659,7 @@
<string name="proxy_host_empty_error">Host não pode ser vazio</string>
<string name="proxy_host_invalid_error">Host não possui um endereço de IP ou domínio válidos</string>
<string name="proxy_port_invalid_error">Porta inválida</string>
+ <!--Subscriptions fragment-->
<!--Database import/export-->
<string name="import_export">Importar/exportar base de dados</string>
<string name="import_export_warning">Essa funcionalidade experimental pode ser usada para transferir suas inscrições e episódios reproduzidos para outro dispositivo.\n\nBancos de dados exportados só podem ser importados pela mesma versão do AntennaPod. Caso contrário, poderá haver algum comportamento inesperado.\n\nApós a importação, os episódios poderão aparecer como baixados, mesmo que não estejam. Basta pressionar o botão de reprodução do episódio para que o AntennaPod perceba isso. </string>
diff --git a/core/src/main/res/values-pt/strings.xml b/core/src/main/res/values-pt/strings.xml
index 295240e43..39a3d33c6 100644
--- a/core/src/main/res/values-pt/strings.xml
+++ b/core/src/main/res/values-pt/strings.xml
@@ -244,6 +244,7 @@
<string name="download_type_media">Ficheiro multimédia</string>
<string name="download_type_image">Imagem</string>
<string name="download_request_error_dialog_message_prefix">Ocorreu um erro ao tentar descarregar o ficheiro:\u0020</string>
+ <string name="null_value_podcast_error">Não foi possível mostrar o podcast.</string>
<string name="authentication_notification_title">Requer autenticação</string>
<string name="authentication_notification_msg">O recurso solicitado requer um utilizador e uma palavra-passe</string>
<string name="confirm_mobile_download_dialog_title">Confirmação de descarga</string>
@@ -318,7 +319,7 @@
<string name="enable_sonic">Ativar Sonic</string>
<!--Empty list labels-->
<string name="no_items_header_label">Não existem episódios na fila</string>
- <string name="no_items_label">Pode adicionar episódios à fila com um toque longo ou descarregando-os.</string>
+ <string name="no_items_label">Pode adicionar um episódio se o descarregar ou com um toque longo no episódio e escolher \"Adicionar à fila\".</string>
<string name="no_feeds_label">Ainda não tem quaisquer podcasts subscritos.</string>
<string name="no_chapters_label">Este episódio não tem capítulos.</string>
<string name="no_shownotes_label">Este episódio não tem notas.</string>
@@ -713,6 +714,8 @@
<string name="proxy_host_empty_error">Servidor não pode estar vazio</string>
<string name="proxy_host_invalid_error">O servidor não tem um endereço ou domínio válido</string>
<string name="proxy_port_invalid_error">Porta inválido</string>
+ <!--Subscriptions fragment-->
+ <string name="subscription_num_columns">Número de colunas</string>
<!--Database import/export-->
<string name="import_export">Importação/exportação da base de dados</string>
<string name="import_export_warning">Esta função experimental pode ser usada para transferir as suas subscrições e episódios para outros dispositivos.\n\nAs bases de dados exportadas apenas podem ser importadas se usar a mesma versão do AntennaPod. Caso contrário, esta função poderá produzir efeitos inesperados.\n\nDepois da importação, os episódios poderão ser apresentados como tendo sido descarregados mesmo que não seja verdade. Prima o botão de reprodução dos episódios para que o AntennaPod detete a situação.</string>
diff --git a/core/src/main/res/values-ru/strings.xml b/core/src/main/res/values-ru/strings.xml
index fd978710b..942be0267 100644
--- a/core/src/main/res/values-ru/strings.xml
+++ b/core/src/main/res/values-ru/strings.xml
@@ -674,6 +674,7 @@ URL файла:
<string name="proxy_host_empty_error">Обязательно укажите хост</string>
<string name="proxy_host_invalid_error">Неверный адрес или домен хоста</string>
<string name="proxy_port_invalid_error">Неверный порт</string>
+ <!--Subscriptions fragment-->
<!--Database import/export-->
<string name="import_export">Импорт/экспорт базы данных</string>
<string name="import_export_warning">Данная опытная функция поможет перенести Ваши подписки и прослушанные выпуски на другое устройство.\n\nЭкспортированные базы данных можно импортировать только в ту же версию AntennaPod. В противном случае может произойти непредвиденное.\n\nПосле импорта выпуски могут быть помечены как загруженные, хотя это и не так. Простого нажатия на кнопку воспроизведения достаточно, чтобы AntennaPod распознала такой случай.</string>
diff --git a/core/src/main/res/values-sv-rSE/strings.xml b/core/src/main/res/values-sv-rSE/strings.xml
index 134be7b4a..b0fa69b3b 100644
--- a/core/src/main/res/values-sv-rSE/strings.xml
+++ b/core/src/main/res/values-sv-rSE/strings.xml
@@ -4,7 +4,7 @@
<string name="feed_update_receiver_name">Uppdatera Prenumerationer</string>
<string name="feeds_label">Flöden</string>
<string name="statistics_label">Statistik</string>
- <string name="add_feed_label">Lägg till Podcast</string>
+ <string name="add_feed_label">Lägg till podcast</string>
<string name="episodes_label">Episoder</string>
<string name="all_episodes_short_label">Alla</string>
<string name="new_episodes_label">Nytt</string>
@@ -47,13 +47,13 @@
<string name="drawer_feed_counter_downloaded">Antal nedladdade episoder</string>
<string name="drawer_feed_counter_none">Inga</string>
<!--Webview actions-->
- <string name="open_in_browser_label">Öppna i Webbläsare</string>
+ <string name="open_in_browser_label">Öppna i webbläsare</string>
<string name="copy_url_label">Kopiera URL</string>
<string name="share_url_label">Dela URL</string>
- <string name="copied_url_msg">Kopierade URL:en till Urklipp</string>
- <string name="go_to_position_label">Gå till denna Position</string>
+ <string name="copied_url_msg">Kopierade URL:en till urklipp</string>
+ <string name="go_to_position_label">Gå till denna position</string>
<!--Playback history-->
- <string name="clear_history_label">Rensa Historiken</string>
+ <string name="clear_history_label">Rensa historiken</string>
<!--Other-->
<string name="confirm_label">Bekräfta</string>
<string name="cancel_label">Avbryt</string>
@@ -84,9 +84,9 @@
<string name="close_label">Stäng</string>
<string name="retry_label">Försök igen</string>
<string name="auto_download_label">Inkludera i automatiska nedladdningar</string>
- <string name="auto_download_apply_to_items_title">Applicera på Föregående Episoder</string>
- <string name="auto_download_apply_to_items_message">Den nya inställningen <i>Automatisk Nedladdning</i> kommer automatiskt att appliceras på nya episoder.\nVill du även applicera det på tidigare publicerade episoder?</string>
- <string name="auto_delete_label">Automatisk Episodborttagning</string>
+ <string name="auto_download_apply_to_items_title">Applicera på tidigare episoder</string>
+ <string name="auto_download_apply_to_items_message">Den nya inställningen <i>Automatisk nedladdning</i> kommer automatiskt att appliceras på nya episoder.\nVill du även applicera det på tidigare publicerade episoder?</string>
+ <string name="auto_delete_label">Automatisk episodborttagning</string>
<string name="parallel_downloads_suffix">\u0020parallella nedladdningar</string>
<string name="feed_auto_download_global">Globala standardinställningar</string>
<string name="feed_auto_download_always">Alltid</string>
@@ -95,20 +95,25 @@
<string name="episode_cleanup_never">Aldrig</string>
<string name="episode_cleanup_queue_removal">Om inte köad</string>
<string name="episode_cleanup_after_listening">Efter färdigspelad</string>
+ <plurals name="episode_cleanup_hours_after_listening">
+ <item quantity="one">1 timma efter klar</item>
+ <item quantity="other">1%d timmar efter klar</item>
+ </plurals>
<plurals name="episode_cleanup_days_after_listening">
<item quantity="one">1 dag efter färdigspelad</item>
<item quantity="other">%d dagar efter färdigspelad</item>
</plurals>
+ <string name="num_selected_label">1%d valda</string>
<!--'Add Feed' Activity labels-->
<string name="feedurl_label">Flödets URL</string>
<string name="etxtFeedurlHint">URL till flöde eller webbsida</string>
<string name="txtvfeedurl_label">Lägg till podcast via URL</string>
- <string name="podcastdirectories_label">Hitta Podcast i Biblioteket</string>
+ <string name="podcastdirectories_label">Hitta Podcast i biblioteket</string>
<string name="podcastdirectories_descr">För att hitta nya podcasts kan du söka i iTunes, fyyd, eller på gpodder.net baserat på namn, kategori eller popularitet.</string>
<string name="browse_gpoddernet_label">Bläddra på gpodder.net</string>
<!--Actions on feeds-->
<string name="mark_all_read_label">Markera alla som spelade</string>
- <string name="mark_all_read_msg">Markera alla Episoder som spelade</string>
+ <string name="mark_all_read_msg">Markera alla episoder som spelade</string>
<string name="mark_all_read_confirmation_msg">Bekräfta att du verkligen vill markera alla episoder som spelade.</string>
<string name="mark_all_read_feed_confirmation_msg">Bekräfta att du vill markera alla episider i denna podcast som spelade.</string>
<string name="mark_all_seen_label">Markera alla som sedda</string>
@@ -121,16 +126,16 @@
<string name="rename_feed_label">Byt namn på podcast</string>
<string name="remove_feed_label">Ta bort podcast</string>
<string name="share_label">Dela…</string>
- <string name="share_link_label">Dela Episod-URL</string>
- <string name="share_link_with_position_label">Dela Episod-URL med Position</string>
- <string name="share_file_label">Dela Fil</string>
- <string name="share_feed_url_label">Dela Flödets URL</string>
- <string name="share_item_url_label">Dela Mediafilens URL</string>
- <string name="share_item_url_with_position_label">Dela Mediafilens URL med Position</string>
+ <string name="share_link_label">Dela episod-URL</string>
+ <string name="share_link_with_position_label">Dela episod-URL med position</string>
+ <string name="share_file_label">Dela fil</string>
+ <string name="share_feed_url_label">Dela flödets URL</string>
+ <string name="share_item_url_label">Dela mediafilens URL</string>
+ <string name="share_item_url_with_position_label">Dela mediafilens URL med position</string>
<string name="feed_delete_confirmation_msg">Bekräfta att du vill ta bort podcast \"%1$s\" och ALLA dess episoder (inklusive nedladdade episoder).</string>
<string name="feed_remover_msg">Tar bort podcast</string>
<string name="load_complete_feed">Uppdatera hela podcasten</string>
- <string name="hide_episodes_title">Dölj Episoder</string>
+ <string name="hide_episodes_title">Dölj episoder</string>
<string name="batch_edit">Batchredigering</string>
<string name="select_all_above">Välj alla ovanför</string>
<string name="select_all_below">Välj alla nedanför</string>
@@ -145,9 +150,13 @@
<string name="hide_is_favorite_label">Är favorit</string>
<string name="filtered_label">Filtrerad</string>
<string name="refresh_failed_msg">{fa-exclamation-circle} Senaste uppdateringen misslyckades</string>
- <string name="open_podcast">Öppna Podcast</string>
+ <string name="open_podcast">Öppna podcast</string>
<!--actions on feeditems-->
<string name="download_label">Ladda ned</string>
+ <plurals name="downloading_batch_label">
+ <item quantity="one">Laddar ner 1%d episod.</item>
+ <item quantity="other">Laddar ner 1%d episoder.</item>
+ </plurals>
<string name="play_label">Spela</string>
<string name="pause_label">Pausa</string>
<string name="stop_label">Stopp</string>
@@ -155,24 +164,45 @@
<string name="remove_label">Ta bort</string>
<string name="delete_label">Ta bort</string>
<string name="delete_failed">Kunde inte ta bort filen. Testa att starta om enheten.</string>
+ <string name="delete_episode_label">Radera episod</string>
+ <plurals name="deleted_episode_batch_label">
+ <item quantity="one">1%d episod raderad.</item>
+ <item quantity="other">1%d episder raderade.</item>
+ </plurals>
<string name="mark_as_seen_label">Markera som sedd</string>
<string name="marked_as_seen_label">Markera som sedd</string>
<string name="mark_read_label">Markera som spelad</string>
<string name="marked_as_read_label">Markera som spelad</string>
+ <plurals name="marked_read_batch_label">
+ <item quantity="one">1%d episod markerad som spelad.</item>
+ <item quantity="other">1%d episoder markerade som spelade.</item>
+ </plurals>
<string name="mark_unread_label">Markera som ospelad</string>
+ <plurals name="marked_unread_batch_label">
+ <item quantity="one">1%d episod markerad som ospelad.</item>
+ <item quantity="other">1%d episoder markerade som ospelade.</item>
+ </plurals>
<string name="add_to_queue_label">Lägg till i kön</string>
<string name="added_to_queue_label">Lägg till i Kö</string>
+ <plurals name="added_to_queue_batch_label">
+ <item quantity="one">1%d episod tillagd i kön.</item>
+ <item quantity="other">1%d episoder tillagda i kön.</item>
+ </plurals>
<string name="remove_from_queue_label">Ta bort från Kön</string>
- <string name="add_to_favorite_label">Lägg till i Favoriter</string>
- <string name="added_to_favorites">Tillagd i Favoriter</string>
- <string name="remove_from_favorite_label">Ta bort från Favoriter</string>
- <string name="removed_from_favorites">Borrtagen ur Favoriter</string>
+ <plurals name="removed_from_queue_batch_label">
+ <item quantity="one">1%d episod borttagen från kön.</item>
+ <item quantity="other">1%d episoder borttagna från kön.</item>
+ </plurals>
+ <string name="add_to_favorite_label">Lägg till i favoriter</string>
+ <string name="added_to_favorites">Tillagd i favoriter</string>
+ <string name="remove_from_favorite_label">Ta bort från favoriter</string>
+ <string name="removed_from_favorites">Borrtagen ur favoriter</string>
<string name="visit_website_label">Besök websidan</string>
<string name="support_label">Flattra det här</string>
<string name="skip_episode_label">Hoppa över episoden</string>
- <string name="activate_auto_download">Aktivera Automatisk Nedladdning</string>
- <string name="deactivate_auto_download">Avaktivera Automatisk Nedladdning</string>
- <string name="reset_position">Nollställ Uppspelningspositionen</string>
+ <string name="activate_auto_download">Aktivera automatisk nedladdning</string>
+ <string name="deactivate_auto_download">Avaktivera automatisk nedladdning</string>
+ <string name="reset_position">Nollställ uppspelningspositionen</string>
<string name="removed_item">Borttagen</string>
<!--Download messages and labels-->
<string name="download_successful">lyckades</string>
@@ -182,14 +212,14 @@
<string name="download_error_details">Detaljer</string>
<string name="download_error_details_message">%1$s \n\nFil-URL:\n%2$s</string>
<string name="download_error_device_not_found">Hittade ingen lagringsenhet</string>
- <string name="download_error_insufficient_space">Otillräckligt Utrymme</string>
+ <string name="download_error_insufficient_space">Otillräckligt utrymme</string>
<string name="download_error_file_error">Filfel</string>
<string name="download_error_http_data_error">HTTP data fel</string>
<string name="download_error_error_unknown">Okänt fel</string>
<string name="download_error_parser_exception">Tolkningsfel</string>
<string name="download_error_unsupported_type">Flödestypen stöds inte</string>
<string name="download_error_connection_error">Anslutningsfel</string>
- <string name="download_error_unknown_host">Okänd Värd</string>
+ <string name="download_error_unknown_host">Okänd värd</string>
<string name="download_error_unauthorized">Autentiseringsfel</string>
<string name="download_error_file_type_type">Filtypsfel</string>
<string name="download_error_forbidden">Förbjuden</string>
@@ -209,11 +239,12 @@
<string name="downloads_processing">Bearbetar nedladdningar</string>
<string name="download_notification_title">Laddar ner podcastdata</string>
<string name="download_report_content">%1$d nedladdningar lyckades, %2$d misslyckades</string>
- <string name="download_log_title_unknown">Okänd Titel</string>
+ <string name="download_log_title_unknown">Okänd titel</string>
<string name="download_type_feed">Flöde</string>
<string name="download_type_media">Mediafil</string>
<string name="download_type_image">Bild</string>
<string name="download_request_error_dialog_message_prefix">Ett fel uppstod vid försöket att ladda ner filen:\u0020</string>
+ <string name="null_value_podcast_error">Inga tillhandahållna podcasts som kunde visas.</string>
<string name="authentication_notification_title">Autentisering krävs</string>
<string name="authentication_notification_msg">Resursen du begärde kräver ett användarnamn och ett lösenord</string>
<string name="confirm_mobile_download_dialog_title">Bekräfta mobil nedladdning</string>
@@ -239,7 +270,7 @@
<string name="unlock_queue">Lås upp Kön</string>
<string name="queue_locked">Kön låst</string>
<string name="queue_unlocked">Kön upplåst</string>
- <string name="clear_queue_label">Rensa Kön</string>
+ <string name="clear_queue_label">Rensa kön</string>
<string name="undo">Ångra</string>
<string name="removed_from_queue">Föremålet avlägsnades</string>
<string name="move_to_top_label">Flytta längst upp</string>
@@ -250,7 +281,7 @@
<string name="episode_title">Episodtitel</string>
<string name="feed_title">Podcasttitel</string>
<string name="random">Slumpa</string>
- <string name="smart_shuffle">Smart Blandning</string>
+ <string name="smart_shuffle">Smart blandning</string>
<string name="ascending">Stigande</string>
<string name="descending">Fallande</string>
<string name="clear_queue_confirmation_msg">Bekräfta att du vill rensa kön från ALLA episoder.</string>
@@ -258,11 +289,11 @@
<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>
<string name="authenticate_label">Autentisera</string>
- <string name="return_home_label">Återgå till Startsidan</string>
+ <string name="return_home_label">Återgå till startsidan</string>
<string name="flattr_auth_success">Autentiseringen lyckades! Du kan nu Flattra saker i appen.</string>
<string name="no_flattr_token_title">Ingen Flattr token hittades</string>
<string name="no_flattr_token_notification_msg">Ditt Flattr-konto verkar inte vara anslutet till AntennaPod. Tryck här för att autentisera.</string>
- <string name="no_flattr_token_msg">Ditt Flattr konto verkar inte vara ansluten till AntennaPod. Du kan antingen ansluta ditt konto till AntennaPod att Flattr saker i app eller så kan du besöka webbplatsen för att Flattr det där.</string>
+ <string name="no_flattr_token_msg">Ditt Flattr konto verkar inte vara ansluten till AntennaPod. Du kan antingen ansluta ditt konto till AntennaPod att Flattra saker i app eller så kan du besöka webbplatsen för att Flattra det där.</string>
<string name="authenticate_now_label">Autentisera</string>
<string name="action_forbidden_title">Åtgärd förbjuden</string>
<string name="action_forbidden_msg">AntennaPod saknar behörighet för den här åtgärden. Anledningen till detta kan vara att AntennaPods tillgång till ditt konto har återkallats. Du kan antingen åter autentisera AntennaPod eller besöka hemsidan istället.</string>
@@ -287,9 +318,25 @@
<string name="set_playback_speed_label">Uppspelningshastigheter</string>
<string name="enable_sonic">Aktivera Sonic</string>
<!--Empty list labels-->
+ <string name="no_items_header_label">Inga köade episoder</string>
+ <string name="no_items_label">Lägg till en episod genom att ladda ner den, eller tryck länge på en episod och väl \"Lägg till i kön\".</string>
<string name="no_feeds_label">Du har inte prenumererat på några podcasts än.</string>
<string name="no_chapters_label">Denna episod har inga kapitel.</string>
<string name="no_shownotes_label">Denna episod har inga shownotes.</string>
+ <string name="no_run_downloads_head_label">Inga pågående nedladdningar</string>
+ <string name="no_run_downloads_label">Du kan ladda ner episoder på sidan podcastdetaljer.</string>
+ <string name="no_comp_downloads_head_label">Inga nedladdade episoder</string>
+ <string name="no_comp_downloads_label">Du kan ladda ner episoder på sidan podcastdetaljer.</string>
+ <string name="no_log_downloads_head_label">Ingen nedladdningslogg</string>
+ <string name="no_log_downloads_label">Nedladdningsloggar visas här när de är tillgängliga.</string>
+ <string name="no_history_head_label">Ingen historik</string>
+ <string name="no_history_label">Efter att du lyssnat på en episod visas den här.</string>
+ <string name="no_all_episodes_head_label">Inga episoder</string>
+ <string name="no_all_episodes_label">När du lagt till en episod visas den här.</string>
+ <string name="no_new_episodes_head_label">Inga nya episoder</string>
+ <string name="no_new_episodes_label">När nya episoder anländer visas de här.</string>
+ <string name="no_fav_episodes_head_label">Inga favoritepisoder</string>
+ <string name="no_fav_episodes_label">Du kan lägga till episoder i favoriter genom att lång-trycka på dem.</string>
<!--Preferences-->
<string name="storage_pref">Lagring</string>
<string name="project_pref">Projekt</string>
@@ -302,6 +349,7 @@
<string name="automation">Automatisering</string>
<string name="download_pref_details">Detaljer</string>
<string name="import_export_pref">Importera/Exportera</string>
+ <string name="import_export_search_keywords">säkerhetskopiering, återställning</string>
<string name="appearance">Utseende</string>
<string name="external_elements">Externa element</string>
<string name="interruptions">Avbrott</string>
@@ -318,53 +366,56 @@
<string name="pref_hardwarePreviousButtonRestarts_sum">Starta om den nuvarande episoden när du trycker på hårdvaruknappen för föregående istället för att spola tillbaka</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="pref_auto_delete_title">Automatisk borttagning</string>
<string name="pref_smart_mark_as_played_sum">Markera episoder som spelade även om mindre än ett visst antal sekunder är kvar</string>
<string name="pref_smart_mark_as_played_title">Smart markera som spelad</string>
<string name="pref_skip_keeps_episodes_sum">Ta inte bort episoder när de hoppas över</string>
- <string name="pref_skip_keeps_episodes_title">Behåll Överhoppade Episoder</string>
+ <string name="pref_skip_keeps_episodes_title">Behåll överhoppade episoder</string>
<string name="pref_favorite_keeps_episodes_sum">Behåll episoder när de är favoritmarkerade</string>
- <string name="pref_favorite_keeps_episodes_title">Behåll Favoritepisoder</string>
+ <string name="pref_favorite_keeps_episodes_title">Behåll favoritepisoder</string>
<string name="playback_pref">Uppspelning</string>
<string name="network_pref">Nätverk </string>
- <string name="pref_autoUpdateIntervallOrTime_title">Uppdateringsintervall eller Tid på Dagen</string>
+ <string name="pref_autoUpdateIntervallOrTime_title">Uppdateringsintervall eller tid på dagen</string>
<string name="pref_autoUpdateIntervallOrTime_sum">Ange ett intervall eller specifik tid på dagen för att uppdatera flödena automatisk.</string>
<string name="pref_autoUpdateIntervallOrTime_message">Du kan välja ett <i>intervall</i> som \"var 2 timmar\", en specifik <i>tid på dagen</i> som \"07:00\" eller <i>avaktivera</i> automatiska uppdateringar helt.\n\n<small>Notera: Uppdateringstiderna är inte exakta. Korta fördröjningar kan uppstå.</small></string>
<string name="pref_autoUpdateIntervallOrTime_Disable">Avaktivera</string>
- <string name="pref_autoUpdateIntervallOrTime_Interval">Sätt intervall</string>
- <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Sätt Tid på Dagen</string>
+ <string name="pref_autoUpdateIntervallOrTime_Interval">Välj intervall</string>
+ <string name="pref_autoUpdateIntervallOrTime_TimeOfDay">Välj tid på dagen</string>
<string name="pref_autoUpdateIntervallOrTime_every">var %1$s</string>
<string name="pref_autoUpdateIntervallOrTime_at">vid %1$s</string>
<string name="pref_downloadMediaOnWifiOnly_sum">Hämta mediefiler endast över WiFi</string>
- <string name="pref_followQueue_title">Kontinuerlig Uppspelning</string>
+ <string name="pref_followQueue_title">Kontinuerlig uppspelning</string>
<string name="pref_downloadMediaOnWifiOnly_title">WiFi nedladdning</string>
- <string name="pref_pauseOnHeadsetDisconnect_title">Hörlurar Bortkopplas</string>
- <string name="pref_unpauseOnHeadsetReconnect_title">Hörlurar Återanslutna</string>
- <string name="pref_unpauseOnBluetoothReconnect_title">Blutetooth Återansluts</string>
- <string name="pref_mobileUpdate_title">Mobila Uppdateringar</string>
+ <string name="pref_pauseOnHeadsetDisconnect_title">Hörlurar bortkopplas</string>
+ <string name="pref_unpauseOnHeadsetReconnect_title">Hörlurar återanslutna</string>
+ <string name="pref_unpauseOnBluetoothReconnect_title">Blutetooth återansluts</string>
+ <string name="pref_mobileUpdate_title">Mobila uppdateringar</string>
<string name="pref_mobileUpdate_sum">Tillåt uppdateringar via mobil dataanslutning</string>
+ <string name="pref_mobileUpdate_nothing">Inget</string>
+ <string name="pref_mobileUpdate_images">Bara bilder</string>
+ <string name="pref_mobileUpdate_everything">Allt</string>
<string name="refreshing_label">Uppdaterar</string>
<string name="flattr_settings_label">Flattr inställningar</string>
<string name="pref_flattr_auth_title">Flattr inloggning</string>
<string name="pref_flattr_auth_sum">För att Flattra saker direkt från appen, logga in på ditt Flattr-konto.</string>
- <string name="pref_flattr_this_app_title">Flattra denna App</string>
+ <string name="pref_flattr_this_app_title">Flattra denna app</string>
<string name="pref_flattr_this_app_sum">Stöd utvecklingen av AntennaPod genom att flattra den. Tack!</string>
<string name="pref_revokeAccess_title">Återkalla åtkomst</string>
<string name="pref_revokeAccess_sum">Återkalla behörigheten till ditt Flattr-konto för denna app.</string>
<string name="pref_auto_flattr_title">Automatisk Flattring</string>
<string name="pref_auto_flattr_sum">Konfigurerar automatisk Flattring</string>
<string name="user_interface_label">Användargränssnitt</string>
- <string name="pref_set_theme_title">Välj Tema</string>
- <string name="pref_nav_drawer_title">Anpassa Navigeringsmenyn</string>
+ <string name="pref_set_theme_title">Välj tema</string>
+ <string name="pref_nav_drawer_title">Anpassa navigeringsmenyn</string>
<string name="pref_nav_drawer_sum">Anpassa utseendet på navigeringmenyn.</string>
- <string name="pref_nav_drawer_items_title">Välj Objekt i Navigeringsmenyn</string>
+ <string name="pref_nav_drawer_items_title">Välj objekt i navigeringsmenyn</string>
<string name="pref_nav_drawer_items_sum">Ändra vilka saker som visas på navigationsmenyn.</string>
- <string name="pref_nav_drawer_feed_order_title">Välj Prenumerationsordning</string>
+ <string name="pref_nav_drawer_feed_order_title">Välj prenumerationsordning</string>
<string name="pref_nav_drawer_feed_order_sum">Ändra ordningen på dina prenumerationer</string>
<string name="pref_nav_drawer_feed_counter_title">Val för Prenumerationsräknaren</string>
<string name="pref_nav_drawer_feed_counter_sum">Ändra informationen som visas vid prenumerationsräknaren. Påverkar även sorteringen av prenumerationer om \'Prenumerationsordning\' är satt till \'Räknare\'.</string>
<string name="pref_set_theme_sum">Ändra utseendet på AntennaPod.</string>
- <string name="pref_automatic_download_title">Automatisk Nedladdning</string>
+ <string name="pref_automatic_download_title">Automatisk nedladdning</string>
<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>
@@ -372,7 +423,7 @@
<string name="pref_autodl_allow_on_mobile_sum">Tillåt automatiska nedladdningar över en mobil dataanslutning.</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_parallel_downloads_title">Parallella Nedladdningar</string>
+ <string name="pref_parallel_downloads_title">Parallella nedladdningar</string>
<string name="pref_episode_cache_title">Episodcache</string>
<string name="pref_theme_title_light">Ljust</string>
<string name="pref_theme_title_dark">Mörkt</string>
@@ -407,19 +458,19 @@
<string name="pref_gpodnet_sethostname_use_default_host">Använd standardvärden</string>
<string name="pref_expandNotify_title">Hög notifieringsprioritet</string>
<string name="pref_expandNotify_sum">Detta expanderar oftast notifieringen och visar uppspelningskontroller.</string>
- <string name="pref_persistNotify_title">Bestående Uppspelningskontroller</string>
+ <string name="pref_persistNotify_title">Bestående uppspelningskontroller</string>
<string name="pref_persistNotify_sum">Behåll avisering och kontroller på låsskärmen när uppspelningen pausas.</string>
- <string name="pref_compact_notification_buttons_title">Sätt Låsskärmens Knappar</string>
- <string name="pref_compact_notification_buttons_sum">Ändra uppspelningsknapparna på låsskärmen. Spela/Pausa knappen är alltid inkluderad.</string>
+ <string name="pref_compact_notification_buttons_title">Val för låsskärmens knappar</string>
+ <string name="pref_compact_notification_buttons_sum">Ändra uppspelningsknapparna på låsskärmen. Spela/pausa knappen är alltid inkluderad.</string>
<string name="pref_compact_notification_buttons_dialog_title">Välj maximalt %1$d st.</string>
<string name="pref_compact_notification_buttons_dialog_error">Du kan bara välja maximalt %1$d st.</string>
- <string name="pref_lockscreen_background_title">Sätt Låsskärmens Bakgrund</string>
+ <string name="pref_lockscreen_background_title">Välj låsskärmens bakgrund</string>
<string name="pref_lockscreen_background_sum">Sätt låsskärmens bakgrund till den spelade episodens bild. En bieffekt är att även tredjepartsappar kan visa bilden.</string>
- <string name="pref_showDownloadReport_title">Visa Nedladdningsrapport</string>
+ <string name="pref_showDownloadReport_title">Visa nedladdningsrapport</string>
<string name="pref_showDownloadReport_sum">Visa en rapport med detaljer om felet när nedladdningar misslyckas.</string>
<string name="pref_expand_notify_unsupport_toast">Androidversioner före 4.1 har inte stöd för expanderade aviseringar.</string>
<string name="pref_queueAddToFront_sum">Lägg till episoder först i kön.</string>
- <string name="pref_queueAddToFront_title">Köa Först</string>
+ <string name="pref_queueAddToFront_title">Köa först</string>
<string name="pref_smart_mark_as_played_disabled">Avaktiverad</string>
<string name="pref_image_cache_size_title">Bildcachestorlek</string>
<string name="pref_image_cache_size_sum">Storleken på bildcachen på disken.</string>
@@ -440,12 +491,13 @@
<string name="pref_enqueue_downloaded_title">Köa Nedladdade</string>
<string name="pref_enqueue_downloaded_summary">Lägg nedladdade episoder i uppspelningskön</string>
<string name="media_player_builtin">Andriods inbyggda spelare</string>
+ <string name="pref_skip_silence_title">Hoppa över tystnad i ljud</string>
<string name="pref_videoBehavior_title">Vid avslutande av video</string>
<string name="pref_videoBehavior_sum">Beteende när videouppspelning avslutas</string>
<string name="stop_playback">Stoppa uppspelning</string>
<string name="continue_playback">Fortsätt ljuduppspelning</string>
<string name="behavior">Beteende</string>
- <string name="pref_back_button_behavior_title">Tillbakaknappens Beteende</string>
+ <string name="pref_back_button_behavior_title">Tillbakaknappens beteende</string>
<string name="pref_back_button_behavior_sum">Byt tillbakaknappens beteende.</string>
<string name="back_button_default">Standard</string>
<string name="back_button_open_drawer">Öppna navigationsrutan</string>
@@ -455,6 +507,8 @@
<string name="double_tap_toast">Tryck på tillbakaknappen igen för att avsluta</string>
<string name="back_button_go_to_page">Gå till sida...</string>
<string name="back_button_go_to_page_title">Välj sida</string>
+ <string name="pref_delete_removes_from_queue_title">Radering tar bort från kön</string>
+ <string name="pref_delete_removes_from_queue_sum">Ta automatiskt bort episoder från kön när de raderas.</string>
<!--Auto-Flattr dialog-->
<string name="auto_flattr_enable">Aktivera automatisk Flattring</string>
<string name="auto_flattr_after_percent">Flattra episoden så snart %d procent har spelats</string>
@@ -477,7 +531,7 @@
<string name="opml_import_explanation_2">Använd en extern applikation som Dropbox, Google Drive eller ditt favoritval av filhanterare för att öppna en OPML fil.</string>
<string name="opml_import_explanation_3">Flera applikationer som Google Mail, Dropbox, Google Drive och de flesta filhanterare kan <i>öppna</i> OPML filer <i>med</i> AntennaPod.</string>
<string name="start_import_label">Påbörja importering</string>
- <string name="opml_import_label">OPML Importering</string>
+ <string name="opml_import_label">OPML importering</string>
<string name="opml_directory_error">FEL! </string>
<string name="reading_opml_label">Läser OPML-fil</string>
<string name="opml_reader_error">Ett fel uppstod vid läsning av OPML dokumentet:</string>
@@ -571,9 +625,9 @@
<string name="folder_not_empty_dialog_msg">Den mapp du har valt är inte tom. Filer kommer att placeras direkt i denna mapp. Fortsätt ändå?</string>
<string name="set_to_default_folder">Välj standardmapp</string>
<string name="pref_pausePlaybackForFocusLoss_sum">Pausa uppspelning istället för att sänka volymen när en annan app vill spela ljud</string>
- <string name="pref_pausePlaybackForFocusLoss_title">Pausa vid Avbrott</string>
+ <string name="pref_pausePlaybackForFocusLoss_title">Pausa vid avbrott</string>
<string name="pref_resumeAfterCall_sum">Återuppta uppspelning när ett telefonsamtal avslutas</string>
- <string name="pref_resumeAfterCall_title">Fortsätt efter Samtal</string>
+ <string name="pref_resumeAfterCall_title">Fortsätt efter samtal</string>
<string name="pref_restart_required">AntennaPod behöver startas om för att denna inställning ska gälla.</string>
<!--Online feed view-->
<string name="subscribe_label">Prenumerera</string>
@@ -608,21 +662,21 @@
<string name="search_fyyd_label">Sök i fyyd</string>
<!--Episodes apply actions-->
<string name="all_label">Alla</string>
- <string name="selected_all_label">Välj alla Episoder</string>
+ <string name="selected_all_label">Välj alla episoder</string>
<string name="none_label">Inga</string>
- <string name="deselected_all_label">Avmarkera alla Episoder</string>
+ <string name="deselected_all_label">Avmarkera alla episoder</string>
<string name="played_label">Spelade</string>
- <string name="selected_played_label">Valde spelade Episoder</string>
+ <string name="selected_played_label">Valde spelade episoder</string>
<string name="unplayed_label">Ospelade</string>
- <string name="selected_unplayed_label">Valde ospelade Episoder</string>
+ <string name="selected_unplayed_label">Valde ospelade episoder</string>
<string name="downloaded_label">Nedladdade</string>
- <string name="selected_downloaded_label">Valde nedladdade Episoder</string>
+ <string name="selected_downloaded_label">Valde nedladdade episoder</string>
<string name="not_downloaded_label">Ej nedladdade</string>
- <string name="selected_not_downloaded_label">Valde ej nedladdade Episoder</string>
+ <string name="selected_not_downloaded_label">Valde ej nedladdade episoder</string>
<string name="queued_label">Köad</string>
- <string name="selected_queued_label">Valde köade Episoder</string>
+ <string name="selected_queued_label">Valde köade episoder</string>
<string name="not_queued_label">Ej köad</string>
- <string name="selected_not_queued_label">Välj ej köade Episoder</string>
+ <string name="selected_not_queued_label">Välj ej köade episoder</string>
<string name="has_media">Har media</string>
<string name="selected_has_media_label">Valde episoder med media</string>
<!--Sort-->
@@ -645,8 +699,9 @@
<string name="left_short">V</string>
<string name="right_short">H</string>
<string name="audio_effects">Ljudeffekter</string>
- <string name="stereo_to_mono">Nedmixning: Stereo till mono</string>
+ <string name="stereo_to_mono">Nedmixning: stereo till mono</string>
<string name="sonic_only">Bara Sonic</string>
+ <string name="exoplayer_only">Endast ExoPlayer</string>
<!--proxy settings-->
<string name="proxy_type_label">Typ</string>
<string name="host_label">Värd</string>
@@ -659,8 +714,10 @@
<string name="proxy_host_empty_error">Värd måste fyllas i</string>
<string name="proxy_host_invalid_error">Värd är inte en giltig IP adress eller domän</string>
<string name="proxy_port_invalid_error">Porten är inte giltig</string>
+ <!--Subscriptions fragment-->
+ <string name="subscription_num_columns">Antal kolumner</string>
<!--Database import/export-->
- <string name="import_export">Databas-Import/Export</string>
+ <string name="import_export">Databas-import/export</string>
<string name="import_export_warning">Denna experimentella funktion kan användas för att föra över dina prenumerationer och spelade episoder till en annan enhet.\n\nExporterade databaser kan bara importeras med samma version av AntennaPod. Annars kommer en import att leda till oförutsägbara konsekvenser.\n\nEfter en import kan episoder visas som nedladdade även om de inte är det. Tryck bara på uppspelningsknappen på episoden för att AntennaPod ska kolla det igen.</string>
<string name="label_import">Import</string>
<string name="label_export">Export</string>
diff --git a/core/src/main/res/values-tr/strings.xml b/core/src/main/res/values-tr/strings.xml
index 4b114e0ef..f27b905bd 100644
--- a/core/src/main/res/values-tr/strings.xml
+++ b/core/src/main/res/values-tr/strings.xml
@@ -553,6 +553,7 @@
<string name="proxy_test_label">Test</string>
<string name="proxy_test_successful">Test başarılı</string>
<string name="proxy_test_failed">Test başarısız</string>
+ <!--Subscriptions fragment-->
<!--Database import/export-->
<!--Casting-->
<!--<string name="cast_failed_to_connect">Could not connect to the device</string>-->
diff --git a/core/src/main/res/values-uk-rUA/strings.xml b/core/src/main/res/values-uk-rUA/strings.xml
index 62e08530f..d40baba2d 100644
--- a/core/src/main/res/values-uk-rUA/strings.xml
+++ b/core/src/main/res/values-uk-rUA/strings.xml
@@ -181,7 +181,19 @@
<string name="marked_as_seen_label">Позначено як переглянутий</string>
<string name="mark_read_label">Позначити як відтворений</string>
<string name="marked_as_read_label">Позначено як відтворений</string>
+ <plurals name="marked_read_batch_label">
+ <item quantity="one">%d епізод помічено як відтворений</item>
+ <item quantity="few">%d епізоди помічено як відтворені</item>
+ <item quantity="many">%d епізодів помічено як відтворені</item>
+ <item quantity="other">%d епізодів помічено як відтворені</item>
+ </plurals>
<string name="mark_unread_label">Позначити як не відтворений</string>
+ <plurals name="marked_unread_batch_label">
+ <item quantity="one">%d епізод помічено як невідтворений</item>
+ <item quantity="few">%d епізоди помічено як невідтворені</item>
+ <item quantity="many">%d епізодів помічено як невідтворені</item>
+ <item quantity="other">%d епізодів помічено як невідтворені</item>
+ </plurals>
<string name="add_to_queue_label">Додати до черги</string>
<string name="added_to_queue_label">Додано до черги</string>
<plurals name="added_to_queue_batch_label">
@@ -325,13 +337,14 @@
<string name="enable_sonic">Включити Sonic</string>
<!--Empty list labels-->
<string name="no_items_header_label">В черзі немає епізодів.</string>
- <string name="no_items_label">Епізоди додаються до черги за допомогою довгого натискання або коли їх завантажують.</string>
+ <string name="no_items_label">Додайте епізод, завантаживши його, або довго натиснувши на нього і вибравши \"Додати до черги\".</string>
<string name="no_feeds_label">Ви ще не підписалися на жодні подкасти.</string>
<string name="no_chapters_label">В цьому епізоді немає розділів.</string>
<string name="no_shownotes_label">До цього епізода немає нотаток.</string>
<string name="no_run_downloads_head_label">Зараз нічого не завантажується.</string>
<string name="no_run_downloads_label">Завантажувати епізоди можна з детального перегляда подкаста.</string>
<string name="no_comp_downloads_head_label">Немає завантажених епізодів</string>
+ <string name="no_comp_downloads_label">Можна завантажувати епізоди на екрані подробиць подкасту.</string>
<string name="no_log_downloads_head_label">Журнал завантажень пустий.</string>
<string name="no_log_downloads_label">Журнал завантажень з’явиться тут.</string>
<string name="no_history_head_label">Немає історії прослуховувань</string>
@@ -513,6 +526,7 @@
<string name="back_button_go_to_page">Перейти на сторінку…</string>
<string name="back_button_go_to_page_title">Вибрати сторінку</string>
<string name="pref_delete_removes_from_queue_title">Видалення з черги видалених епізодів</string>
+ <string name="pref_delete_removes_from_queue_sum">Автоматично видаляти епізод із черги, коли він буде видалений.</string>
<!--Auto-Flattr dialog-->
<string name="auto_flattr_enable">Включити автоматичне заохочення авторів через сервіс flattr</string>
<string name="auto_flattr_after_percent">Заохотити автора через Flattr щойно %d відсотків епізода було відтворено</string>
@@ -711,6 +725,7 @@
<string name="audio_effects">Аудіоефекти</string>
<string name="stereo_to_mono">Зробити моно із стерео</string>
<string name="sonic_only">Тільки Sonic</string>
+ <string name="exoplayer_only">Лише ExoPlayer</string>
<!--proxy settings-->
<string name="proxy_type_label">Тип</string>
<string name="host_label">Хост</string>
@@ -723,6 +738,8 @@
<string name="proxy_host_empty_error">Хост не може бути пустим</string>
<string name="proxy_host_invalid_error">Хост не є правильною IP-адресою або доменним ім’ям</string>
<string name="proxy_port_invalid_error">Порт недійсний</string>
+ <!--Subscriptions fragment-->
+ <string name="subscription_num_columns">Кількість стовпців</string>
<!--Database import/export-->
<string name="import_export">Імпортувати/Експортувати базу данних</string>
<string name="import_export_warning">Ця експериментальна функція використовується для перенесення ваших підписок та вже прослуханих епізодів до іншого пристрою.\n\nЕкспортована база даних може бути імпортована тією ж самою версією AntennaPod. Інакше, результат може бути непередбаченим.\n\nПісля імпортування, епізоди можуть відображатися як завантажені, навіть якщо вони такими не є. Просто натисніть кнопку відтворення епізодів, щоб AntennaPod виявив це.</string>
diff --git a/core/src/main/res/values-zh-rCN/strings.xml b/core/src/main/res/values-zh-rCN/strings.xml
index 2da34a230..f78c6b0ae 100644
--- a/core/src/main/res/values-zh-rCN/strings.xml
+++ b/core/src/main/res/values-zh-rCN/strings.xml
@@ -592,6 +592,7 @@
<string name="proxy_host_empty_error">主机地址不能为空</string>
<string name="proxy_host_invalid_error">主机地址为无效的IP地址或域名</string>
<string name="proxy_port_invalid_error">端口不可用</string>
+ <!--Subscriptions fragment-->
<!--Database import/export-->
<string name="label_import">导入</string>
<string name="label_export">导出</string>
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index add2dfe14..b11f47129 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -302,6 +302,8 @@
<string name="ascending">Ascending</string>
<string name="descending">Descending</string>
<string name="clear_queue_confirmation_msg">Please confirm that you want to clear the queue of ALL of the episodes in it</string>
+ <string name="sort_old_to_new">Old to new</string>
+ <string name="sort_new_to_old">New to old</string>
<!-- Flattr -->
<string name="flattr_auth_label">Flattr sign-in</string>
@@ -375,7 +377,7 @@
<string name="appearance">Appearance</string>
<string name="external_elements">External elements</string>
<string name="interruptions">Interruptions</string>
- <string name="buttons">Playback control buttons</string>
+ <string name="playback_control">Playback control</string>
<string name="media_player">Media player</string>
<string name="pref_episode_cleanup_title">Episode Cleanup</string>
<string name="pref_episode_cleanup_summary">Episodes that aren\'t in the queue and aren\'t favorites should be eligible for removal if Auto Download needs space for new episodes</string>
@@ -472,6 +474,8 @@
<string name="pref_gpodnet_notifications_sum">This setting does not apply to authentication errors.</string>
<string name="pref_playback_speed_title">Playback Speeds</string>
<string name="pref_playback_speed_sum">Customize the speeds available for variable speed audio playback</string>
+ <string name="pref_playback_time_respects_speed_title">Adjust media info to playback speed</string>
+ <string name="pref_playback_time_respects_speed_sum">Displayed position and duration are adapted to playback speed</string>
<string name="pref_fast_forward">Fast Forward Skip Time</string>
<string name="pref_fast_forward_sum">Customize the number of seconds to jump forward when the fast forward button is clicked</string>
<string name="pref_rewind">Rewind Skip Time</string>
@@ -644,6 +648,7 @@
<string name="choose_data_directory">Choose Data Folder</string>
<string name="choose_data_directory_message">Please choose the base of your data folder. AntennaPod will create the appropriate sub-directories.</string>
<string name="choose_data_directory_permission_rationale">Access to external storage is required to change the data folder</string>
+ <string name="choose_data_directory_available_space">%1$s free</string>
<string name="create_folder_msg">Create new folder with name "%1$s"?</string>
<string name="create_folder_success">Created new folder</string>
<string name="create_folder_error_no_write_access">Cannot write to this folder</string>
@@ -796,4 +801,5 @@
<string name="notification_channel_playing_description">Allows to control playback. This is the main notification you see while playing a podcast.</string>
<string name="notification_channel_error">Errors</string>
<string name="notification_channel_error_description">Shown if something went wrong, for example if download or gpodder sync fails.</string>
+ <string name="import_bad_file">Invalid/corrupt file</string>
</resources>
diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml
index b4fb2b3a3..d80137ea3 100644
--- a/core/src/main/res/values/styles.xml
+++ b/core/src/main/res/values/styles.xml
@@ -11,76 +11,76 @@
<item name="progressBarTheme">@style/ProgressBarLight</item>
<item name="buttonStyle">@style/Widget.AntennaPod.Button</item>
<item name="alertDialogTheme">@style/AntennaPod.Dialog.Light</item>
- <item type="attr" name="action_bar_icon_color">@color/grey600</item>
- <item type="attr" name="storage">@drawable/ic_sd_grey600_24dp</item>
- <item type="attr" name="ic_swap">@drawable/ic_swap_vertical_grey600_24dp</item>
- <item type="attr" name="statistics">@drawable/ic_poll_box_grey600_24dp</item>
- <item type="attr" name="action_about">@drawable/ic_info_grey600_24dp</item>
- <item type="attr" name="checkbox_multiple">@drawable/ic_checkbox_multiple_marked_outline_grey600_24dp</item>
- <item type="attr" name="action_search">@drawable/ic_search_grey600_24dp</item>
- <item type="attr" name="action_stream">@drawable/ic_settings_input_antenna_grey600_24dp</item>
- <item type="attr" name="av_download">@drawable/ic_file_download_grey600_24dp</item>
- <item type="attr" name="av_fast_forward">@drawable/ic_fast_forward_grey600_24dp</item>
- <item type="attr" name="av_pause">@drawable/ic_pause_grey600_24dp</item>
- <item type="attr" name="av_play">@drawable/ic_play_arrow_grey600_24dp</item>
- <item type="attr" name="av_rewind">@drawable/ic_fast_rewind_grey600_24dp</item>
- <item type="attr" name="content_discard">@drawable/ic_delete_grey600_24dp</item>
- <item type="attr" name="content_new">@drawable/ic_add_grey600_24dp</item>
- <item type="attr" name="content_remove_from_queue">@drawable/ic_remove_grey600</item>
- <item type="attr" name="feed">@drawable/ic_feed_grey600_24dp</item>
- <item type="attr" name="location_web_site">@drawable/ic_web_grey600_24dp</item>
- <item type="attr" name="navigation_accept">@drawable/ic_done_grey600_24dp</item>
- <item type="attr" name="navigation_cancel">@drawable/ic_cancel_grey600_24dp</item>
- <item type="attr" name="navigation_expand">@drawable/ic_expand_more_grey600_36dp</item>
- <item type="attr" name="navigation_refresh">@drawable/ic_refresh_grey600_24dp</item>
- <item type="attr" name="navigation_up">@drawable/navigation_up</item>
- <item type="attr" name="social_share">@drawable/ic_share_grey600_24dp</item>
- <item type="attr" name="stat_playlist">@drawable/ic_list_grey600_24dp</item>
- <item type="attr" name="type_audio">@drawable/ic_hearing_grey600_18dp</item>
- <item type="attr" name="type_video">@drawable/ic_remove_red_eye_grey600_18dp</item>
- <item type="attr" name="non_transparent_background">@color/white</item>
- <item type="attr" name="overlay_background">@color/overlay_light</item>
- <item type="attr" name="overlay_drawable">@drawable/overlay_drawable</item>
- <item type="attr" name="dragview_background">@drawable/ic_drag_vertical_grey600_48dp</item>
- <item type="attr" name="dragview_float_background">@color/white</item>
- <item type="attr" name="nav_drawer_background">@color/white</item>
- <item type="attr" name="drawer_activated_color">@color/highlight_light</item>
- <item type="attr" name="ic_new">@drawable/ic_new_releases_grey600_24dp</item>
- <item type="attr" name="ic_history">@drawable/ic_history_grey600_24dp</item>
- <item type="attr" name="ic_folder">@drawable/ic_folder_grey600_24dp</item>
- <item type="attr" name="av_play_big">@drawable/ic_play_arrow_grey600_36dp</item>
- <item type="attr" name="av_pause_big">@drawable/ic_pause_grey600_36dp</item>
- <item type="attr" name="av_ff_big">@drawable/ic_fast_forward_grey600_36dp</item>
- <item type="attr" name="av_rew_big">@drawable/ic_fast_rewind_grey600_36dp</item>
- <item type="attr" name="av_skip_big">@drawable/ic_skip_grey600_36dp</item>
- <item type="attr" name="ic_fav">@drawable/ic_star_border_grey600_24dp</item>
- <item type="attr" name="ic_unfav">@drawable/ic_star_grey600_24dp</item>
- <item type="attr" name="ic_settings">@drawable/ic_settings_grey600_24dp</item>
- <item type="attr" name="ic_lock_open">@drawable/ic_lock_open_grey600_24dp</item>
- <item type="attr" name="ic_lock_closed">@drawable/ic_lock_closed_grey600_24dp</item>
- <item type="attr" name="ic_filter">@drawable/ic_filter_grey600_24dp</item>
- <item type="attr" name="ic_sleep">@drawable/ic_sleep_grey600_24dp</item>
- <item type="attr" name="ic_sleep_off">@drawable/ic_sleep_off_grey600_24dp</item>
- <item type="attr" name="ic_select_all">@drawable/ic_select_all_grey600</item>
- <item type="attr" name="ic_select_none">@drawable/ic_select_none_grey600</item>
- <item type="attr" name="ic_sort">@drawable/ic_sort_grey600_24dp</item>
- <item type="attr" name="ic_sd_storage">@drawable/ic_sd_storage_grey600_36dp</item>
- <item type="attr" name="ic_create_new_folder">@drawable/ic_create_new_folder_grey600_24dp</item>
- <item type="attr" name="ic_cast_disconnect">@drawable/ic_cast_disconnect_grey600_36dp</item>
- <item type="attr" name="ic_cellphone_text">@drawable/ic_cellphone_text_grey600_24dp</item>
- <item type="attr" name="ic_question_answer">@drawable/ic_forum_grey600_24dp</item>
- <item type="attr" name="ic_bug">@drawable/ic_bug_grey600_24dp</item>
- <item type="attr" name="ic_known_issues">@drawable/ic_format_list_bulleted_grey600_24dp</item>
-
- <item type="attr" name="master_switch_background">@color/master_switch_background_light</item>
- <item type="attr" name="currently_playing_background">@color/highlight_light</item>
+ <item name="action_bar_icon_color">@color/grey600</item>
+ <item name="storage">@drawable/ic_sd_grey600_24dp</item>
+ <item name="ic_swap">@drawable/ic_swap_vertical_grey600_24dp</item>
+ <item name="statistics">@drawable/ic_poll_box_grey600_24dp</item>
+ <item name="action_about">@drawable/ic_info_grey600_24dp</item>
+ <item name="checkbox_multiple">@drawable/ic_checkbox_multiple_marked_outline_grey600_24dp</item>
+ <item name="action_search">@drawable/ic_search_grey600_24dp</item>
+ <item name="action_stream">@drawable/ic_settings_input_antenna_grey600_24dp</item>
+ <item name="av_download">@drawable/ic_file_download_grey600_24dp</item>
+ <item name="av_fast_forward">@drawable/ic_fast_forward_grey600_24dp</item>
+ <item name="av_pause">@drawable/ic_pause_grey600_24dp</item>
+ <item name="av_play">@drawable/ic_play_arrow_grey600_24dp</item>
+ <item name="av_rewind">@drawable/ic_fast_rewind_grey600_24dp</item>
+ <item name="content_discard">@drawable/ic_delete_grey600_24dp</item>
+ <item name="content_new">@drawable/ic_add_grey600_24dp</item>
+ <item name="content_remove_from_queue">@drawable/ic_remove_grey600</item>
+ <item name="feed">@drawable/ic_feed_grey600_24dp</item>
+ <item name="location_web_site">@drawable/ic_web_grey600_24dp</item>
+ <item name="navigation_accept">@drawable/ic_done_grey600_24dp</item>
+ <item name="navigation_cancel">@drawable/ic_cancel_grey600_24dp</item>
+ <item name="navigation_expand">@drawable/ic_expand_more_grey600_36dp</item>
+ <item name="navigation_refresh">@drawable/ic_refresh_grey600_24dp</item>
+ <item name="navigation_up">@drawable/navigation_up</item>
+ <item name="social_share">@drawable/ic_share_grey600_24dp</item>
+ <item name="stat_playlist">@drawable/ic_list_grey600_24dp</item>
+ <item name="type_audio">@drawable/ic_hearing_grey600_18dp</item>
+ <item name="type_video">@drawable/ic_remove_red_eye_grey600_18dp</item>
+ <item name="non_transparent_background">@color/white</item>
+ <item name="overlay_background">@color/overlay_light</item>
+ <item name="overlay_drawable">@drawable/overlay_drawable</item>
+ <item name="dragview_background">@drawable/ic_drag_vertical_grey600_48dp</item>
+ <item name="dragview_float_background">@color/white</item>
+ <item name="nav_drawer_background">@color/white</item>
+ <item name="drawer_activated_color">@color/highlight_light</item>
+ <item name="ic_new">@drawable/ic_new_releases_grey600_24dp</item>
+ <item name="ic_history">@drawable/ic_history_grey600_24dp</item>
+ <item name="ic_folder">@drawable/ic_folder_grey600_24dp</item>
+ <item name="av_play_big">@drawable/ic_play_arrow_grey600_36dp</item>
+ <item name="av_pause_big">@drawable/ic_pause_grey600_36dp</item>
+ <item name="av_ff_big">@drawable/ic_fast_forward_grey600_36dp</item>
+ <item name="av_rew_big">@drawable/ic_fast_rewind_grey600_36dp</item>
+ <item name="av_skip_big">@drawable/ic_skip_grey600_36dp</item>
+ <item name="ic_fav">@drawable/ic_star_border_grey600_24dp</item>
+ <item name="ic_unfav">@drawable/ic_star_grey600_24dp</item>
+ <item name="ic_settings">@drawable/ic_settings_grey600_24dp</item>
+ <item name="ic_lock_open">@drawable/ic_lock_open_grey600_24dp</item>
+ <item name="ic_lock_closed">@drawable/ic_lock_closed_grey600_24dp</item>
+ <item name="ic_filter">@drawable/ic_filter_grey600_24dp</item>
+ <item name="ic_sleep">@drawable/ic_sleep_grey600_24dp</item>
+ <item name="ic_sleep_off">@drawable/ic_sleep_off_grey600_24dp</item>
+ <item name="ic_select_all">@drawable/ic_select_all_grey600</item>
+ <item name="ic_select_none">@drawable/ic_select_none_grey600</item>
+ <item name="ic_sort">@drawable/ic_sort_grey600_24dp</item>
+ <item name="ic_sd_storage">@drawable/ic_sd_storage_grey600_36dp</item>
+ <item name="ic_create_new_folder">@drawable/ic_create_new_folder_grey600_24dp</item>
+ <item name="ic_cast_disconnect">@drawable/ic_cast_disconnect_grey600_36dp</item>
+ <item name="ic_cellphone_text">@drawable/ic_cellphone_text_grey600_24dp</item>
+ <item name="ic_question_answer">@drawable/ic_forum_grey600_24dp</item>
+ <item name="ic_bug">@drawable/ic_bug_grey600_24dp</item>
+ <item name="ic_known_issues">@drawable/ic_format_list_bulleted_grey600_24dp</item>
+
+ <item name="master_switch_background">@color/master_switch_background_light</item>
+ <item name="currently_playing_background">@color/highlight_light</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
- <item type="attr" name="about_screen_background">#e5e5e5</item>
- <item type="attr" name="about_screen_card_background">#ffffff</item>
- <item type="attr" name="about_screen_card_border">#d2d2d2</item>
- <item type="attr" name="about_screen_font_color">#000000</item>
+ <item name="about_screen_background">#e5e5e5</item>
+ <item name="about_screen_card_background">#ffffff</item>
+ <item name="about_screen_card_border">#d2d2d2</item>
+ <item name="about_screen_font_color">#000000</item>
</style>
<style name="Theme.AntennaPod.Dark" parent="Theme.Base.AntennaPod.Dark">
@@ -95,74 +95,74 @@
<item name="buttonStyle">@style/Widget.AntennaPod.Button</item>
<item name="progressBarTheme">@style/ProgressBarDark</item>
<item name="alertDialogTheme">@style/AntennaPod.Dialog.Dark</item>
- <item type="attr" name="action_bar_icon_color">@color/white</item>
- <item type="attr" name="storage">@drawable/ic_sd_white_24dp</item>
- <item type="attr" name="ic_swap">@drawable/ic_swap_vertical_white_24dp</item>
- <item type="attr" name="statistics">@drawable/ic_poll_box_white_24dp</item>
- <item type="attr" name="action_about">@drawable/ic_info_white_24dp</item>
- <item type="attr" name="checkbox_multiple">@drawable/ic_checkbox_multiple_marked_outline_white_24dp</item>
- <item type="attr" name="action_search">@drawable/ic_search_white_24dp</item>
- <item type="attr" name="action_stream">@drawable/ic_settings_input_antenna_white_24dp</item>
- <item type="attr" name="av_download">@drawable/ic_file_download_white_24dp</item>
- <item type="attr" name="av_fast_forward">@drawable/ic_fast_forward_white_24dp</item>
- <item type="attr" name="av_pause">@drawable/ic_pause_white_24dp</item>
- <item type="attr" name="av_play">@drawable/ic_play_arrow_white_24dp</item>
- <item type="attr" name="av_rewind">@drawable/ic_fast_rewind_white_24dp</item>
- <item type="attr" name="content_discard">@drawable/ic_delete_white_24dp</item>
- <item type="attr" name="content_new">@drawable/ic_add_white_24dp</item>
- <item type="attr" name="content_remove_from_queue">@drawable/ic_remove_white</item>
- <item type="attr" name="feed">@drawable/ic_feed_white_24dp</item>
- <item type="attr" name="location_web_site">@drawable/ic_web_white_24dp</item>
- <item type="attr" name="navigation_accept">@drawable/ic_done_white_24dp</item>
- <item type="attr" name="navigation_cancel">@drawable/ic_cancel_white_24dp</item>
- <item type="attr" name="navigation_expand">@drawable/ic_expand_more_white_36dp</item>
- <item type="attr" name="navigation_refresh">@drawable/ic_refresh_white_24dp</item>
- <item type="attr" name="navigation_up">@drawable/navigation_up_dark</item>
- <item type="attr" name="social_share">@drawable/ic_share_white_24dp</item>
- <item type="attr" name="stat_playlist">@drawable/ic_list_white_24dp</item>
- <item type="attr" name="type_audio">@drawable/ic_hearing_white_18dp</item>
- <item type="attr" name="type_video">@drawable/ic_remove_red_eye_white_18dp</item>
- <item type="attr" name="non_transparent_background">@color/black</item>
- <item type="attr" name="overlay_background">@color/overlay_dark</item>
- <item type="attr" name="overlay_drawable">@drawable/overlay_drawable_dark</item>
- <item type="attr" name="dragview_background">@drawable/ic_drag_vertical_white_48dp</item>
- <item type="attr" name="dragview_float_background">@color/black</item>
- <item type="attr" name="nav_drawer_background">@color/nav_drawer_background_dark</item>
- <item type="attr" name="drawer_activated_color">@color/nav_drawer_highlighted_dark</item>
- <item type="attr" name="ic_new">@drawable/ic_new_releases_white_24dp</item>
- <item type="attr" name="ic_history">@drawable/ic_history_white_24dp</item>
- <item type="attr" name="ic_folder">@drawable/ic_folder_white_24dp</item>
- <item type="attr" name="av_play_big">@drawable/ic_play_arrow_white_36dp</item>
- <item type="attr" name="av_pause_big">@drawable/ic_pause_white_36dp</item>
- <item type="attr" name="av_ff_big">@drawable/ic_fast_forward_white_36dp</item>
- <item type="attr" name="av_rew_big">@drawable/ic_fast_rewind_white_36dp</item>
- <item type="attr" name="av_skip_big">@drawable/ic_skip_white_36dp</item>
- <item type="attr" name="ic_fav">@drawable/ic_star_border_white_24dp</item>
- <item type="attr" name="ic_unfav">@drawable/ic_star_white_24dp</item>
- <item type="attr" name="ic_settings">@drawable/ic_settings_white_24dp</item>
- <item type="attr" name="ic_lock_open">@drawable/ic_lock_open_white_24dp</item>
- <item type="attr" name="ic_lock_closed">@drawable/ic_lock_closed_white_24dp</item>
- <item type="attr" name="ic_filter">@drawable/ic_filter_white_24dp</item>
- <item type="attr" name="ic_sleep">@drawable/ic_sleep_white_24dp</item>
- <item type="attr" name="ic_sleep_off">@drawable/ic_sleep_off_white_24dp</item>
- <item type="attr" name="ic_select_all">@drawable/ic_select_all_white</item>
- <item type="attr" name="ic_select_none">@drawable/ic_select_none_white</item>
- <item type="attr" name="ic_sort">@drawable/ic_sort_white_24dp</item>
- <item type="attr" name="ic_sd_storage">@drawable/ic_sd_storage_white_36dp</item>
- <item type="attr" name="ic_create_new_folder">@drawable/ic_create_new_folder_white_24dp</item>
- <item type="attr" name="ic_cast_disconnect">@drawable/ic_cast_disconnect_white_36dp</item>
- <item type="attr" name="ic_cellphone_text">@drawable/ic_cellphone_text_white_24dp</item>
- <item type="attr" name="ic_question_answer">@drawable/ic_baseline_question_answer_white_24dp</item>
- <item type="attr" name="ic_bug">@drawable/ic_bug_white_24dp</item>
- <item type="attr" name="ic_known_issues">@drawable/ic_format_list_bulleted_white_24dp</item>
- <item type="attr" name="master_switch_background">@color/master_switch_background_dark</item>
- <item type="attr" name="currently_playing_background">@color/highlight_dark</item>
+ <item name="action_bar_icon_color">@color/white</item>
+ <item name="storage">@drawable/ic_sd_white_24dp</item>
+ <item name="ic_swap">@drawable/ic_swap_vertical_white_24dp</item>
+ <item name="statistics">@drawable/ic_poll_box_white_24dp</item>
+ <item name="action_about">@drawable/ic_info_white_24dp</item>
+ <item name="checkbox_multiple">@drawable/ic_checkbox_multiple_marked_outline_white_24dp</item>
+ <item name="action_search">@drawable/ic_search_white_24dp</item>
+ <item name="action_stream">@drawable/ic_settings_input_antenna_white_24dp</item>
+ <item name="av_download">@drawable/ic_file_download_white_24dp</item>
+ <item name="av_fast_forward">@drawable/ic_fast_forward_white_24dp</item>
+ <item name="av_pause">@drawable/ic_pause_white_24dp</item>
+ <item name="av_play">@drawable/ic_play_arrow_white_24dp</item>
+ <item name="av_rewind">@drawable/ic_fast_rewind_white_24dp</item>
+ <item name="content_discard">@drawable/ic_delete_white_24dp</item>
+ <item name="content_new">@drawable/ic_add_white_24dp</item>
+ <item name="content_remove_from_queue">@drawable/ic_remove_white</item>
+ <item name="feed">@drawable/ic_feed_white_24dp</item>
+ <item name="location_web_site">@drawable/ic_web_white_24dp</item>
+ <item name="navigation_accept">@drawable/ic_done_white_24dp</item>
+ <item name="navigation_cancel">@drawable/ic_cancel_white_24dp</item>
+ <item name="navigation_expand">@drawable/ic_expand_more_white_36dp</item>
+ <item name="navigation_refresh">@drawable/ic_refresh_white_24dp</item>
+ <item name="navigation_up">@drawable/navigation_up_dark</item>
+ <item name="social_share">@drawable/ic_share_white_24dp</item>
+ <item name="stat_playlist">@drawable/ic_list_white_24dp</item>
+ <item name="type_audio">@drawable/ic_hearing_white_18dp</item>
+ <item name="type_video">@drawable/ic_remove_red_eye_white_18dp</item>
+ <item name="non_transparent_background">@color/black</item>
+ <item name="overlay_background">@color/overlay_dark</item>
+ <item name="overlay_drawable">@drawable/overlay_drawable_dark</item>
+ <item name="dragview_background">@drawable/ic_drag_vertical_white_48dp</item>
+ <item name="dragview_float_background">@color/black</item>
+ <item name="nav_drawer_background">@color/nav_drawer_background_dark</item>
+ <item name="drawer_activated_color">@color/nav_drawer_highlighted_dark</item>
+ <item name="ic_new">@drawable/ic_new_releases_white_24dp</item>
+ <item name="ic_history">@drawable/ic_history_white_24dp</item>
+ <item name="ic_folder">@drawable/ic_folder_white_24dp</item>
+ <item name="av_play_big">@drawable/ic_play_arrow_white_36dp</item>
+ <item name="av_pause_big">@drawable/ic_pause_white_36dp</item>
+ <item name="av_ff_big">@drawable/ic_fast_forward_white_36dp</item>
+ <item name="av_rew_big">@drawable/ic_fast_rewind_white_36dp</item>
+ <item name="av_skip_big">@drawable/ic_skip_white_36dp</item>
+ <item name="ic_fav">@drawable/ic_star_border_white_24dp</item>
+ <item name="ic_unfav">@drawable/ic_star_white_24dp</item>
+ <item name="ic_settings">@drawable/ic_settings_white_24dp</item>
+ <item name="ic_lock_open">@drawable/ic_lock_open_white_24dp</item>
+ <item name="ic_lock_closed">@drawable/ic_lock_closed_white_24dp</item>
+ <item name="ic_filter">@drawable/ic_filter_white_24dp</item>
+ <item name="ic_sleep">@drawable/ic_sleep_white_24dp</item>
+ <item name="ic_sleep_off">@drawable/ic_sleep_off_white_24dp</item>
+ <item name="ic_select_all">@drawable/ic_select_all_white</item>
+ <item name="ic_select_none">@drawable/ic_select_none_white</item>
+ <item name="ic_sort">@drawable/ic_sort_white_24dp</item>
+ <item name="ic_sd_storage">@drawable/ic_sd_storage_white_36dp</item>
+ <item name="ic_create_new_folder">@drawable/ic_create_new_folder_white_24dp</item>
+ <item name="ic_cast_disconnect">@drawable/ic_cast_disconnect_white_36dp</item>
+ <item name="ic_cellphone_text">@drawable/ic_cellphone_text_white_24dp</item>
+ <item name="ic_question_answer">@drawable/ic_baseline_question_answer_white_24dp</item>
+ <item name="ic_bug">@drawable/ic_bug_white_24dp</item>
+ <item name="ic_known_issues">@drawable/ic_format_list_bulleted_white_24dp</item>
+ <item name="master_switch_background">@color/master_switch_background_dark</item>
+ <item name="currently_playing_background">@color/highlight_dark</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
- <item type="attr" name="about_screen_background">#303030</item>
- <item type="attr" name="about_screen_card_background">#424242</item>
- <item type="attr" name="about_screen_card_border">#262626</item>
- <item type="attr" name="about_screen_font_color">#ffffff</item>
+ <item name="about_screen_background">#303030</item>
+ <item name="about_screen_card_background">#424242</item>
+ <item name="about_screen_card_border">#262626</item>
+ <item name="about_screen_font_color">#ffffff</item>
</style>
<style name="Theme.AntennaPod.TrueBlack" parent="Theme.Base.AntennaPod.TrueBlack">
@@ -171,13 +171,13 @@
<style name="Theme.Base.AntennaPod.TrueBlack" parent="Theme.Base.AntennaPod.Dark">
<item name="progressBarTheme">@style/ProgressBarTrueBlack</item>
- <item type="attr" name="non_transparent_background">@color/black</item>
- <item type="attr" name="overlay_background">@color/black</item>
- <item type="attr" name="overlay_drawable">@drawable/overlay_drawable_dark_trueblack</item>
- <item type="attr" name="dragview_background">@drawable/ic_drag_vertical_white_48dp</item>
- <item type="attr" name="dragview_float_background">@color/black</item>
- <item type="attr" name="nav_drawer_background">@color/black</item>
- <item type="attr" name="drawer_activated_color">@color/highlight_trueblack</item>
+ <item name="non_transparent_background">@color/black</item>
+ <item name="overlay_background">@color/black</item>
+ <item name="overlay_drawable">@drawable/overlay_drawable_dark_trueblack</item>
+ <item name="dragview_background">@drawable/ic_drag_vertical_white_48dp</item>
+ <item name="dragview_float_background">@color/black</item>
+ <item name="nav_drawer_background">@color/black</item>
+ <item name="drawer_activated_color">@color/highlight_trueblack</item>
<item name="android:textColorPrimary">@color/white</item>
<item name="android:color">@color/white</item>
<item name="android:colorBackground">@color/black</item>
@@ -214,14 +214,14 @@
<style name="Theme.Base.AntennaPod.TrueBlack.NoTitle" parent="Theme.Base.AntennaPod.Dark.NoTitle">
<item name="progressBarTheme">@style/ProgressBarTrueBlack</item>
- <item type="attr" name="non_transparent_background">@color/black</item>
- <item type="attr" name="overlay_background">@color/black</item>
- <item type="attr" name="overlay_drawable">@drawable/overlay_drawable_dark_trueblack</item>
- <item type="attr" name="dragview_background">@drawable/ic_drag_vertical_white_48dp</item>
- <item type="attr" name="dragview_float_background">@color/black</item>
- <item type="attr" name="nav_drawer_background">@color/black</item>
- <item type="attr" name="drawer_activated_color">@color/highlight_trueblack</item>
- <item type="attr" name="currently_playing_background">@color/highlight_trueblack</item>
+ <item name="non_transparent_background">@color/black</item>
+ <item name="overlay_background">@color/black</item>
+ <item name="overlay_drawable">@drawable/overlay_drawable_dark_trueblack</item>
+ <item name="dragview_background">@drawable/ic_drag_vertical_white_48dp</item>
+ <item name="dragview_float_background">@color/black</item>
+ <item name="nav_drawer_background">@color/black</item>
+ <item name="drawer_activated_color">@color/highlight_trueblack</item>
+ <item name="currently_playing_background">@color/highlight_trueblack</item>
<item name="android:textColorPrimary">@color/white</item>
<item name="android:color">@color/white</item>
<item name="android:colorBackground">@color/black</item>