aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/build.gradle18
-rw-r--r--app/src/google/AndroidManifest.xml30
-rw-r--r--app/src/main/java/github/daneren2005/dsub/provider/DLNARouteProvider.java24
-rw-r--r--app/src/main/java/github/daneren2005/dsub/service/DownloadService.java133
-rw-r--r--app/src/main/java/github/daneren2005/dsub/util/Notifications.java68
-rw-r--r--app/src/main/res/values-hu/strings.xml5
-rw-r--r--app/src/main/res/values-pt-rPT/strings.xml42
-rw-r--r--app/src/main/res/xml/changelog.xml16
8 files changed, 215 insertions, 121 deletions
diff --git a/app/build.gradle b/app/build.gradle
index 47604723..3c8e5f45 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,15 +1,15 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 24
+ compileSdkVersion 27
buildToolsVersion '25.0.0'
defaultConfig {
applicationId "github.daneren2005.dsub"
minSdkVersion 14
- targetSdkVersion 23
- versionCode 195
- versionName '5.3.5'
+ targetSdkVersion 26
+ versionCode 198
+ versionName '5.4.1'
setProperty("archivesBaseName", "DSub $versionName")
resConfigs "de", "es", "fr", "hu", "nl", "pt-rPT", "ru", "sv"
}
@@ -56,11 +56,11 @@ android {
dependencies {
compile project(':Server Proxy')
compile fileTree(include: ['*.jar'], dir: 'libs')
- compile 'com.android.support:support-v4:24.2.+'
- compile 'com.android.support:appcompat-v7:24.2.+'
- compile 'com.android.support:mediarouter-v7:24.2.+'
- compile 'com.android.support:recyclerview-v7:24.2.+'
- compile 'com.android.support:design:24.2.+'
+ compile 'com.android.support:support-v4:27.1.+'
+ compile 'com.android.support:appcompat-v7:27.1.+'
+ compile 'com.android.support:mediarouter-v7:27.1.+'
+ compile 'com.android.support:recyclerview-v7:27.1.+'
+ compile 'com.android.support:design:27.1.+'
googleCompile 'com.google.android.gms:play-services-cast:8.1.0'
compile 'com.sothree.slidinguppanel:library:3.0.0'
compile 'de.hdodenhof:circleimageview:1.2.1'
diff --git a/app/src/google/AndroidManifest.xml b/app/src/google/AndroidManifest.xml
index 14827d43..0708a47e 100644
--- a/app/src/google/AndroidManifest.xml
+++ b/app/src/google/AndroidManifest.xml
@@ -2,17 +2,23 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="github.daneren2005.dsub">
- <meta-data
- android:name="com.google.android.backup.api_key"
- android:value="AEdPqrEAAAAIUhOMtwa_eG-f0oYUHnetl_Cz7cO9zae8ZXOK5w" />
- <meta-data
- android:name="com.google.android.gms.version"
- android:value="@integer/google_play_services_version" />
- <meta-data
- android:name="com.google.android.gms.car.application"
- android:resource="@xml/auto_app_description" />
- <meta-data
- android:name="com.google.android.gms.car.notification.SmallIcon"
- android:resource="@drawable/stat_notify_playing" />
+ <application android:label="@string/common.appname"
+ android:backupAgent="github.daneren2005.dsub.util.SettingsBackupAgent"
+ android:icon="@drawable/launch"
+ android:theme="@style/Theme.DSub.Light">
+
+ <meta-data
+ android:name="com.google.android.backup.api_key"
+ android:value="AEdPqrEAAAAIUhOMtwa_eG-f0oYUHnetl_Cz7cO9zae8ZXOK5w" />
+ <meta-data
+ android:name="com.google.android.gms.version"
+ android:value="@integer/google_play_services_version" />
+ <meta-data
+ android:name="com.google.android.gms.car.application"
+ android:resource="@xml/auto_app_description" />
+ <meta-data
+ android:name="com.google.android.gms.car.notification.SmallIcon"
+ android:resource="@drawable/stat_notify_playing" />
+ </application>
</manifest>
diff --git a/app/src/main/java/github/daneren2005/dsub/provider/DLNARouteProvider.java b/app/src/main/java/github/daneren2005/dsub/provider/DLNARouteProvider.java
index 0ee16723..f4238c99 100644
--- a/app/src/main/java/github/daneren2005/dsub/provider/DLNARouteProvider.java
+++ b/app/src/main/java/github/daneren2005/dsub/provider/DLNARouteProvider.java
@@ -228,7 +228,9 @@ public class DLNARouteProvider extends MediaRouteProvider {
removing.remove(id);
return;
}
- adding.add(id);
+ synchronized (adding) {
+ adding.add(id);
+ }
if(device.getType().getType().equals("MediaRenderer") && device instanceof RemoteDevice) {
try {
@@ -255,21 +257,35 @@ public class DLNARouteProvider extends MediaRouteProvider {
broadcastDescriptors();
}
});
- adding.remove(id);
+
+ synchronized (adding) {
+ if (adding.contains(id)) {
+ adding.remove(id);
+ }
+ }
}
@Override
public void failure(ActionInvocation actionInvocation, UpnpResponse upnpResponse, String s) {
Log.w(TAG, "Failed to get default volume for DLNA route");
Log.w(TAG, "Reason: " + s);
- adding.remove(id);
+
+ synchronized (adding) {
+ if (adding.contains(id)) {
+ adding.remove(id);
+ }
+ }
}
});
} catch(Exception e) {
Log.e(TAG, "Failed to add device", e);
}
} else {
- adding.remove(id);
+ synchronized (adding) {
+ if(adding.contains(id)) {
+ adding.remove(id);
+ }
+ }
}
}
private void deviceRemoved(Device device) {
diff --git a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java
index c5caad26..a4ca705c 100644
--- a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java
+++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java
@@ -68,6 +68,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
+import java.util.concurrent.CopyOnWriteArrayList;
import android.annotation.TargetApi;
import android.app.Service;
@@ -154,7 +155,7 @@ public class DownloadService extends Service {
private boolean removePlayed;
private boolean shufflePlay;
private boolean artistRadio;
- private final List<OnSongChangedListener> onSongChangedListeners = new ArrayList<>();
+ private final CopyOnWriteArrayList<OnSongChangedListener> onSongChangedListeners = new CopyOnWriteArrayList<>();
private long revision;
private static DownloadService instance;
private String suggestedPlaylistName;
@@ -2800,12 +2801,7 @@ public class DownloadService extends Service {
addOnSongChangedListener(listener, false);
}
public void addOnSongChangedListener(OnSongChangedListener listener, boolean run) {
- synchronized(onSongChangedListeners) {
- int index = onSongChangedListeners.indexOf(listener);
- if (index == -1) {
- onSongChangedListeners.add(listener);
- }
- }
+ onSongChangedListeners.addIfAbsent(listener);
if(run) {
if(mediaPlayerHandler != null) {
@@ -2824,56 +2820,47 @@ public class DownloadService extends Service {
}
}
public void removeOnSongChangeListener(OnSongChangedListener listener) {
- synchronized(onSongChangedListeners) {
- int index = onSongChangedListeners.indexOf(listener);
- if (index != -1) {
- onSongChangedListeners.remove(index);
- }
- }
+ onSongChangedListeners.remove(listener);
}
private void onSongChanged() {
final long atRevision = revision;
- synchronized(onSongChangedListeners) {
- final boolean shouldFastForward = shouldFastForward();
- for (final OnSongChangedListener listener : onSongChangedListeners) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- if (revision == atRevision && instance != null) {
- listener.onSongChanged(currentPlaying, currentPlayingIndex, shouldFastForward);
+ final boolean shouldFastForward = shouldFastForward();
+ for (final OnSongChangedListener listener : onSongChangedListeners) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (revision == atRevision && instance != null) {
+ listener.onSongChanged(currentPlaying, currentPlayingIndex, shouldFastForward);
- MusicDirectory.Entry entry = currentPlaying != null ? currentPlaying.getSong() : null;
- listener.onMetadataUpdate(entry, METADATA_UPDATED_ALL);
- }
+ MusicDirectory.Entry entry = currentPlaying != null ? currentPlaying.getSong() : null;
+ listener.onMetadataUpdate(entry, METADATA_UPDATED_ALL);
}
- });
- }
+ }
+ });
+ }
- if (mediaPlayerHandler != null && !onSongChangedListeners.isEmpty()) {
- mediaPlayerHandler.post(new Runnable() {
- @Override
- public void run() {
- onSongProgress();
- }
- });
- }
+ if (mediaPlayerHandler != null && !onSongChangedListeners.isEmpty()) {
+ mediaPlayerHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ onSongProgress();
+ }
+ });
}
}
private void onSongsChanged() {
final long atRevision = revision;
- synchronized(onSongChangedListeners) {
- final boolean shouldFastForward = shouldFastForward();
- for (final OnSongChangedListener listener : onSongChangedListeners) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- if (revision == atRevision && instance != null) {
- listener.onSongsChanged(downloadList, currentPlaying, currentPlayingIndex, shouldFastForward);
- }
+ final boolean shouldFastForward = shouldFastForward();
+ for (final OnSongChangedListener listener : onSongChangedListeners) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (revision == atRevision && instance != null) {
+ listener.onSongsChanged(downloadList, currentPlaying, currentPlayingIndex, shouldFastForward);
}
- });
- }
+ }
+ });
}
}
@@ -2888,17 +2875,15 @@ public class DownloadService extends Service {
final int index = getCurrentPlayingIndex();
final int queueSize = size();
- synchronized(onSongChangedListeners) {
- for (final OnSongChangedListener listener : onSongChangedListeners) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- if (revision == atRevision && instance != null) {
- listener.onSongProgress(currentPlaying, position, duration, isSeekable);
- }
+ for (final OnSongChangedListener listener : onSongChangedListeners) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (revision == atRevision && instance != null) {
+ listener.onSongProgress(currentPlaying, position, duration, isSeekable);
}
- });
- }
+ }
+ });
}
if(manual) {
@@ -2921,35 +2906,31 @@ public class DownloadService extends Service {
}
private void onStateUpdate() {
final long atRevision = revision;
- synchronized(onSongChangedListeners) {
- for (final OnSongChangedListener listener : onSongChangedListeners) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- if (revision == atRevision && instance != null) {
- listener.onStateUpdate(currentPlaying, playerState);
- }
+ for (final OnSongChangedListener listener : onSongChangedListeners) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (revision == atRevision && instance != null) {
+ listener.onStateUpdate(currentPlaying, playerState);
}
- });
- }
+ }
+ });
}
}
public void onMetadataUpdate() {
onMetadataUpdate(METADATA_UPDATED_ALL);
}
public void onMetadataUpdate(final int updateType) {
- synchronized(onSongChangedListeners) {
- for (final OnSongChangedListener listener : onSongChangedListeners) {
- handler.post(new Runnable() {
- @Override
- public void run() {
- if (instance != null) {
- MusicDirectory.Entry entry = currentPlaying != null ? currentPlaying.getSong() : null;
- listener.onMetadataUpdate(entry, updateType);
- }
+ for (final OnSongChangedListener listener : onSongChangedListeners) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (instance != null) {
+ MusicDirectory.Entry entry = currentPlaying != null ? currentPlaying.getSong() : null;
+ listener.onMetadataUpdate(entry, updateType);
}
- });
- }
+ }
+ });
}
handler.post(new Runnable() {
diff --git a/app/src/main/java/github/daneren2005/dsub/util/Notifications.java b/app/src/main/java/github/daneren2005/dsub/util/Notifications.java
index 750ab40c..428c33e0 100644
--- a/app/src/main/java/github/daneren2005/dsub/util/Notifications.java
+++ b/app/src/main/java/github/daneren2005/dsub/util/Notifications.java
@@ -15,7 +15,9 @@
package github.daneren2005.dsub.util;
+import android.annotation.TargetApi;
import android.app.Notification;
+import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ComponentName;
@@ -56,11 +58,24 @@ public final class Notifications {
private static boolean downloadForeground = false;
private static boolean persistentPlayingShowing = false;
+ private static NotificationChannel playingChannel;
+ private static NotificationChannel downloadingChannel;
+ private static NotificationChannel syncChannel;
+
private final static Pair<Integer, Integer> NOTIFICATION_TEXT_COLORS = new Pair<Integer, Integer>();
public static void showPlayingNotification(final Context context, final DownloadService downloadService, final Handler handler, MusicDirectory.Entry song) {
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ getPlayingNotificationChannel(context);
+ }
+
// Set the icon, scrolling text and timestamp
- final Notification notification = new Notification(R.drawable.stat_notify_playing, song.getTitle(), System.currentTimeMillis());
+ final Notification notification = new NotificationCompat.Builder(context)
+ .setSmallIcon(R.drawable.stat_notify_playing)
+ .setTicker(song.getTitle())
+ .setWhen(System.currentTimeMillis())
+ .setChannelId("now-playing-channel")
+ .build();
final boolean playing = downloadService.getPlayerState() == PlayerState.STARTED;
if(playing) {
@@ -331,7 +346,24 @@ public final class Notifications {
DSubWidgetProvider.notifyInstances(context, downloadService, false);
}
+ @TargetApi(Build.VERSION_CODES.O)
+ private static NotificationChannel getPlayingNotificationChannel(Context context) {
+ if(playingChannel == null) {
+ playingChannel = new NotificationChannel("now-playing-channel", "Now Playing", NotificationManager.IMPORTANCE_LOW);
+ playingChannel.setDescription("Now playing notification");
+
+ NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
+ notificationManager.createNotificationChannel(playingChannel);
+ }
+
+ return playingChannel;
+ }
+
public static void showDownloadingNotification(final Context context, final DownloadService downloadService, Handler handler, DownloadFile file, int size) {
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ getDownloadingNotificationChannel(context);
+ }
+
Intent cancelIntent = new Intent(context, DownloadService.class);
cancelIntent.setAction(DownloadService.CANCEL_DOWNLOADS);
PendingIntent cancelPI = PendingIntent.getService(context, 0, cancelIntent, 0);
@@ -356,7 +388,8 @@ public final class Notifications {
.setOngoing(true)
.addAction(R.drawable.notification_close,
context.getResources().getString(R.string.common_cancel),
- cancelPI);
+ cancelPI)
+ .setChannelId("downloading-channel");
Intent notificationIntent = new Intent(context, SubsonicFragmentActivity.class);
notificationIntent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD_VIEW, true);
@@ -395,6 +428,19 @@ public final class Notifications {
}
}
+ @TargetApi(Build.VERSION_CODES.O)
+ private static NotificationChannel getDownloadingNotificationChannel(Context context) {
+ if(downloadingChannel == null) {
+ downloadingChannel = new NotificationChannel("downloading-channel", "Downloading Notification", NotificationManager.IMPORTANCE_LOW);
+ downloadingChannel.setDescription("Ongoing downloading notification to keep the service alive");
+
+ NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
+ notificationManager.createNotificationChannel(downloadingChannel);
+ }
+
+ return downloadingChannel;
+ }
+
public static void showSyncNotification(final Context context, int stringId, String extra) {
showSyncNotification(context, stringId, extra, null);
}
@@ -404,6 +450,10 @@ public final class Notifications {
extra = "";
}
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ getSyncNotificationChannel(context);
+ }
+
NotificationCompat.Builder builder;
builder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.stat_notify_sync)
@@ -413,6 +463,7 @@ public final class Notifications {
.setOngoing(false)
.setGroup(NOTIFICATION_SYNC_GROUP)
.setPriority(NotificationCompat.PRIORITY_LOW)
+ .setChannelId("sync-channel")
.setAutoCancel(true);
Intent notificationIntent = new Intent(context, SubsonicFragmentActivity.class);
@@ -449,4 +500,17 @@ public final class Notifications {
notificationManager.notify(stringId, builder.build());
}
}
+
+ @TargetApi(Build.VERSION_CODES.O)
+ private static NotificationChannel getSyncNotificationChannel(Context context) {
+ if(syncChannel == null) {
+ syncChannel = new NotificationChannel("sync-channel", "Sync Notifications", NotificationManager.IMPORTANCE_MIN);
+ syncChannel.setDescription("Sync notifications");
+
+ NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
+ notificationManager.createNotificationChannel(syncChannel);
+ }
+
+ return syncChannel;
+ }
}
diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml
index 3416a471..6a2799ea 100644
--- a/app/src/main/res/values-hu/strings.xml
+++ b/app/src/main/res/values-hu/strings.xml
@@ -346,6 +346,8 @@
<string name="settings.max_bitrate_unlimited">Korlátlan</string>
<string name="settings.wifi_required_title">Streamelés csak Wi-Fivel</string>
<string name="settings.wifi_required_summary">Streamelés csak Wi-Fi hálózaton keresztül.</string>
+ <string name="settings.local_network_required_title">Ne streameljen roaming közben</string>
+ <string name="settings.local_network_required_summary">Ne streameljen médiát roaming közben</string>
<string name="settings.network_timeout_title">Hálózati időtúllépés</string>
<string name="settings.network_timeout_10000">10 másodperc</string>
<string name="settings.network_timeout_15000">15 másodperc</string>
@@ -491,6 +493,8 @@
<string name="settings.casting_cache_summary">Az éppen lejátszott dal gyorsítótárazása a tartalomátküldés (Casting) alatt.</string>
<string name="settings.casting.dlna_casting_enabled">DLNA engedélyezve</string>
<string name="settings.casting.dlna_casting_enabled.summary">Ha akkumulátor-merülési probléma lépne fel Android 7.0 alatt, kapcsolja ki a funkciót!</string>
+ <string name="settings.rewind_interval">Visszatekerés időintervalluma</string>
+ <string name="settings.fastforward_interval">Gyors előretekerés időintervalluma</string>
<string name="shuffle.title">Dalsorrend keverése</string>
<string name="shuffle.startYear">Kezdő év:</string>
@@ -498,6 +502,7 @@
<string name="shuffle.genre">Műfaj:</string>
<string name="shuffle.pick_genre">Műfaj kiválasztása</string>
+ <string name="share.create_error">%s megosztás létrehozása sikertelen!</string>
<string name="share.expires">Lejárati idő: %s</string>
<string name="share.expires_never">Nincs lejárati idő</string>
<string name="share.deleted">\"%s\" megosztás törölve</string>
diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml
index 885035a4..c8f59195 100644
--- a/app/src/main/res/values-pt-rPT/strings.xml
+++ b/app/src/main/res/values-pt-rPT/strings.xml
@@ -50,11 +50,11 @@
<string name="main.faq_text">
<![CDATA[
<font color="red">Cache vs Cache permanente</font>:
- <br/>Quando o DSub transfere as músicas, as mesmas poderão ser eliminadas mais tarde para dar espaço para novas transferências. Por outro lado, as músicas que ficam permanentemente na cache nunca serão eliminadas.
+ <br/>Quando o DSub transfere as músicas, as mesmas poderão vir a ser eliminadas para dar espaço a novas transferências. Por outro lado, as músicas que ficam permanentemente na cache nunca serão eliminadas automaticamente.
<p/><font color="red">Falhas com o Chromecast</font>:
<br/>Experimente a opção Definições -> Transmissão -> Usar dispositivo como proxy. É uma solução alternativa devido ao Chromecast não aceitar certificados auto-assinados.
<p/><font color="red">Primeiro nível na biblioteca são grupos de artistas</font>:
- <br/>No menu de opções, desmarque a opção "Artistas no primeiro nível". Isto fará com que o primeiro nível de diretorias apresentado seja tratado como grupos de artistas em vez de artistas propriamente ditos.
+ <br/>No menu de opções, desmarque a opção "Artistas no primeiro nível". Isto fará com que o primeiro nível de diretórios apresentado seja tratado como grupos de artistas em vez de artistas propriamente ditos.
]]>
</string>
<string name="main.shuffle">Aleatório</string>
@@ -102,7 +102,7 @@
<string name="menu.add_podcast">Adicionar canal</string>
<string name="menu.keep_synced">Manter sincronizado</string>
<string name="menu.stop_sync">Parar sincronização</string>
- <string name="menu.show_all">Mostrar todo o conteúdo</string>
+ <string name="menu.show_all">Mostrar todas as músicas</string>
<string name="menu.show_artist">Mostrar artista</string>
<string name="menu.share">Partilhar</string>
<string name="menu.delete_cache">Eliminar cache</string>
@@ -161,8 +161,8 @@
<string name="select_genre.songs">%d músicas</string>
<string name="select_genre.albums">%d álbuns</string>
- <string name="select_podcasts.error">Houve um erro ao transferir este podcast no servidor. O servidor deve transferi-lo primeiro.</string>
- <string name="select_podcasts.skipped">Este podcast não foi transferido no servidor. O servidor deve transferi-lo primeiro.</string>
+ <string name="select_podcasts.error">Ocorreu um erro ao transferir este podcast no servidor. O servidor deve de o transferir primeiro.</string>
+ <string name="select_podcasts.skipped">Este podcast não foi transferido no servidor. O servidor deve de o transferir primeiro.</string>
<string name="select_podcasts.initializing">Este podcast está a ser inicializado no servidor. Por favor atualize dentro de momentos.</string>
<string name="select_podcasts.server_download">Transferir no servidor</string>
<string name="select_podcasts.server_delete">Eliminar do servidor</string>
@@ -282,13 +282,13 @@
<string name="settings.server_password">Palavra-passe</string>
<string name="settings.server_open_browser">Abrir no navegador</string>
<string name="settings.server_sync_summary">Ativar ou não a sincronização para este servidor</string>
- <string name="settings.server_sync">Sincronização ativa</string>
+ <string name="settings.server_sync">Ativar sincronização</string>
<string name="settings.cache_title">Cache de música</string>
<string name="settings.preload_wifi">Músicas para pré-carregar (Wi-Fi)</string>
<string name="settings.preload_mobile">Músicas para pré-carregar (dados móveis)</string>
<string name="settings.cache_size">Tamanho da cache</string>
<string name="settings.cache_location">Localização da cache</string>
- <string name="settings.cache_location_error">Localização da cache inválida. A utilizar predefinição.</string>
+ <string name="settings.cache_location_error">Localização da cache inválida. A usar predefinição.</string>
<string name="settings.cache_location_reset">Não foi possível escrever na localização da cache que definiu. Se atualizou recentemente o SO do seu dispositivo para o KitKat 4.4, então o modo como as aplicações escrevem no cartão SD mudou e só podem escrever numa localização específica. A localização que o DSub usa já foi alterada para a localização correta. Para eliminar os antigos dados da aplicação, terá que montar o cartão SD no computador e eliminar a pasta manualmente</string>
<string name="settings.cache_location_internal">Interna</string>
<string name="settings.cache_location_external">Externa</string>
@@ -320,6 +320,7 @@
<string name="settings.max_bitrate_wifi">Taxa de bits máxima do áudio - Wi-Fi</string>
<string name="settings.max_bitrate_mobile">Taxa de bits máxima do áudio - Dados móveis</string>
<string name="settings.max_bitrate_32">32 Kbps</string>
+ <string name="settings.max_bitrate_48">48 Kbps</string>
<string name="settings.max_bitrate_64">64 Kbps</string>
<string name="settings.max_bitrate_80">80 Kbps</string>
<string name="settings.max_bitrate_96">96 Kbps</string>
@@ -383,7 +384,7 @@
<string name="settings.temp_loss_nothing">Não fazer nada</string>
<string name="settings.keep_played_count_title">Manter as músicas reproduzidas</string>
<string name="settings.keep_played_count_none">Remover todas as músicas reproduzidas</string>
- <string name="settings.keep_played_count_one">Manter as últimas músicas reproduzidas</string>
+ <string name="settings.keep_played_count_one">Manter a última música reproduzida</string>
<string name="settings.keep_played_count_two">Manter as 2 últimas músicas reproduzidas</string>
<string name="settings.keep_played_count_three">Manter as 3 últimas músicas reproduzidas</string>
<string name="settings.disconnect_pause_title">Pausar ao desconectar</string>
@@ -400,7 +401,7 @@
<string name="settings.video_player">Reprodutor de vídeo</string>
<string name="settings.video_raw">Raw (Requer Subsonic 4.8+)</string>
<string name="settings.video_hls">HTTP Live Stream (HLS) (Requer Subsonic 4.8+)</string>
- <string name="settings.video_transcode">Transcodificação direta (Requer vídeo -> mp4 ou configuração similar no servidor</string>
+ <string name="settings.video_transcode">Transcodificação direta (Requer vídeo -> mp4 ou configuração semelhante no servidor</string>
<string name="settings.video_flash">Flash (Requer plugin)</string>
<string name="settings.cache_screen_title">Cache/Ligação</string>
<string name="settings.playback_title">Reprodução</string>
@@ -415,8 +416,8 @@
<string name="settings.shares_enabled">Ativar partilhas</string>
<string name="settings.shares_enabled_summary">Mostrar ou não a opção \"Partilhas\" no menu lateral</string>
<string name="settings.sync_title">Sincronização</string>
- <string name="settings.sync_enabled">Sincronização ativa</string>
- <string name="settings.sync_enabled_summary">Verificar periodicamente ou não as listas de reprodução ou podcasts por alterações</string>
+ <string name="settings.sync_enabled">Ativar sincronização</string>
+ <string name="settings.sync_enabled_summary">Verificar ou não periodicamente as listas de reprodução ou podcasts por alterações</string>
<string name="settings.sync_interval">Intervalo de sincronização</string>
<string name="settings.sync_interval_15">15 minutos</string>
<string name="settings.sync_interval_30">30 minutos</string>
@@ -445,8 +446,8 @@
<string name="settings.menu_options.star_summary">Mostrar \"Marcar/Remover estrela\" nos menus</string>
<string name="settings.menu_options.shared_summary">Mostrar \"Partilhar\" nos menus</string>
<string name="settings.menu_options.rate_summary">Mostrar \"Classificar\" nos menus</string>
- <string name="settings.browse_by_tags">Procurar por tags</string>
- <string name="settings.browse_by_tags_summary">Procurar por tags em vez da estrutura das pastas. Requer Subsonic 4.7+</string>
+ <string name="settings.browse_by_tags">Navegar por etiquetas</string>
+ <string name="settings.browse_by_tags_summary">Navegar por etiquetas em vez da estrutura das pastas. Requer Subsonic 4.7+</string>
<string name="settings.disable_exit_prompt">Desativar diálogo de saída</string>
<string name="settings.disable_exit_prompt_summary">Fechar a aplicação imediatamente após pressionar o botão de voltar no ecrã inicial</string>
<string name="settings.override_system_language">Sobrepor linguagem do sistema</string>
@@ -462,11 +463,11 @@
<string name="settings.admin_enabled">Ativar administração</string>
<string name="settings.admin_enabled_summary">Mostrar ou não a opção \"Administração\" no menu lateral</string>
<string name="settings.replay_gain">Replay Gain</string>
- <string name="settings.replay_gain_summary">Escalar ou não o volume da reprodução por tags \"replay gain\" nos álbuns e faixas</string>
- <string name="settings.replay_gain_type">Ler pelas tags</string>
+ <string name="settings.replay_gain_summary">Escalar ou não o volume da reprodução por etiquetas \"replay gain\" nos álbuns e faixas</string>
+ <string name="settings.replay_gain_type">Ler pelas etiquetas</string>
<string name="settings.replay_gain_type.smart">Deteção inteligente</string>
- <string name="settings.replay_gain_type.album">Tags nos álbuns</string>
- <string name="settings.replay_gain_type.track">Tags nas faixas</string>
+ <string name="settings.replay_gain_type.album">Etiquetas nos álbuns</string>
+ <string name="settings.replay_gain_type.track">Etiquetas nas faixas</string>
<string name="settings.replay_gain_bump">Pré-amplificação do Replay Gain</string>
<string name="settings.replay_gain_untagged">Músicas sem Replay Gain</string>
<string name="settings.casting">Transmissão</string>
@@ -487,7 +488,12 @@
<string name="settings.heads_up_notification_summary">Mostrar notificações de reprodução como notificações \"Heads Up\" (Android Lollipop+ apenas)</string>
<string name="settings.casting_cache">Cache durante a transmissão</string>
<string name="settings.casting_cache_summary">Adicionar à cache as músicas a reproduzir no momento da transmissão</string>
+ <string name="settings.casting.dlna_casting_enabled">Ativar DLNA</string>
+ <string name="settings.casting.dlna_casting_enabled.summary">Se tiver problemas com o descarregamento da bateria no Android 7.0 experimente desativar isto</string>
+ <string name="settings.rewind_interval">Intervalo de retrocesso</string>
+ <string name="settings.fastforward_interval">Intervalo de avanço</string>
+ <string name="share.create_error">Falha ao criar a partilha %s</string>
<string name="shuffle.title">Aleatorizar por</string>
<string name="shuffle.startYear">Ano de início:</string>
<string name="shuffle.endYear">Ano de fim:</string>
@@ -521,7 +527,7 @@
<string name="admin.change_email_invalid">Introduza um email válido</string>
<string name="admin.change_password">Alterar palavra-passe</string>
<string name="admin.change_password_success">A palavra-passe de %1$s foi alterada com sucesso</string>
- <string name="admin.change_password_error">Falha ao alterar palavra-passe de %1$s</string>
+ <string name="admin.change_password_error">Falha ao alterar a palavra-passe de %1$s</string>
<string name="admin.change_password_current_label">Palavra-passe atual:</string>
<string name="admin.change_password_label">Nova palavra-passe:</string>
<string name="admin.change_password_invalid">Introduza uma palavra-passe válida</string>
diff --git a/app/src/main/res/xml/changelog.xml b/app/src/main/res/xml/changelog.xml
index d31f6df6..8aa15153 100644
--- a/app/src/main/res/xml/changelog.xml
+++ b/app/src/main/res/xml/changelog.xml
@@ -1,5 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<changelog>
+ <release version="5.4.1" versioncode="198" releasedate="07/29/2018">
+ <change>Fix Android Auto compatibility</change>
+ </release>
+ <release version="5.4" versioncode="197" releasedate="07/26/2018">
+ <change>Add option to change rewind/fast forward interval (thanks KBerstene)</change>
+ <change>Auto: Play entire directory when selecting song (thanks hufman)</change>
+ <change>Auto: Show 50 songs instead of 3 (thanks hufman)</change>
+ <change>Auto: Fix playing from a bookmark when multiple bookmarks in directory (thanks hufman)</change>
+ <change>Add option to disable downloads while roaming (thanks The-Compiler)</change>
+ <change>Fix persistent notification showing different actions when paused</change>
+ <change>Fix OPUS files not showing up in Offline mode</change>
+ <change>Fix not being able to have servers with _ in the domain</change>
+ <change>Fix cache exceeding limit with long playlist</change>
+ <change>Fix error if null album when applying ReplayGain</change>
+ <change>Fix deadlock bug</change>
+ </release>
<release version="5.3.5" versioncode="195" releasedate="04/18/2016">
<change>Add option to scan server for Subsonic 6.1+</change>
<change>Enhanced custom playback speed UI (thanks SilentViking)</change>