From cf7738effe4230e2fbfc54dc327bc17b2ab1fc4c Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 10 Apr 2015 20:37:18 +0200 Subject: LoudnessEnhancer for Android 4.4+ --- .../main/java/com/aocate/media/AndroidMediaPlayer.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/com/aocate/media/AndroidMediaPlayer.java b/core/src/main/java/com/aocate/media/AndroidMediaPlayer.java index 17ee74a13..c0aeba722 100644 --- a/core/src/main/java/com/aocate/media/AndroidMediaPlayer.java +++ b/core/src/main/java/com/aocate/media/AndroidMediaPlayer.java @@ -14,13 +14,15 @@ package com.aocate.media; -import java.io.IOException; - import android.content.Context; import android.media.MediaPlayer; +import android.media.audiofx.LoudnessEnhancer; import android.net.Uri; +import android.os.Build; import android.util.Log; +import java.io.IOException; + public class AndroidMediaPlayer extends MediaPlayerImpl { private final static String AMP_TAG = "AocateAndroidMediaPlayer"; @@ -205,6 +207,15 @@ public class AndroidMediaPlayer extends MediaPlayerImpl { Log.d(AMP_TAG, " ++++++++++++++++++++++++++++++++ Setting prepared listener to this.onPreparedListener"); mp.setOnPreparedListener(this.onPreparedListener); mp.setOnSeekCompleteListener(this.onSeekCompleteListener); + + // loudness enhancer + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + int audioSession = mp.getAudioSessionId(); + LoudnessEnhancer effect = new LoudnessEnhancer(audioSession); + effect.setTargetGain(600); // amplify up to 6 dB + effect.setEnabled(true); + Log.d(AMP_TAG, "Loudness enhancer enabled"); + } } @Override -- cgit v1.2.3 From 5fe65f470e4f5e279e57f5107975428f3c232eab Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Wed, 22 Apr 2015 11:21:59 +0200 Subject: Reorganize episode cache size values --- core/src/main/res/values/arrays.xml | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index ccf14d329..57de2ca2e 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -39,30 +39,24 @@ 12 24 + - @string/pref_episode_cache_unlimited - 1 - 2 5 10 - 20 - 40 - 60 - 80 + 25 + 50 100 + @string/pref_episode_cache_unlimited - -1 - 1 - 2 5 10 - 20 - 40 - 60 - 80 + 25 + 50 100 + -1 + 0.5 0.6 -- cgit v1.2.3 From c856e48382eaedd1c17bf1c3d38909a852c84bac Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Thu, 21 May 2015 19:08:09 -0400 Subject: Revert "LoudnessEnhancer for Android 4.4+" --- core/src/main/java/com/aocate/media/AndroidMediaPlayer.java | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/com/aocate/media/AndroidMediaPlayer.java b/core/src/main/java/com/aocate/media/AndroidMediaPlayer.java index c0aeba722..7c2ea3d61 100644 --- a/core/src/main/java/com/aocate/media/AndroidMediaPlayer.java +++ b/core/src/main/java/com/aocate/media/AndroidMediaPlayer.java @@ -16,9 +16,7 @@ package com.aocate.media; import android.content.Context; import android.media.MediaPlayer; -import android.media.audiofx.LoudnessEnhancer; import android.net.Uri; -import android.os.Build; import android.util.Log; import java.io.IOException; @@ -207,15 +205,6 @@ public class AndroidMediaPlayer extends MediaPlayerImpl { Log.d(AMP_TAG, " ++++++++++++++++++++++++++++++++ Setting prepared listener to this.onPreparedListener"); mp.setOnPreparedListener(this.onPreparedListener); mp.setOnSeekCompleteListener(this.onSeekCompleteListener); - - // loudness enhancer - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - int audioSession = mp.getAudioSessionId(); - LoudnessEnhancer effect = new LoudnessEnhancer(audioSession); - effect.setTargetGain(600); // amplify up to 6 dB - effect.setEnabled(true); - Log.d(AMP_TAG, "Loudness enhancer enabled"); - } } @Override -- cgit v1.2.3 From 53bf17ada858f000c59ffdb53146599f225a7de6 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Mon, 25 May 2015 20:50:51 -0400 Subject: reverting to tryLock for getPosition. Fixes AntennaPod/AntennaPod#829 --- .../antennapod/core/service/playback/PlaybackServiceMediaPlayer.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 243ee78e4..7a8e38c59 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -534,7 +534,9 @@ public class PlaybackServiceMediaPlayer { * Returns the position of the current media object or INVALID_TIME if the position could not be retrieved. */ public int getPosition() { - playerLock.lock(); + if (!playerLock.tryLock()) { + return INVALID_TIME; + } int retVal = INVALID_TIME; if (playerStatus == PlayerStatus.PLAYING -- cgit v1.2.3 From 1bf803a6b21c1547cb66d679b927e983f670e2a2 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 28 May 2015 11:41:36 +0200 Subject: Remove cancel, adjust strings --- core/src/main/res/values/strings.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index c6308fa7b..5150f9bd8 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -161,10 +161,10 @@ Authentication required The resource you requested requires a username and a password Confirm Mobile Download - Downloading over mobile data connection is disabled in the settings.\n\nEnable temporarily or just add to queue?\n\nYour choice will be remember for 10 minutes. - Downloading over mobile data connection is disabled in the settings.\n\nEnable temporarily?\n\nYour choice will be remember for 10 minutes. - Only add to Queue - Enable temporarily + Downloading over mobile data connection is disabled in the settings.\n\nYou can choose to either only add the episode to the queue or you can allow downloading temporarily.\n\nYour choice will be remember for 10 minutes. + Downloading over mobile data connection is disabled in the settings.\n\nDo you want to allow downloading temporarily?\n\nYour choice will be remember for 10 minutes. + Enqueue + Allow temporarily Error! -- cgit v1.2.3 From fb9349ead0f4083a7de99f5eb135523a7b97e256 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 28 May 2015 11:57:07 +0200 Subject: Queued episodes that are played can now be auto downloaded --- core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java | 1 - 1 file changed, 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java index 11348953e..1168c60e4 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java @@ -403,7 +403,6 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr return this.hasMedia() && false == this.getMedia().isPlaying() && false == this.getMedia().isDownloaded() && - false == this.isRead() && this.getAutoDownload(); } -- cgit v1.2.3 From ef518f3ec0a489d843da4af053767d9f59fa827f Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 28 May 2015 22:42:08 +0200 Subject: Handle failed refresh correctly, fix for nav drawer layout --- core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index e570ee709..defce5930 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -308,10 +308,11 @@ public final class DBTasks { private static void refreshFeed(Context context, Feed feed, boolean loadAllPages) throws DownloadRequestException { Feed f; + Date lastUpdate = feed.hasLastUpdateFailed() ? new Date(0) : feed.getLastUpdate(); if (feed.getPreferences() == null) { - f = new Feed(feed.getDownload_url(), feed.getLastUpdate(), feed.getTitle()); + f = new Feed(feed.getDownload_url(), lastUpdate, feed.getTitle()); } else { - f = new Feed(feed.getDownload_url(), feed.getLastUpdate(), feed.getTitle(), + f = new Feed(feed.getDownload_url(), lastUpdate, feed.getTitle(), feed.getPreferences().getUsername(), feed.getPreferences().getPassword()); } f.setId(feed.getId()); -- cgit v1.2.3 From bd4b7e2f64da01048416ad3ca78b69f707c01f84 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Thu, 28 May 2015 17:46:33 -0400 Subject: updated strings --- core/src/main/res/values-az/strings.xml | 5 -- core/src/main/res/values-ca/strings.xml | 8 --- core/src/main/res/values-cs-rCZ/strings.xml | 28 +++++--- core/src/main/res/values-da/strings.xml | 8 --- core/src/main/res/values-de/strings.xml | 11 --- core/src/main/res/values-es-rES/strings.xml | 5 -- core/src/main/res/values-es/strings.xml | 11 --- core/src/main/res/values-fr/strings.xml | 2 - core/src/main/res/values-hi-rIN/strings.xml | 5 -- core/src/main/res/values-it-rIT/strings.xml | 11 +-- core/src/main/res/values-iw-rIL/strings.xml | 11 --- core/src/main/res/values-ja/strings.xml | 52 +++++++++++--- core/src/main/res/values-ko/strings.xml | 11 --- core/src/main/res/values-nl/strings.xml | 5 -- core/src/main/res/values-pl-rPL/strings.xml | 8 --- core/src/main/res/values-pt-rBR/strings.xml | 5 -- core/src/main/res/values-pt/strings.xml | 101 ++++++++++++++++++---------- core/src/main/res/values-ro-rRO/strings.xml | 5 -- core/src/main/res/values-ru/strings.xml | 15 ++++- core/src/main/res/values-sv-rSE/strings.xml | 11 --- core/src/main/res/values-tr/strings.xml | 11 --- core/src/main/res/values-uk-rUA/strings.xml | 56 +++++++++++---- core/src/main/res/values-zh-rCN/strings.xml | 60 ++++++++++++++--- 23 files changed, 233 insertions(+), 212 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values-az/strings.xml b/core/src/main/res/values-az/strings.xml index b52ecf4a4..8c56cc671 100644 --- a/core/src/main/res/values-az/strings.xml +++ b/core/src/main/res/values-az/strings.xml @@ -43,7 +43,6 @@ Kanalın URLı - Hamısını oxunmuş kimi işarələ Məlumatı göstər Web-səhifəyi paylaş Kanalı paylaş @@ -54,8 +53,6 @@ Pauza İnternetən yayimla Sil - Oxumuş kimi işarələ - Oxunmamış kimi işarələ Növbəyə əlavə et Növbədən sil Web-səhifəsini aç @@ -76,8 +73,6 @@ Əlaqə xətasi Naməlum xost Yükləmələrin hamısını ləğv et - Yükləmə ləğv olundu - Yükləmə başa çatdı Yanlış URL IO xətasi Tələbin xətası diff --git a/core/src/main/res/values-ca/strings.xml b/core/src/main/res/values-ca/strings.xml index be7a73e6d..b03ae3b6f 100644 --- a/core/src/main/res/values-ca/strings.xml +++ b/core/src/main/res/values-ca/strings.xml @@ -66,8 +66,6 @@ Podeu cercar nous podcasts al directori de gpodder.net mitjançant el seu nom, categoria o popularitat. Navega gpodder.net - Marca-ho tot com a llegit - S\'han marcat tots els episodis com a llegits Mostra informació Esborra podcast Comparteix l\'enllaç de la plana @@ -83,8 +81,6 @@ Reprodueix sense baixar Suprimeix Esborra episodi - Marca com a llegit - Marca com a pendent Afegeix a la cua Suprimeix de la cua Visita el lloc web @@ -108,8 +104,6 @@ Amfitrió desconegut Error d\'autenticació Cancel·la totes les baixades - S\'ha cancel·lat la baixada - Baixades completades URL mal formatada Error d\'E/S Error de petició @@ -240,8 +234,6 @@ Canvia les dades d\'inici de sessió del vostre compte de gpodder.net Velocitats de reproducció Personalitzeu les velocitats disponibles per a una velocitat de reproducció d\'àudio variable - Salta a l\'instant - Salta aquesta quantitat de segons en rebobinar o en avançar ràpidament Definex nom del servidor Utilitza el servidor per defecte Amplia la notificació diff --git a/core/src/main/res/values-cs-rCZ/strings.xml b/core/src/main/res/values-cs-rCZ/strings.xml index 661faefbe..e110c3adc 100644 --- a/core/src/main/res/values-cs-rCZ/strings.xml +++ b/core/src/main/res/values-cs-rCZ/strings.xml @@ -58,6 +58,7 @@ Zavřít Zkusit znovu Zahrnout do automaticky stahovaných + \u0020paralelních stahování URL kanálu URL nebo webová stránka kanálu @@ -66,8 +67,6 @@ Můžete vyhledávat nové podcasty podle jména, kategorie nebo popularity v seznamu gpodder.net. Prohledávat gpodder.net - Označit vše jako přečtené - Označit všechny epizody jako přečtené Informace o zdroji Odstranit podcast Sdílet odkaz @@ -83,8 +82,6 @@ Vysílat Odstranit Odstranit epizodu - Označit jako přečtené - Označit jako nepřečtené Přidat do fronty Odebrat z fronty Navštívit stránku @@ -108,8 +105,6 @@ Neznámý host Chyba přihlášení Zrušit všechna stahování - Stahování zrušeno - Všechna stahování dokončena Chybné URL IO chyba Chyba požadavku @@ -150,6 +145,7 @@ Délka Vzestupně Sestupně + Prosím potvrďte, že chcete vyčistit tuto frontu a VŠECHNY v ní obsažené epizody Flattr přihlášení Stiskněte následující tlačítko pro spuštění autentizačního procesu. Budete přesměrováni na přihlašovací obrazovku flattru a vyzváni k potvrzení udělení práv pro použití flattru aplikací AntennaPod. Po udělení práv se automaticky vrátíte na tuto obrazovku. @@ -165,10 +161,17 @@ Přístup ukončen Úspěšně revokován přístup AntennPodu k vašemu účtu. Pro dokončení tohoto procesu je ještě zapotřebí na stránkách flattru odebrat z vašeho účtu AntennaPod ze seznamu povolených aplikací. + Flattrován jeden příspěvek! + Flattrováno %d příspěvků! + Flattrován: %s. + Selhalo flattrování %d příspěvků! + Neflattrováno: %s. + Příspěvek bude flattrován později Flattruji %s AntennaPod flattruje AntennaPod flattroval AntennaPod flattr selhal + Získávání flattrovaných příspěvků Stáhnout plugin Plugin není nainstalován @@ -218,6 +221,7 @@ Povolit automatické stahování pouze pomocí vybraných Wi-Fi sítí. Stahovat, pokud neprobíhá nabíjení Povolit automatické stahování i pokud není baterie nabíjena + Paralelní stahování Historie epizod Světlý Tmavý @@ -233,8 +237,6 @@ Změní přihlašovací údaje k vašemu gpodder.net účtu. Rychlosti přehrávání Přizpůsobení rychlosti je dostupné pro přehrávání zvuku různými rychlostmi - Čas poskočení - Poskočí o vybraný počet sekund při posunu zpět nebo vpřed Nastavit hostname Použít přednastaveného hosta Rozšířené upozornění @@ -242,6 +244,8 @@ Pevné ovládání přehrávání Zachovat upozornění a ovládání na obrazovce uzamčení i při pozastaveném přehrávání. Verze Androidu nižší než 4.1 nepodporují rozšířená upozornění. + Přidávat nové epizody na začátek fronty. + Přidat na začátek. Povolit automatické flattrování Flattrovat díl jakmile bude odehráno %d procent @@ -256,6 +260,9 @@ Nalezeno v názvu OPML soubory umožňují přenést vaše podcasty z jednoho přehrávače na jiný. + Vybrat umístění v místním souborovém systému. + Použít externí aplikaci jako třeba Dropbox, Google Drive nebo oblíbeného správce souborů k otevření OPML souboru. + Mnoho aplikací jako třeba Google Mail, Dropbox, Google Drive a většina správců souborů umí otevřít OPML soubory v aplikaci AntennaPod. Importovat OPML import CHYBA! @@ -264,6 +271,8 @@ Adresář importu je prázdný. Označit vše Zrušit výběr + Z místního souborového systému + Použít externí aplikaci OPML export Exportuji... Chyba exportu @@ -283,7 +292,7 @@ KATEGORIE TOP PODCASTY DOPORUČENÉ - Vyhledat na gpodder.net + Prohledat gpodder.net Přihlásit Vítejte do průvodce přihlášením ke gpodder.net účtu. Zadejte vaše přihlašovací údaje: Přihlásit @@ -349,4 +358,5 @@ Změnit uživatelské jméno a heslo pro tento podcast a jeho epizody. Importuji odběry z jednoúčelových aplikací... + Prohledat iTunes diff --git a/core/src/main/res/values-da/strings.xml b/core/src/main/res/values-da/strings.xml index ba7fafca6..2253a9e9c 100644 --- a/core/src/main/res/values-da/strings.xml +++ b/core/src/main/res/values-da/strings.xml @@ -66,8 +66,6 @@ Du kan søge efter nye podcasts efter navn, kategori eller popularitet i gpodder.net biblioteket Gennemse gpodder.net - Marker alle som læst - Marker alle episoder som læst Vis information Fjern podcast Del webside link @@ -83,8 +81,6 @@ Stream Fjern Fjern episode - Marker som læst - Marker som ulæst Tilføj til kø Fjern fra kø Besøg webside @@ -108,8 +104,6 @@ Ukendt vært Godkendelses fejl Annuller alle downloads - Download afbrudt - Downloads afsluttet Misdannet URL IO fejl Anmode fejl @@ -240,8 +234,6 @@ Skift din gpodder.net kontos login information. Afspilningshastigheder Tilpas tilgængelige hastigheder for variabelt afspilningshastigheds plugin - Søg tid - Søg så mange sekunder når der spoles tilbage eller frem Indstil værtsnavn Brug standard vært Udvid notifikation diff --git a/core/src/main/res/values-de/strings.xml b/core/src/main/res/values-de/strings.xml index f2d0a66ad..9383559b0 100644 --- a/core/src/main/res/values-de/strings.xml +++ b/core/src/main/res/values-de/strings.xml @@ -67,10 +67,6 @@ Bei gpodder.net kannst du neue Podcasts nach Name, Kategorie oder Popularität suchen. gpodder.net durchsuchen - Alle als gespielt markieren - Alle Episoden als gespielt markieren - Bitte bestätige, dass alle Episoden als gespielt markiert werden sollen. - Bitte bestätige, dass alle Episoden in diesem Feed als gespielt markiert werden sollen. Informationen anzeigen Podcast entfernen Webseiten-Link teilen @@ -86,9 +82,6 @@ Streamen Entfernen Episode entfernen - Als gespielt markieren - Als ungespielt markieren - Als gespielt markiert Zur Abspielliste hinzufügen Aus der Abspielliste entfernen Webseite besuchen @@ -112,8 +105,6 @@ Unbekannter Host Authentifizierungsfehler Alle Downloads abbrechen - Download abgebrochen - Download abgeschlossen Fehler in URL E/A Error Anfragefehler @@ -246,8 +237,6 @@ Ändere die Anmeldeinformationen deines gpodder.net Profils Wiedergabegeschwindigkeiten Lege die verfügbaren Werte für die Veränderung der Wiedergabeschwindigkeit fest - Spul-Zeit - Spule so viele Sekunden vor oder zurück Hostname ändern Standard-Host verwenden Benachrichtigung erweitern diff --git a/core/src/main/res/values-es-rES/strings.xml b/core/src/main/res/values-es-rES/strings.xml index d05c34876..bf753c113 100644 --- a/core/src/main/res/values-es-rES/strings.xml +++ b/core/src/main/res/values-es-rES/strings.xml @@ -39,7 +39,6 @@ URL del canal - Marcar todo como leído Información del programa Compartir el enlace de la web Compartir el enlace del canal @@ -50,8 +49,6 @@ Pausar Transmitir Quitar - Marcar como leído - Marcar como no leído Añadir a la cola Quitar de la cola Visitar el sitio web @@ -72,8 +69,6 @@ Error de conexión Host desconocido Cancelar todas las descargas - Descarga cancelada - Descargas completadas URL malformada Error de E/S Error de petición diff --git a/core/src/main/res/values-es/strings.xml b/core/src/main/res/values-es/strings.xml index eb1d1631b..5972bcdf2 100644 --- a/core/src/main/res/values-es/strings.xml +++ b/core/src/main/res/values-es/strings.xml @@ -67,10 +67,6 @@ Es posible buscar podcasts nuevos por nombre, categoría o popularidad en el directorio de gpodder.net. Explorar gpodder.net - Marcar todo como leído - Se marcaron todos los episodios como leídos - Por favor, confirme que desea marcar todos los episodios como leídos. - Por favor, confirme que desea marcar todos los episodios de este feed como leídos. Información del programa Eliminar podcast Compartir el enlace de la web @@ -86,9 +82,6 @@ Transmitir Quitar Quitar episodio - Marcar como leído - Marcar como no leído - Marcado como leído Añadir a la cola Quitar de la cola Visitar el sitio web @@ -112,8 +105,6 @@ Host desconocido Error de autenticación Cancelar todas las descargas - Descarga cancelada - Descargas completadas URL con formato incorrecto Error de E/S Error de solicitud @@ -246,8 +237,6 @@ Modificar datos de inicio de sesión en gpodder.net. Velocidades de reproducción Personalice las velocidades disponibles para la reproducción de audio a velocidad variable - Intervalo de búsqueda - Avanzar o retroceder esta cantidad de segundos Definir nombre de equipo Usar nombre de equipo por defecto Expandir Notificación diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml index 141b84bf7..57e967c70 100644 --- a/core/src/main/res/values-fr/strings.xml +++ b/core/src/main/res/values-fr/strings.xml @@ -246,8 +246,6 @@ Modifier les information de connexion pour votre compte gpodder.net Vitesses de lecture Modifier la liste des vitesses disponibles pour la lecture audio - Chercher un moment spécifique - Bouger d\'autant de secondes en rembobinant ou en faisant une avance rapide Choisir un nom de domaine Utiliser le nom de domaine par défaut Etendre la notification diff --git a/core/src/main/res/values-hi-rIN/strings.xml b/core/src/main/res/values-hi-rIN/strings.xml index f32c7c02f..d383765c5 100644 --- a/core/src/main/res/values-hi-rIN/strings.xml +++ b/core/src/main/res/values-hi-rIN/strings.xml @@ -52,7 +52,6 @@ यूआरएल द्वारा पॉडकास्ट जोड़ें पॉडकास्ट निर्देशिका - पढ़ने के रूप में सभी को चिह्नित करें जानकारी दिखाएँ पॉडकास्ट हटाएँ @@ -66,8 +65,6 @@ रोकें स्ट्रिम हटाएँ - पढ़ा हुआ के रूप में चिह्नित करें - ना पढ़ा हुआ के रूप में चिह्नित करें क़तार में जोड़ें क़तार से हटाएँ वेबसाइट पर जाएँ @@ -91,8 +88,6 @@ कनेक्शन त्रुटि अज्ञात होस्ट सभी डाउनलोड रद्द करें - डाउनलोड रद्द - डाउनलोड पूरा हो गया है गलत URL आईओ त्रुटि अनुरोध त्रुटि diff --git a/core/src/main/res/values-it-rIT/strings.xml b/core/src/main/res/values-it-rIT/strings.xml index 361657b6b..849ba2c7a 100644 --- a/core/src/main/res/values-it-rIT/strings.xml +++ b/core/src/main/res/values-it-rIT/strings.xml @@ -58,6 +58,7 @@ Chiudi Riprova Includi nei download automatici + \u0020download paralleli URL del feed www.example.com/feed @@ -66,8 +67,6 @@ Puoi cercare dei nuovi podcast in base al nome, alla categoria o alla popolarità nella directory di gpodder.net. Esplora gpodder.net - Segna tutti come letti - Segnati tutti gli episodi come letti Informazioni Rimuovi un podcast Condividi il link al sito @@ -83,9 +82,6 @@ Stream Rimuovi Rimuovi l\'episodio - Segna come letto - Segna come non letto - Segnato come letto Aggiungi alla coda Rimuovi dalla coda Visita il sito @@ -109,8 +105,6 @@ Host sconosciuto Errore di autenticazione Annulla tutti i download - Download annullato - Download completati URL malformato Errore IO Errore della richiesta @@ -242,8 +236,6 @@ Cambia le informazioni di login per il tuo account gpodder.net. Velocità di riproduzione Personalizza le velocità disponibili per la riproduzione audio a velocità variabile - Tempo di ricerca - Cerca tutti questi secondi quando si riavvolge o si va avanti velocemente Imposta l\'hostname Usa l\'host di default Espandi le notifiche @@ -273,6 +265,7 @@ La directory di importazione è vuota. Seleziona tutti Deseleziona tutti + Utilizza un\'applicazione esterna Esportazione su OPML Esportazione in corso... Errore di esportazione diff --git a/core/src/main/res/values-iw-rIL/strings.xml b/core/src/main/res/values-iw-rIL/strings.xml index 9e9c0e6bc..cf0e79aec 100644 --- a/core/src/main/res/values-iw-rIL/strings.xml +++ b/core/src/main/res/values-iw-rIL/strings.xml @@ -67,10 +67,6 @@ אפשר לחפש פודקסטים חדשים לפי בשם, קטגוריה או פופולריות בספריית gpodder.net. עיין בgpodder.net - סמן הכל כנקרא - סמן את כל הפרקים כנקרא - אנא אשר שאתה רוצה לסמן את כל פרקים כנקראים. - אנא אשר שאתה רוצה לסמן את כל פרקים בהזנה זו כנקראים. הצג מידע הסר פודקאסט שתף קישור אתר @@ -86,9 +82,6 @@ הזרם הסר הסר פרק - סמן כנקרא - סמן כלא נקרא - סומן כנקרא הוסף לתור הסר מהתור בקר באתר @@ -112,8 +105,6 @@ שרת לא ידוע שגיאת אימות בטל את כל ההורדות - הורדה בוטלה - הורדות הושלמו כתובת אתר שגויה שגיאת קלט פלט שגיאת בקשה @@ -247,8 +238,6 @@ שנה פרטי התחברות של חשבון gpodder.net. מהירויות ניגון התאמת המהיריות הזמינות לניגון במהירות משתנה - זמן דילוג - דלג מספר שניות זה בדילוג לאחור או קדימה הגדר שם שרת השתמש בשרת ברירת מידל הרחב הודעה diff --git a/core/src/main/res/values-ja/strings.xml b/core/src/main/res/values-ja/strings.xml index 9021b2b42..79411ffc1 100644 --- a/core/src/main/res/values-ja/strings.xml +++ b/core/src/main/res/values-ja/strings.xml @@ -26,6 +26,7 @@ メニューを開く メニューを閉じる + ドロワー設定 ブラウザーで開く URLをコピー @@ -39,6 +40,7 @@ キャンセル 作者 言語 + URL 設定 映像 エラー @@ -67,10 +69,10 @@ 名前、カテゴリや人気で、gpodder.netディレクトリ内の新しいポッドキャストを検索することができます。 gpodder.netを参照 - 既読としてマーク - すべてのエピソードを既読にしました - 既読としてマークするすべてのエピソードを確認してください。 - 既読としてマークするこのフィードのすべてのエピソードを確認してください。 + すべて再生済としてマーク + すべてのエピソードを再生済にしました + 再生済としてマークするすべてのエピソードを確認してください。 + 再生済としてマークするこのフィードのすべてのエピソードを確認してください。 情報を表示 ポッドキャストを削除 Webサイトのリンクを共有 @@ -78,6 +80,16 @@ このフィードと、このフィードのダウンロードしたすべてのエピソードを削除することを確認してください。 フィードの削除中 フィードをすべて更新 + エピソードを非表示にする + 未再生 + 一時停止しました + 再生しました + キューに入れました + キューに入っていません + ダウンロードしました + ダウンロードしていません + フィルターしました + {fa-exclamation-circle} 前回更新に失敗しました ダウンロード 再生 @@ -86,16 +98,20 @@ ストリーム 削除 エピソードを削除 - 既読にする - 未読にする - 既読 + 再生済としてマーク + 未再生としてマーク + 再生済としてマークしました キューに追加 + キューに追加しました キューから削除 Webサイトを訪問 これをFlattr すべてキューに入れる すべてダウンロード エピソードをスキップ + 自動ダウンロードを有効にする + 自動ダウンロードを無効にする + 再生位置をリセット 完成 失敗 @@ -113,7 +129,9 @@ 認証エラー すべてのダウンロードをキャンセル ダウンロードをキャンセルしました - ダウンロードが完了しました + ダウンロードをキャンセルしました\nこのアイテムの 自動ダウンロード を無効にしました + ダウンロードがエラーで完了しました + ダウンロード レポート 不正な形式のURL IOエラー リクエストエラー @@ -129,6 +147,11 @@ ファイルのダウンロード中にエラーが発生しました:\u0020 認証が必要です リクエストしたリソースは、ユーザー名とパスワードが必要です + モバイルダウンロードの確認 + モバイルデータ接続でのダウンロードは設定で無効になっています。\n\n一時的に有効にするか、またはキューに追加するだけにしますか?\n\n選択は 10 分間記憶されます。 + モバイルデータ接続でのダウンロードは設定で無効になっています。\n\n一時的に有効にしますか?\n\n選択は 10 分間記憶されます。 + キューに追加するだけ + 一時的に有効にする エラー! 再生するメディアがありません @@ -143,6 +166,8 @@ ポッドキャストを再生中 AntennaPod - 不明なメディアキー: %1$d + キューをロック + キューのロックを解除 キューをクリア 元に戻す アイテムを削除しました @@ -200,6 +225,8 @@ 再生が完了した時に次のキューのアイテムに移動します 再生が完了した時にエピソードを削除します 自動削除 + 一定の秒数未満の再生時間がまだ残っている場合でも、エピソードを再生済としてマークします + 再生済としてスマートマーク 再生 ネットワーク 更新間隔 @@ -223,6 +250,8 @@ 自動Flattrを構成 インターフェース テーマを選択 + ナビゲーションドロワーを変更 + ナビゲーションドロワーに表示するアイテムを変更します。 AntennaPodの外観を変更します。 自動ダウンロード エピソードの自動ダウンロードを構成します。 @@ -246,8 +275,8 @@ gpodder.netアカウントのログイン情報を変更します。 再生速度 可変速度音声再生に使用可能な速度をカスタマイズします - シーク時間 - 巻き戻しまたは早送り時にこの秒数でシークします + 早送り時間 + 巻き戻し時間 ホスト名をセット デフォルトホストを使用 拡張通知 @@ -257,6 +286,7 @@ Androidバージョン4.1以前では、拡張通知をサポートしていません。 新しいエピソードをキューの先頭に追加します。 キューの先頭に入れる + 無効 自動Flattrを有効にする %d %再生したらエピソードをFlattr @@ -341,6 +371,8 @@ デフォルトのフォルダーを選択 他のアプリがサウンドを再生したい時に、音量を下げる代わりに再生の一時停止します 割り込み時に一時停止 + 着信が完了した後に再生を再開します + 着信後に再開 購読 購読しました diff --git a/core/src/main/res/values-ko/strings.xml b/core/src/main/res/values-ko/strings.xml index 7830be329..b330d1ecb 100644 --- a/core/src/main/res/values-ko/strings.xml +++ b/core/src/main/res/values-ko/strings.xml @@ -67,10 +67,6 @@ gpodder.net 디렉터리에서 이름, 분류, 인기에 따라 새 팟캐스트를 검색할 수 있고, iTunes 스토어에서 검색할 수도 있습니다. gpodder.net 둘러보기 - 모두 읽은 것으로 표시 - 모든 에피소드 읽은 것으로 표시 - 에피소드 모두를 읽은 것으로 표시하는지 확인하십시오. - 이 피드의 에피소드 모두를 읽은 것으로 표시하는지 확인하십시오. 정보 표시 팟캐스트 제거 홈페이지 링크 공유 @@ -86,9 +82,6 @@ 스트리밍 제거 에피소드 제거 - 읽은 것으로 표시 - 읽지 않은 것으로 표시 - 읽은 것으로 표시 대기열에 추가 대기열에서 제거 홈페이지 보기 @@ -112,8 +105,6 @@ 알 수 없는 호스트 인증 오류 모든 다운로드 취소 - 다운로드 취소됨 - 다운로드 마침 URL 형식 틀림 입출력 오류 요청 오류 @@ -246,8 +237,6 @@ gpodder.net 계정의 로그인 정보를 바꿉니다. 재생 속도 여러가지 오디오 재생 속도 직접 설정 - 넘기기 간격 - 뒤나 앞으로 이동할 때 몇 초를 넘어갈지 지정합니다 호스트 이름 설정 기본 호스트 사용 알림 확장 diff --git a/core/src/main/res/values-nl/strings.xml b/core/src/main/res/values-nl/strings.xml index 0f447d54a..baa800486 100644 --- a/core/src/main/res/values-nl/strings.xml +++ b/core/src/main/res/values-nl/strings.xml @@ -51,7 +51,6 @@ Feed URL Podcast toevoegen bij URL - Alles als gelezen markeren Toon informatie Website link delen Feed link delen @@ -63,8 +62,6 @@ Pauze Stream Verwijderen - Als gelezen markeren - Als ongelezen markeren Voeg toe aan wachtrij Verwijder van wachtrij Website bezoeken @@ -86,8 +83,6 @@ Onbekende host Authenticatie fout Alle downloads annuleren - Download geannuleerd - Downloads afgerond Misvormde URL IO fout Fout in de aanvraag diff --git a/core/src/main/res/values-pl-rPL/strings.xml b/core/src/main/res/values-pl-rPL/strings.xml index ba1a0bb91..03b9a6b11 100644 --- a/core/src/main/res/values-pl-rPL/strings.xml +++ b/core/src/main/res/values-pl-rPL/strings.xml @@ -66,8 +66,6 @@ Możesz wyszukiwać nowe podcasty ze względu na nazwę, kategorię lub popularność na gpodder.net Przeglądaj gpodder.net - Oznacz wszystkie jako przeczytane - Wszystkie odcinki zaznaczone jako przeczytane Pokaż informacje Usuń podcast Udostępnij stronę @@ -83,8 +81,6 @@ Strumień Usuń Usuń odcinek - Oznacz jako przeczytane - Oznacz jako nieprzeczytane Dodaj do kolejki Usuń z kolejki Odwiedź stronę @@ -108,8 +104,6 @@ Nieznany host Błąd autoryzacji Anuluj wszystkie pobierania - Pobieranie anulowane - Pobieranie ukończone Niepoprawny adres Błąd wejścia/wyjścia Błąd żądania @@ -238,8 +232,6 @@ Zmień dane logowania konta gpodder.net. Prędkość odtwarzania Dostosuj prędkości dostępne dla odtwarzania audio o zmiennej prędkości - Seek time - Przeskocz o tyle sekund przewijając Ustaw nazwę hosta Użyj domyślnego hosta Rozwiń Powiadomienia diff --git a/core/src/main/res/values-pt-rBR/strings.xml b/core/src/main/res/values-pt-rBR/strings.xml index c3523acfb..d7d1e181c 100644 --- a/core/src/main/res/values-pt-rBR/strings.xml +++ b/core/src/main/res/values-pt-rBR/strings.xml @@ -51,7 +51,6 @@ URL do Feed Adicionar podcast por URL - Marcar todos como lido Mostrar informação Compartilhar link do site Compartilhar link do feed @@ -63,8 +62,6 @@ Pausar Stream Remover - Marcar como lido - Marcar como não lido Adicionar à fila Remover da fila Visitar Website @@ -85,8 +82,6 @@ Erro de conexão Host desconhecido Cancelar todos os downloads - Download cancelado - Downloads finalizados URL inválida Erro de IO Erro de requisição diff --git a/core/src/main/res/values-pt/strings.xml b/core/src/main/res/values-pt/strings.xml index d9e201e21..565f0f25e 100644 --- a/core/src/main/res/values-pt/strings.xml +++ b/core/src/main/res/values-pt/strings.xml @@ -26,11 +26,12 @@ Abrir menu Fechar menu + Preferências da gaveta Abrir no navegador Copiar URL Partilhar URL - URL copiado para a área de transferência. + URL copiado para a área de transferência Ir para esta posição Limpar histórico @@ -39,6 +40,7 @@ Cancelar Autor Idioma + URL Definições Imagem Erro @@ -64,20 +66,30 @@ URL da fonte ou sítio web Adicionar podcast via URL Localizar podcasts no diretório - Pode procurar os novos podcasts no gPodder.net por nome, categoria ou popularidade e também na loja iTunes. + Pode procurar por novos podcasts no gPodder.net e também na loja iTunes. Pode procurar por nome, categoria e popularidade. Procurar no gPodder.net - Marcar tudo como lido - Marcar todos os episódios como lidos - Por favor confirme que deseja marcar todos os episódios como lidos. - Por favor confirme que deseja marcar todos os episódios desta fonte como lidos. + Marcar tudo como reproduzido + Marcar todos os episódios como reproduzidos + Por favor confirme que deseja marcar todos os episódios como reproduzidos + Por favor confirme que deseja marcar todos os episódios desta fonte como reproduzidos Mostrar informações Remover podcast Partilhar ligação do sítio web Partilhar ligação da fonte - Confirme a eliminação desta fonte e de todos os episódios a ela petencentes. + Confirme a eliminação desta fonte e de todos os episódios a ela pertencentes Remover fonte Atualizar todas as páginas da fonte + Ocultar episódios + Não reproduzidos + Em pausa + Reproduzidos + Na fila + Não na fila + Transferidos + Não transferidos + Filtrados + {fa-exclamation-circle} Última atualização falhada Transferir Reproduzir @@ -86,16 +98,20 @@ Emitir Remover Remover episódio - Marcar como lido - Marcar como novo - Marcar como lido + Marcar como reproduzido + Marcar como não reproduzido + Marcado como reproduzido Adicionar à fila + Adicionado à fila Remover da fila Aceder ao sítio web Flattr Colocar tudo na fila Transferir tudo Ignorar episódio + Ativar transferência automática + Desativar transferência automática + Repor posição de reprodução sucesso falha @@ -113,7 +129,9 @@ Erro de autenticação Cancelar transferências Transferência cancelada - Transferências terminadas + Transferência cancelada\nTransferência automática desativada para este item + Transferências terminadas com erros + Relatório de transferências URL inválido Erro I/O Erro de pedido @@ -129,6 +147,8 @@ Ocorreu um erro ao transferir o ficheiro:\u0020 Requer autenticação O recurso solicitado requer um utilizador e uma senha + Apenas adicionados à fila + Ativar temporariamente Erro! Nada em reprodução @@ -143,6 +163,8 @@ Reproduzir podcast Tecla multimédia desconhecida: %1$d + Bloquear fila + Desbloquear fila Limpar fila Anular Item removido @@ -154,7 +176,7 @@ Duração Crescente Decrescente - Por favor confirme que deseja limpar todos os episódios da fila de reprodução. + Tem a certeza de que deseja remover todos os episódios da lista de reprodução? Sessão Flattr Prima o botão abaixo para iniciar a autenticação. O seu navegador web abrirá o ecrã da sessão flattr e ser-lhe-á solicitada a permissão para o AntennaPod efetuar as alterações. Após ser dada a permissão, voltará novamente a este ecrã. @@ -187,8 +209,8 @@ Para que a velocidade de reprodução variável funcione, tem que instalar um biblioteca de terceiros.\n\nClique em Transferir extra para a transferir no Google Play.\n\nQuaisquer problemas que ocorram na utilização do extra devem ser reportados diretamente ao seu programador. Velocidades de reprodução - Não existem itens na lista. - Ainda não possui quaisquer fontes. + Não existem itens nesta lista. + Ainda não possui quaisquer fontes Outras Sobre @@ -214,20 +236,22 @@ A atualizar Definições flattr Sessão flattr - Inicie sessão na sua conta flattr para fazer o flattr no AntennaPod. + Inicie sessão na sua conta flattr para fazer o flattr no AntennaPod Flattr desta aplicação Ajude no desenvolvimento do AntennaPod através do Flattr. Obrigado! Revogar acesso - Revogar permissões de acesso da aplicação à sua conta flattr. + Revogar permissões de acesso da aplicação à sua conta flattr Flattr automático Configurar flattr automático Interface Tema - Mudar o aspeto do AntennaPod. + Alterar itens da gaveta + Alterar os itens a aparecer na gaveta de navegação + Mudar o aspeto do AntennaPod Transferência automática - Configure a transferência automática dos episódios. + Configure a transferência automática dos episódios Ativar filtro Wi-Fi - Apenas permitir transferências automáticas através de redes sem fios. + Apenas permitir transferências automáticas através de redes sem fios Transferência se não estiver a carregar Permitir transferência automática se a bateria não estiver a ser carregada Transferências simultâneas @@ -239,24 +263,25 @@ hora Manual Acesso - Aceda à sua conta gpodder.net para poder sincronizar as subscrições. + Aceda à sua conta gpodder.net para poder sincronizar as subscrições Sair Sessão terminada Mudar informação de acesso - Mudar informação de acesso à sua conta gpodder.net. + Mudar informação de acesso à sua conta gpodder.net Velocidades de reprodução Personalize as velocidades de reprodução disponíveis. - Intervalo de procura - Ao recuar ou avançar, procurar este valor de segundos + Tempo a avançar + Tempo a recuar Definir nome de servidor Utilizar pré-definição Expansão de notificação - Expandir sempre a notificação para mostrar os botões de reprodução. + Expandir sempre a notificação para mostrar os botões de reprodução Controlos de reprodução persistentes - Manter controlos de notificação e ecrã de bloqueio ao colocar a reprodução em pausa. - As versões Android anteriores à 4.1 não possuem suporte à expansão de notificações. - Colocar novos episódios no inicio da fila. + Manter controlos de notificação e ecrã de bloqueio ao colocar a reprodução em pausa + As versões Android anteriores à 4.1 não possuem suporte à expansão de notificações + Colocar novos episódios no inicio da fila Novos episódios no inicio + Desativado Ativar flattr automático Flattr de episódios ao atingir %d porcento de reprodução @@ -270,16 +295,16 @@ Procura Encontrado no título - Os ficheiros OPML permitem-lhe mover os podcasts entre aplicações. - Escolha um caminho especifico no sistema local de ficheiros. - Utilize aplicações externas como o Dropbox, Google Drive ou o seu gestor de ficheiros preferido para abrir o ficheiro OPML. - As aplicações como o Google Mail, Dropbox, Google Drive ou gestores de ficheiros podem abrir os ficheiros OPML através do AntennaPod. + Os ficheiros OPML permitem-lhe mover os podcasts entre aplicações + Escolha um caminho especifico no sistema local de ficheiros + Utilize aplicações externas como o Dropbox, Google Drive ou o seu gestor de ficheiros preferido para abrir o ficheiro OPML + As aplicações como o Google Mail, Dropbox, Google Drive ou gestores de ficheiros podem abrir os ficheiros OPML através do AntennaPod Iniciar importação Importação OPML Erro! A ler ficheiro OPML Ocorreu um erro ao ler o ficheiro OPML: - O diretório de importação está vazio. + O diretório de importação está vazio Marcar tudo Desmarcar tudo Do sistema local de ficheiros @@ -287,7 +312,7 @@ Exportação OPML Exportação... Erro de exportação - Exportação efetuada. + Exportação efetuada O ficheiro .opml foi gravado em:\u0020 Definir temporizador @@ -313,7 +338,7 @@ Seleção de dispositivo Criar um novo dispositivo ou escolher um existente para aceder à sua conta gpodder.net ID do dispositivo:\u0020 - Legenda + Nome Criar novo dispositivo Escolher dispositivo: ID do dispositivo não pode estar vazia @@ -329,7 +354,7 @@ Ocorreu um erro ao sincronizar:\u0020 Diretório escolhido: - Criar diretório + Criar pasta Escolha o diretório Criar um diretório com o nome \"%1$s\"? Novo diretório criado @@ -341,10 +366,12 @@ Escolha a pasta pré-definida Pausa na reprodução em vez de baixar o volume se outra aplicação quiser reproduzir sons Pausa nas interrupções + Continuar reprodução ao terminar a chamada + Continuar após a chamada Subscrever Subscrito - Transferência... + A transferir... Mostrar capítulos Mostrar notas @@ -366,7 +393,7 @@ Carregar próxima página Autenticação - Altere o seu nome de utilizador e senha para este podcast e seus episódios. + Altere o seu nome de utilizador e senha para este podcast e seus episódios Importar subscrições de aplicações single-purpose... Procurar no iTunes diff --git a/core/src/main/res/values-ro-rRO/strings.xml b/core/src/main/res/values-ro-rRO/strings.xml index 390f50767..82851530a 100644 --- a/core/src/main/res/values-ro-rRO/strings.xml +++ b/core/src/main/res/values-ro-rRO/strings.xml @@ -47,7 +47,6 @@ Adresă feed - Marchează toate ca citite Arată informații Împarte adresă website Împarte adresă feed @@ -58,8 +57,6 @@ Pauză Stream Elimină - Marchează ca citit - Marchează ca necitit Adaugă la Coadă Șterge din Coadă Vizitează Website @@ -80,8 +77,6 @@ Eroare de conexiune Host necunoscut Anulează toate descărcările - Descărcare anulată - Descărcări terminate URL malformat Eroare IO Eroare cerere diff --git a/core/src/main/res/values-ru/strings.xml b/core/src/main/res/values-ru/strings.xml index 187a92861..ae10b314f 100644 --- a/core/src/main/res/values-ru/strings.xml +++ b/core/src/main/res/values-ru/strings.xml @@ -141,6 +141,7 @@ 00:00:00 Буферизация Воспроизведение подкаста + AntennaPod - неизвестный ключ носителя: %1$d Очистить очередь Отмена @@ -161,6 +162,7 @@ Вернуться к началу Успешная авторизация. Теперь можно использовать Flattr прямо из приложения. Токен Flattr не найден + Ваша учетная запись Flattr не подключена к AntennaPod. Нажмите здесь, чтобы войти. Кажется, ваш аккаунт Flattr не подключен к AntennaPod. Можно подключить аккаунт к AntennaPod или посетить сайт канала, чтобы пожертвовать через Flattr прямо на сайте. Авторизоваться Действие запрещено @@ -182,6 +184,7 @@ Загрузить плагин Плагин не установлен + Для работы переменной скорости воспроизведения нужно установить библиотеку стороннего разработчика.\n\nНажмите \"Загрузить плагин\", чтобы скачать бесплатный плагин из Play Store\n\nЛюбые вопросы по работе плагина находятся вне ответственности AntennaPod и должны быть направлены владельцу плагина. Скорость воспроизведения Список пуст @@ -217,6 +220,7 @@ Отозвать доступ Отменить доступ этого приложения к вашему аккаунту Flattr. Автоматически поддерживать через Flattr + Настройка автоматической поддержки через Flattr Интерфейс Выбор темы Изменить тему оформления AntennaPod @@ -242,8 +246,6 @@ Изменить информацию авторизации для аккаунта gpodder.net Скорость воспроизведения Настроить скорости воспроизведения - Перемотка - Пропускать секунд при перемотке назад или вперед Задать имя узла Использовать узел по умолчанию Расширенное уведомление @@ -251,7 +253,10 @@ Постоянный контрооль воспроизведения Сохранять уведомление и кнопки воспроизведения на экране блокировки во время паузы. Версии Android ниже 4.1 не поддерживают расширенные уведомления. + Добавлять новые выпуски в начало очереди. + В начало очереди. + Включить автоматическую поддержку через Flattr Поддерживать через Flattr эпизоды, прослушанные на %d процентов Поддерживать эпизод через Flattr в начале воспроизведения Поддерживать эпизод через Flattr в конце воспроизведения @@ -265,6 +270,8 @@ OPML файлы позволяют перемещать ваши подкасты из одного менеджера подкастов в другой. Укажите путь к файлу на устройстве + Откройте OPML-файл с помощью внешних приложений: Dropbox, Google Drive или любой файловый менеджер. + Множество приложений умеют открывать OPML-файлы в AntennaPod, например: Google Mail, Dropbox, Google Drive и большинство файловых менеджеров. Начать импорт Импорт OPML Ошибка @@ -273,9 +280,12 @@ Каталог для импорта пуст. Отметить все Снять все отметки + Из файловой системы + С помощью внешнего приложения Экспорт в OPML Экспортируется... Ошибка экспорта + OPML успешно экспортирован. Файл OPML был записан в:\u0020 Установить таймер сна @@ -354,6 +364,7 @@ Загрузить следующую страницу Авторизация + Изменить имя пользователя и пароль для этого подкаста и его выпусков. Импорт подписок из одноцелевых приложений… Поиск в iTunes diff --git a/core/src/main/res/values-sv-rSE/strings.xml b/core/src/main/res/values-sv-rSE/strings.xml index e70ca5d3f..9e8057100 100644 --- a/core/src/main/res/values-sv-rSE/strings.xml +++ b/core/src/main/res/values-sv-rSE/strings.xml @@ -67,10 +67,6 @@ Du kan söka efter podcasts baserat på namn, kategori eller populäritet med tjänsten gpodder.net Bläddra på gpodder.net - Markera alla som lästa - Markera alla episoder som lästa - Bekräfta att du vill markera alla avsnitt som lästa. - Bekräfta att du vill markera alla avsnitt i detta flöde som lästa. Visa information Ta bort podcast Dela hemsidans länk @@ -86,9 +82,6 @@ Strömma Ta bort Ta bort episod - Markera som läst - Markera som oläst - Markerad som läst Lägg till i kön Ta bort från Kön Besök websidan @@ -112,8 +105,6 @@ Okänd värd Autentiseringsproblem Avbryt alla nedladdningar - Nedladdning avbruten - Nedladdningar färdiga Felaktig webbadress IO fel Request fel @@ -246,8 +237,6 @@ Ändra inloggningsinformationen för ditt gpodder.net konto. Uppspelningshastigheter Anpassa de tillgängliga hastigheterna för variabel uppspelningshastighet. - Söklängd - Sök så här många sekunder vid snabbspolning bakåt eller framåt Sätt värdnamn Använd standardvärden Expandera notifieringar diff --git a/core/src/main/res/values-tr/strings.xml b/core/src/main/res/values-tr/strings.xml index e83c9b48e..1af926e30 100644 --- a/core/src/main/res/values-tr/strings.xml +++ b/core/src/main/res/values-tr/strings.xml @@ -67,10 +67,6 @@ gdpodder.net dizininde yeni cep yayınlarını isme, kategoriye veya popülerliğe göre arayabilirsiniz veya iTunes mağazasında arama yapabilirsiniz. gpodder.net\'e gözat - Hepsini okundu olarak işaretle - Tüm bölümler okundu olarak işaretlendi - Lütfen tüm bölümleri okundu olarak işaretlemek istediğinizi onaylayın. - Lütfen bu besleme içindeki tüm bölümleri okundu olarak işaretlemek istediğinizi onaylayın. Bilgiyi göster Cep yayını kaldır Web sayfası bağlantısı paylaş @@ -86,9 +82,6 @@ Akış Kaldır Bölümü kaldır - Okundu olarak işaretle - Okunmadı olarak işaretle - Okundu olarak işaretlendi Kuyruğa Ekle Kuyruktan Kaldır Siteyi Ziyaret Et @@ -112,8 +105,6 @@ Bilinmeyen sunucu Yetkilendirme hatası Bütün indirmeleri iptal et - İndirme iptal edildi - İndirme tamamlandı Bozuk URL G/Ç Hatası İstek hatası @@ -246,8 +237,6 @@ gpodder.net hesabınız için giriş bilgisini değiştirin. Çalma hızları Değişken hızlı ses yürütmesi için kullanılabilir hızları özelleştirin - Arama zamanı - Geri veya ileri sararken bu kadar saniye atla Sunucu ismini ayarla Varsayılan sunucuyu kullan Bildirimi Genişlet diff --git a/core/src/main/res/values-uk-rUA/strings.xml b/core/src/main/res/values-uk-rUA/strings.xml index 20374232a..b6cd8ca98 100644 --- a/core/src/main/res/values-uk-rUA/strings.xml +++ b/core/src/main/res/values-uk-rUA/strings.xml @@ -26,6 +26,7 @@ Показати меню Сховати меню + Настройки навігації Відкрити в браузері Копіювати URL @@ -39,6 +40,7 @@ Скасувати Автор Мова + URL Налаштування Зображення Помилка @@ -67,10 +69,10 @@ В каталозі gpodder.net можливий пошук за назвою, категорією або популярністю. Переглянути gpodder.net - Позначити всі як переглянуті - Позначено всі епізоди як переглянуті - Будь ласка, підтвердіть що ви бажаєте позначити всі епізоди як прочитані. - Будь ласка, підтвердіть що ви бажаєте позначити всі епізоди цього канала як прочитані. + Позначити всі як грані + Позначено всі епізоди як грані + Будь ласка, підтвердіть що ви бажаєте позначити всі епізоди як грані. + Будь ласка, підтвердіть що ви бажаєте позначити всі епізоди цього канала як грані. Інформація Видалити подкаст Поділитися URL сайту @@ -78,6 +80,16 @@ Ви впенені що хочете видаліти канал та всі завантажені епізоди Удаляю канал Оновити канал цілком + Приховати епізоди + Неграні + На паузі + Грані + В черзі + Не в черзі + Завантажені + Не завантажені + Фільтровані + {fa-exclamation-circle} Останнє оновлення було невдалим Завантажити Грати @@ -86,16 +98,20 @@ Прослухати без завантаження Видалити Видалити епізод - Позначити як переглянутий - Позначити як не переглянутий - Позначено як прочитане + Позначити як граний + Позначити як не граний + Позначено як граний Додати до черги + Додано до черги Видалити з черги Відкрити сайт Підтримати за допомогою Flattr Додати до черги Завантажити все Пропустити епізод + Включити автоматичне завантаження + Виключити автозавантаження + Вернути початкову позицію відтворення успішно з помилками @@ -112,8 +128,10 @@ Невідомий host Помилка автентифікації Скасувати всі завантаження - Відмінено завантаження - Завантажили + Завантаження скасоване + Завантаження скасоване\nВимкнуто автоматичне завантаження для цього елемента + Завантаження завершені з помилками + Звіт про завантаження Невірний URL Помилка IO Помилка запиту @@ -129,6 +147,11 @@ Помилка при завантажені файлу:\u0020 Потрібна автентифікація Для доступа до цього ресурса потрібні ім\'я та пароль + Підтвердження мобільних завантажень + Завантаження через мобільний зв\'язок вимкнено в настройках.\n\nУвімкнути тимчасово або тільки додати до черги?\n\nВаш вибір буде запам\'ятовано на 10 хвилин. + Завантаження через мобільний зв\'язок вимкнено в настройках.\n\nУвімкнути тимчасово?\n\nВаш вибір буде запам\'ятовано на 10 хвилин. + Лише додати до черги + Увімкнути тимчасово Помилка! Нічого грати @@ -143,6 +166,8 @@ Грає подкаст AntennaPod - Невідомий медіа ключ: %1$d + Заблокувати чергу + Розблокувати чергу Очистити чергу Скасувати Видалено @@ -200,6 +225,8 @@ Перейти до наступного епізода в черзі коли поточний закінчено Видалити епізод після повного відтворення Автовидалення + Позначити епізоди як грані навіть якщо залишилось менш ніж зазначене число секунд до кінця відтворення + Розумне позначення граних епізодів Відтворення Мережа Частота оновлень @@ -223,6 +250,8 @@ Налаштування автоматичного заохочення авторів через сервіс flattr Вигляд Обрати тему + Змінити настройки навігації + Вибрати елементи для використання у навігації Змінити вигляд AntennaPod Автоматичне завантаження Налаштування автоматичного завантаження епізодів @@ -246,8 +275,8 @@ Змінити інформацію щодо облікового запису gpodder.net Швидкість програвання Налаштування швідкості доступно для змінної швидкості програвання - Час перемотки - Перейти на таку кількість секунд при перемотуванні назад або вперед + Час перемотки вперед + Час перемотки назад Встановити ім\'я хоста Використати хост по замовчанню Розгорнути повідомлення @@ -257,6 +286,7 @@ Android до версії 4.1 не підтримує розширені повідомлення. Додавати нові епізоди до початку черги. Додавати в початок черги. + Вимкнено Включити автоматичне заохочення авторів через сервіс flattr Заохотити автора через Flattr щойно %d відсотків епізода було відтворено @@ -340,7 +370,9 @@ В папці щось є. Всі завантаження зберігаються в цю папку. Все рівно продовжувати? Обрати папку по замовчанню Призупиняти програвання замість зниження гучності коли інша програма хоче програти звук - Пауза для перевивання + Пауза в разі переривання + Відновити відтворення після закінчення дзвінка + Відновити після дзвінка Підписатися Підписано diff --git a/core/src/main/res/values-zh-rCN/strings.xml b/core/src/main/res/values-zh-rCN/strings.xml index 0a2b9355e..20caf6c67 100644 --- a/core/src/main/res/values-zh-rCN/strings.xml +++ b/core/src/main/res/values-zh-rCN/strings.xml @@ -31,6 +31,7 @@ 复制 URL 分享 URL 复制 URL 到剪贴板. + 去往该位置 清空历史 @@ -57,29 +58,30 @@ 关闭 重试 包含到自动下载 + \u0020 并行下载 订阅 URL + www.example.com/feed 添加播客 URL + 从目录中寻找播客 您可以在 gpodder.net 通过名称、类别或热门来搜索新播客 浏览 gpodder.net - 全部标识已读 - 将所有曲目标记为已读 查看信息 删除播客 分享网站链接 分享订阅链接 确认要删除这些订阅吗? 该订阅所有已经下载的曲目将一并删除. 删除订阅 + 刷新全部订阅 下载 播放 暂停 + 停止 流媒体 删除 移除曲目 - 标记已读 - 标记未读 添加到播放列表 从播放列表中删除 访问网站 @@ -103,8 +105,6 @@ 未知主机 认证错误 取消所有下载 - 已取消下载 - 下载完成 畸形 URL IO 错误 请求出错 @@ -132,12 +132,20 @@ 00:00:00 缓冲中 播客播放中 + AntennaPod - 未知媒体密钥: %1$d 清空播放列表 撤消 已删除项 移到顶端 移到下部 + 排序 + 按字母 + 按日期 + 按时长 + 升序 + 降序 + 请确认您要清除队列中的全部曲目 Flattr 登录 按下面的按钮开始身份验证过程. 将在浏览器中打开 Flattr 登录界面并要求给予 AntennaPod 访问 Flattr 的权限. 权限许可后, 将自动回到这个界面. @@ -145,16 +153,29 @@ 返回主页 验证成功! 现在可以使用应用内 Flattr 相关功能了. 没有找到 Flattr 验证令牌信息 - 您的 flattr 账户似乎并没有连接到 AntennaPod. You can either connect your account to AntennaPod to flattr things within the app or you can visit the website of the thing to flattr it there. + 您的 flattr 账户似乎并没有连接到 AntennaPod,点这里验证。 + 您的 flattr 账户似乎并没有连接到 AntennaPod. 您可以关联您的账户到AntennaPod以便在应用内flattr条目,或者您可以自己访问条目的网站完成flattr 验证 被禁止 AntennaPod 没有权限执行本动作. 原因可能是: AntennaPod 对您账户的访问令牌被撤销. 你可以重新\"验证\"或访问该网站来授权. 撤销访问 您已经成功撤销 AntennaPod 对账户令牌的访问. 为了完成这个过程, 您必须到 Flattr 网站 \"账户设置->已批准应用\" 列表内删除本应用. + 成功Flattr一个条目 + 成功Flattr%d个条目 + Flattr%s成功. + Flattr失败%d个条目 + %sFlattr失败. + 稍后将Flattr该条目 + 正在Flattr%s + AntennaPod正在Flattr + AntennaPod已经Flattr + AntennaPod Flattr失败 + 查询Flattr结果状态 插件下载 插件没有安装 + 要使播放速度可变,必须安装第三方库。\n\n点击 \'插件下载\' 从 \'Play 商店\' 下载免费插件\n\n使用这些插件中碰到的任何问题请报告给插件作者,与 AntennaPod 无关。 播放速度 列表为空. @@ -168,7 +189,7 @@ 耳机断开时暂停播放 当耳机重新连接时恢复播放 播放完成跳转到播放列表下一项 - 当播放完成后删除单集 + 当播放完成后删除曲目 自动删除 播放 网络 @@ -190,6 +211,8 @@ 撤销访问 撤销访问本应用对您 Flattr 账户的访问权限. + 自动Flattr + 设置自动 flattring 界面 主题选择 改变 AntennaPod 外观 @@ -197,6 +220,9 @@ 配置自动下载的曲目 打开 Wi-Fi 过滤器 只允许在 Wi-Fi 网络下自动下载 + 未充电时下载 + 未充电时允许自动下载 + 并行下载 曲目缓存 浅色 暗色 @@ -212,16 +238,20 @@ 改变 gpodder.net 账户登录信息. 播放速度 自定义音频播放速度 - 定位时间 - 当倒退或快速回放时以这些秒为单位 设置主机名 使用默认主机 扩展通知 总是扩展通知以显示播放按钮 保持播放控制 在暂停时保持通知和锁屏界面的控制。 - Android 版本 4.1 之前不支持扩展通知 + Android 4.1 之前不支持扩展通知。 + 添加新曲目到队列之前。 + 新曲目从播放列表的前排插入 + 启用自动 flattring + 当播放到百分之%d时Flattr改曲目 + 当播放开始时Flattr改曲目 + 当播放结束时Flattr改曲目 搜索订阅或者曲目 笔记中查找 @@ -231,6 +261,9 @@ 标题中查找 OPML 文件可以方便的从别的播客转移数据过来。 + 从本地文件系统选择一个特定文件地址。 + 使用外部应用程序,例如 Dropbox,Google Drive 或您喜爱的文件管理器打开 OPML 文件。 + AntennaPod 一样,许多应用例如Google Mail,Dropbox,Google Drive和大多数文件管理器均可 打开 OPML文件。 开始导入 OPML 导入 错误! @@ -239,6 +272,8 @@ 导入目录为空. 全选 取消所有选择 + 来自本地文件系统 + 使用外部应用 OPML 导出 导出中... 导出出错 @@ -262,6 +297,7 @@ 登录 欢迎进入 gpodder.net 登录流程. 首先, 输入请你的登录信息: 登录 + 如果您目前没有账户,可以从这里创建:\nhttps://gpodder.net/register/ 用户名 密码 设备选择 @@ -317,9 +353,11 @@ 新曲目数 已收听曲目数 拖动以变更本项目的位置 + 载入下一页 验证 给本播客及曲目变更用户名及密码 正在从选定的应用中导入订阅... + 搜索 iTunes -- cgit v1.2.3 From 72067b64fca2c303e397d6475d9733ad07374ed2 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Mon, 1 Jun 2015 18:04:32 -0400 Subject: updated strings, bumped build number --- core/src/main/res/values-cs-rCZ/strings.xml | 43 ++++++++++++++++++++++ core/src/main/res/values-de/strings.xml | 47 ++++++++++++++++++++++-- core/src/main/res/values-es/strings.xml | 43 ++++++++++++++++++++++ core/src/main/res/values-ko/strings.xml | 43 ++++++++++++++++++++++ core/src/main/res/values-pt/strings.xml | 9 +++-- core/src/main/res/values-sv-rSE/strings.xml | 55 +++++++++++++++++++++++++---- 6 files changed, 230 insertions(+), 10 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values-cs-rCZ/strings.xml b/core/src/main/res/values-cs-rCZ/strings.xml index e110c3adc..90304a404 100644 --- a/core/src/main/res/values-cs-rCZ/strings.xml +++ b/core/src/main/res/values-cs-rCZ/strings.xml @@ -26,6 +26,7 @@ Otevřít menu Zavřít menu + Nastavení panelu Otevřít v prohlížeči Kopírovat URL @@ -39,6 +40,7 @@ Zrušit Autor Jazyk + URL Nastavení Obrázek Chyba @@ -67,6 +69,10 @@ Můžete vyhledávat nové podcasty podle jména, kategorie nebo popularity v seznamu gpodder.net. Prohledávat gpodder.net + Označit vše jako poslechnuté + Všechny epizody označeny jako poslechnuté + Prosím potvrďte, že chcete označit všechny vybrané epizody jako poslechnuté. + Prosím potvrďte, že chcete označit všechny epizody z tohoto zdroje jako poslechnuté. Informace o zdroji Odstranit podcast Sdílet odkaz @@ -74,6 +80,16 @@ Prosím potvrďte, že chcete smazat tento kanál včetně všech stažených epizod. Odstranit kanál Obnovit kompletní kanál + Skrýt epizody + Neposlechnuté + Pozastavené + Poslechnuté + Ve frontě + Mimo frontu + Stažené + Nestažené + Filtrované + {fa-exclamation-circle} Poslední aktualizace selhala Stáhnout Přehrát @@ -82,13 +98,20 @@ Vysílat Odstranit Odstranit epizodu + Označit jako poslechnuté + Označit jako neposlechnuté + Označeno jako poslechnuté Přidat do fronty + Přidáno do fronty Odebrat z fronty Navštívit stránku Flattrovat Vše do fronty Stáhnout vše Přeskočit epizodu + Aktivovat automatické stahování + Deaktivovat automatické stahování + Vymazat pozici přehrávání úspěšné selhalo @@ -105,6 +128,10 @@ Neznámý host Chyba přihlášení Zrušit všechna stahování + Stahování zrušeno + Stahování zrušeno\nVypnuto automatické stahování této položky + Stahování dokončeno s chybou + Report stahování Chybné URL IO chyba Chyba požadavku @@ -120,6 +147,11 @@ Nastala chyba při pokusu o stažení souboru:\u0020 Vyžadováno ověření Zdroj který jste vybrali vyžaduje zadání uživatelského jména a hesla + Potvrdit mobilní stahování + Stahování dat přes mobilní připojení je v nastavení vypnuto.\n\nDočasně povolit nebo pouze přidat do fronty?\n\nTato volba bude platná po dalších 10 minut. + Stahování dat přes mobilní připojení je v nastavení vypnuto.\n\nDočasně povolit?\n\nTato volba bude platná po dalších 10 minut. + Pouze přidat do fronty + Dočasně povolit Chyba! Žádné probíhající přehrávání @@ -134,6 +166,8 @@ Přehrávaný podcast AntennaPod - Neznámý klíč médií: %1$d + Zamknout frontu + Odemknout frontu Vyprázdnit frontu Zpět Položka odebrána @@ -191,6 +225,8 @@ Po přehrání položky z fronty přejít automaticky na další Smazat díl po jeho přehrání Automatické mazání + Označit epizody jako poslechnuté i pokud ještě zbývá určitý počet sekund přehrávání do jejich konce + Chytré označování jako poslechnuté Přehrávání Síť Interval aktualizace zdrojů @@ -214,6 +250,8 @@ Nastavit automatické flattrování Uživatelské rozhraní Vybrat motiv + Změnit navigační panel + Upravit zobrazení položek v navigačním panelu. Změnit vzhled AntennaPod. Automatické stahování Nastavení automatického stahování epizod. @@ -237,6 +275,8 @@ Změní přihlašovací údaje k vašemu gpodder.net účtu. Rychlosti přehrávání Přizpůsobení rychlosti je dostupné pro přehrávání zvuku různými rychlostmi + Čas rychlého posunu + Čas přetočení Nastavit hostname Použít přednastaveného hosta Rozšířené upozornění @@ -246,6 +286,7 @@ Verze Androidu nižší než 4.1 nepodporují rozšířená upozornění. Přidávat nové epizody na začátek fronty. Přidat na začátek. + Vypnuto Povolit automatické flattrování Flattrovat díl jakmile bude odehráno %d procent @@ -330,6 +371,8 @@ Vybrat hlavní adresář Místo snížení hlasitosti pozastavit přehrávání v případě, že jiná aplikace přehrává zvuk. Automatické pozastavení přehrávání + Pokračovat v přehrávání po ukončení telefonního hovoru + Pokračovat po telefonátu Odebírat Odebíráno diff --git a/core/src/main/res/values-de/strings.xml b/core/src/main/res/values-de/strings.xml index 9383559b0..93e52acb6 100644 --- a/core/src/main/res/values-de/strings.xml +++ b/core/src/main/res/values-de/strings.xml @@ -26,6 +26,7 @@ Menü öffnen Menü schließen + Seitenleisten-Einstellungen Im Browser öffnen URL kopieren @@ -39,6 +40,7 @@ Abbrechen Autor Sprache + URL Einstellungen Bild Fehler @@ -64,9 +66,13 @@ URL des Feeds oder der Webseite Podcast per URL hinzufügen Podcast in Verzeichnis finden - Bei gpodder.net kannst du neue Podcasts nach Name, Kategorie oder Popularität suchen. + Bei gpodder.net kannst du neue Podcasts nach Name, Kategorie oder Popularität suchen. Oder suche bei iTunes. gpodder.net durchsuchen + Alle als gespielt markieren + Alle Episoden als gespielt markieren + Bitte bestätige, dass alle Episoden als gespielt markiert werden sollen. + Bitte bestätige, dass alle Episoden in diesem Feed als gespielt markiert werden sollen. Informationen anzeigen Podcast entfernen Webseiten-Link teilen @@ -74,6 +80,16 @@ Bitte bestätige, dass du diesen Feed und ALLE heruntergeladenen Episoden dieses Feeds entfernen möchtest. Entferne Feed Kompletten Feed aktualisieren + Episoden verbergen + Ungespielt + Pausiert + Gespielt + In Abspielliste + Nicht in Abspielliste + Heruntergeladen + Nicht heruntergeladen + Gefiltert + {fa-exclamation-circle} Aktualisierung fehlgeschlagen Herunterladen Abspielen @@ -82,13 +98,20 @@ Streamen Entfernen Episode entfernen + Als gespielt markieren + Als ungespielt markieren + Als gespielt markiert Zur Abspielliste hinzufügen + Zur Abspielliste hinzugefügt Aus der Abspielliste entfernen Webseite besuchen Flattrn Alle zur Abspielliste hinzufügen Alle herunterladen Episode überspringen + Automatischen Download aktivieren + Automatischen Download deaktivieren + Wiedergabe-Position zurücksetzen erfolgreich fehlgeschlagen @@ -105,6 +128,10 @@ Unbekannter Host Authentifizierungsfehler Alle Downloads abbrechen + Download abgebrochen + Download abgebrochen\nAutomatischen Download für diese Episode deaktiviert + Downloads endeten mit Fehler(n) + Download-Bericht Fehler in URL E/A Error Anfragefehler @@ -120,6 +147,11 @@ Beim Herunterladen der Datei ist ein Fehler aufgetreten:\u0020 Authentifizierung erforderlich Die angeforderte Quelle erfordert einen Benutzernamen und ein Passwort + Mobilen Download bestätigen + Das Herunterladen über die mobile Datenverbindung ist in den Einstellungen deaktiviert.\n\nVorübergehend erlauben oder nur zur Abspielliste hinzufügen?\n\nDeine Entscheidung wird für 10 Minuten gespeichert. + Das Herunterladen über die mobile Datenverbindung ist in den Einstellungen deaktiviert.\n\nVorübergehend erlauben?\n\nDeine Entscheidung wird für 10 Minuten gespeichert. + Zur Abspielliste hinzufügen + Vorübergehend erlauben Fehler! Keine Medienwiedergabe @@ -134,6 +166,8 @@ Spiele Podcast ab AntennaPod - Unbekannte Medientaste: %1$d + Abspielliste sperren + Abspielliste entsperren Abspielliste leeren Rückgängig Element entfernt @@ -191,6 +225,8 @@ Springe zur nächsten Episode, wenn die vorherige Episode endet Episode löschen, wenn die Wiedergabe endet Automatisches Löschen + Episoden werden als gespielt markiert, wenn weniger als eine bestimmte Anzahl Sekunden Restspielzeit übrig sind + Schlaues als gespielt markieren Wiedergabe Netzwerk Aktualisierungsintervall @@ -214,6 +250,8 @@ Automatisches Flattrn konfigurieren Benutzeroberfläche Theme auswählen + Seitenleiste ändern + Ändere, welche Listen in der Seitenleiste erscheinen Ändere das Aussehen von AntennaPod. Automatisches Herunterladen Konfiguriere das automatische Herunterladen von Episoden. @@ -237,6 +275,8 @@ Ändere die Anmeldeinformationen deines gpodder.net Profils Wiedergabegeschwindigkeiten Lege die verfügbaren Werte für die Veränderung der Wiedergabeschwindigkeit fest + Vorspulzeit + Rückspulzeit Hostname ändern Standard-Host verwenden Benachrichtigung erweitern @@ -246,6 +286,7 @@ Android-Versionen vor 4.1 unterstützen keine erweiterten Benachrichtigungen. Fügen Sie neue Folgen auf den Anfang der Warteschlange. Vorne in Abspielliste einreihen + Deaktiviert Automatisches Flattrn aktivieren Flattr eine Episode, sobald %d Prozent gespielt worden sind @@ -330,6 +371,8 @@ Standardordner auswählen Pausiere die Wiedergabe statt die Lautstärke zu reduzieren, wenn eine andere Anwendung Töne abspielt Bei Unterbrechungen pausieren + Wiedergabe fortsetzen, wenn Anruf beendet ist + Nach Anruf fortsetzen Abonnieren Abonniert @@ -358,5 +401,5 @@ Ändere den Benutzernamen und das Passwort für diesen Podcast und dessen Episoden. Importiere Abonnements aus Single-Purpose Apps - iTunes suchen + iTunes durchsuchen diff --git a/core/src/main/res/values-es/strings.xml b/core/src/main/res/values-es/strings.xml index 5972bcdf2..d5255a589 100644 --- a/core/src/main/res/values-es/strings.xml +++ b/core/src/main/res/values-es/strings.xml @@ -26,6 +26,7 @@ Abrir menú Cerrar menú + Preferencias del cajón Abrir en el navegador Copiar URL @@ -39,6 +40,7 @@ Cancelar Autor Idioma + URL Ajustes Imagen Error @@ -67,6 +69,10 @@ Es posible buscar podcasts nuevos por nombre, categoría o popularidad en el directorio de gpodder.net. Explorar gpodder.net + Marcar todos como escuchado + Se marcaron todos los episodios como escuchados + Por favor, confirme que desea marcar todos los episodios como escuchados. + Por favor, confirme que desea marcar todos los episodios de este feed como escuchados. Información del programa Eliminar podcast Compartir el enlace de la web @@ -74,6 +80,16 @@ Confirme que quiere eliminar este canal y TODOS los episodios descargados del mismo. Quitando el canal Actualizar el canal completo + Ocultar episodios + No escuchados + Pausados + Escuchados + En cola + No en cola + Descargados + No descargados + Filtrados + {fa-exclamation-circle} Error en última actualización Descargar Reproducir @@ -82,13 +98,20 @@ Transmitir Quitar Quitar episodio + Marcar como escuchado + Marcar como no escuchado + Marcado como escuchado Añadir a la cola + Añadido a la cola Quitar de la cola Visitar el sitio web Añadir a Flattr Ponerlos todos en cola Descargarlos todos Omitir episodio + Activar descarga automática + Desactivar descarga automática + Resetear posición de reproducción exitoso fallido @@ -105,6 +128,10 @@ Host desconocido Error de autenticación Cancelar todas las descargas + Descarga cancelada + Cancelada descarga\nDeshabilitada Descarga Automática para este ítem + Descargas completadas con error(es) + Informe de descarga URL con formato incorrecto Error de E/S Error de solicitud @@ -120,6 +147,11 @@ Ha ocurrido un error al intentar descargar el archivo:\u0020 Se necesita autenticación Para acceder al recurso solicitado debe proporcionar un usuario y contraseña + Confirmar descarga por red móvil + Las descargas sobre la red móvil están deshabilitadas en ajustes.\n\nHabilitar temporalmente o sólo agregar a la cola?\n\nEsta elección será recordada por 10 minutos. + Las descargas sobre la red móvil están deshabilitadas en ajustes.\n\nHabilitar temporalmente?\n\nEsta elección será recordada por 10 minutos. + Sólo agregar a la cola + Habilitar temporalmente Error No hay medios en reproducción @@ -134,6 +166,8 @@ Reproduciendo el podcast AntennaPod - Tecla multimedia desconocida: %1$d + Bloquear cola + Desbloquear cola Vaciar la cola Deshacer Artículo eliminado @@ -191,6 +225,8 @@ Saltar al siguiente elemento de la cola al acabar la reproducción Borrar episodio cuando finalice la reproducción Eliminar automáticamente + Marcar episodios como escuchados incluso si todavía quedan unos segundos por escuchar + Marcar como escuchado inteligente Reproducción Red Intervalo de actualización @@ -214,6 +250,8 @@ Configurar flattr automático Interfaz de usuario Elegir un tema + Cambiar el cajón de navegación + Cambiar los ítems que aparecen en el cajón de navegación Cambiar la apariencia de AntennaPod. Descarga automática Configurar la descarga automática de episodios. @@ -237,6 +275,8 @@ Modificar datos de inicio de sesión en gpodder.net. Velocidades de reproducción Personalice las velocidades disponibles para la reproducción de audio a velocidad variable + Intervalo de avance + Intervalo de retroceso Definir nombre de equipo Usar nombre de equipo por defecto Expandir Notificación @@ -246,6 +286,7 @@ Las versiones de Android anteriores a la 4.1 no soportan notificaciones expandidas Agregar nuevos episodios al principio de la cola. Poner al principio de la cola. + Deshabilitado Habilitar Flattr automático Hacer Flattr del episodio en cuanto se haya reproducido el %d por ciento @@ -330,6 +371,8 @@ Elegir carpeta predeterminada Pausar la reproducción en lugar de bajar el volumen cuando otra aplicación reproduzca sonidos Pausar durante las interrupciones + Reanudar reproducción tras una llamada + Reanudar tras una llamada Suscribirse Suscrito diff --git a/core/src/main/res/values-ko/strings.xml b/core/src/main/res/values-ko/strings.xml index b330d1ecb..148010050 100644 --- a/core/src/main/res/values-ko/strings.xml +++ b/core/src/main/res/values-ko/strings.xml @@ -26,6 +26,7 @@ 메뉴 열기 메뉴 닫기 + 드로어 기본 설정 브라우저에서 열기 URL 복사 @@ -39,6 +40,7 @@ 취소 저자 언어 + URL 설정 그림 오류 @@ -67,6 +69,10 @@ gpodder.net 디렉터리에서 이름, 분류, 인기에 따라 새 팟캐스트를 검색할 수 있고, iTunes 스토어에서 검색할 수도 있습니다. gpodder.net 둘러보기 + 모두 재생했다고 표시 + 모든 에피소드를 재생했다고 표시했습니다 + 모든 에피소드를 재생했다고 표시할지 확인하십시오. + 이 피드에 들어 있는 모든 에피소드를 재생했다고 표시할지 확인하십시오. 정보 표시 팟캐스트 제거 홈페이지 링크 공유 @@ -74,6 +80,16 @@ 이 피드와 이 피드에서 다운로드한 모든 에피소드를 삭제하시려면 확인을 누르십시오. 피드 삭제하는 중 전체 피드 새로고침 + 에피소드 감추기 + 재생 안 함 + 일시 중지 + 재생함 + 대기열 추가 + 대기열 추가 안 함 + 다운로드함 + 다운로드 안 함 + 필터링함 + {fa-exclamation-circle} 최근 새로 고침 실패 다운로드 재생 @@ -82,13 +98,20 @@ 스트리밍 제거 에피소드 제거 + 재생했다고 표시 + 재생하지 않음으로 표시 + 재생했다고 표시함 대기열에 추가 + 대기열에 추가함 대기열에서 제거 홈페이지 보기 Flattr하기 모두 대기열에 추가 모두 다운로드 에피소드 건너뛰기 + 자동 다운로드 활성화 + 자동 다운로드 해제 + 재생 위치 초기화 성공 실패 @@ -105,6 +128,10 @@ 알 수 없는 호스트 인증 오류 모든 다운로드 취소 + 다운로드 취소함 + 다운로드 취소함\n이 항목에 자동 다운로드를 해제합니다 + 다운로드 마침 (오류 있음) + 다운로드 보고서 URL 형식 틀림 입출력 오류 요청 오류 @@ -120,6 +147,11 @@ 파일을 다운로드하는 중 오류가 발생했습니다:\u0020 인증이 필요합니다 요청한 자원은 사용자 이름과 암호가 필요합니다 + 휴대전화망 다운로드 확인 + 휴대전화망 데이터 연결을 통한 다운로드는 설정에서 막혀 있습니다.\n\n임시로 다운로드를 허용할 수도 있고, 대기열에 추가만 할 수도 있습니다.\n\n여기서 선택한 사항은 10분 동안 유지됩니다. + 휴대전화망 데이터 연결을 통한 다운로드는 설정에서 막혀 있습니다.\n\n임시로 다운로드를 열 수 있습니다\n\n여기서 선택한 사항은 10분 동안 유지됩니다. + 대기열에 추가만 + 임시로 허용 오류! 재생 중인 미디어 없음 @@ -134,6 +166,8 @@ 팟캐스트 재생 중 안테나팟 - 알 수 없는 미디어 키: %1$d + 대기열 잠그기 + 대기열 잠금 해제 대기열 지우기 실행 취소 항목을 제거했습니다 @@ -191,6 +225,8 @@ 재생을 마쳤을 때 다음 대기열로 이동 재생이 끝나면 에피소드 삭제 자동 삭제 + 재생이 일정한 시간보다 (초 단위) 적게 남으면 에피소드를 재생한 것으로 표시 + 똑똑하게 재생한 것으로 표시 재생 네트워크 업데이트 주기 @@ -214,6 +250,8 @@ 자동 flattr 설정 사용자 인터페이스 테마 선택 + 네비게이션 드로어 바꾸기 + 네비게이션 드로어에 어떤 항목을 표시할지 바꿉니다. 안테나팟의 겉모양을 바꿉니다. 자동 다운로드 에피소드 자동 다운로드를 설정합니다. @@ -237,6 +275,8 @@ gpodder.net 계정의 로그인 정보를 바꿉니다. 재생 속도 여러가지 오디오 재생 속도 직접 설정 + 빠르게 감기 시간 + 뒤로 감기 시간 호스트 이름 설정 기본 호스트 사용 알림 확장 @@ -246,6 +286,7 @@ 안드로이드 4.1 전 버전에서는 알림 확장을 지원하지 않습니다. 새 에피소드를 대기열 앞에 추가합니다. 대기열 앞에 추가 + 사용 안 함 자동 flattr 사용 %d 퍼센트를 재생하면 에피소드에 flattr합니다 @@ -330,6 +371,8 @@ 기본 폴더 선택 다른 앱이 소리를 낼 때 볼륨을 줄이지 않고 재생을 일시 중지 끼어들면 일시 중지 + 전화 통화가 끝난 후에 재생 다시 시작 + 통화 후에 다시 시작 구독 구독함 diff --git a/core/src/main/res/values-pt/strings.xml b/core/src/main/res/values-pt/strings.xml index 565f0f25e..964124b90 100644 --- a/core/src/main/res/values-pt/strings.xml +++ b/core/src/main/res/values-pt/strings.xml @@ -147,6 +147,9 @@ Ocorreu um erro ao transferir o ficheiro:\u0020 Requer autenticação O recurso solicitado requer um utilizador e uma senha + Confirmação de transferência + A transferência através de dados móveis está desativada nas definições.\n\nAtivar temporariamente ou apenas adicionar à fila?\n\nA sua decisão será memorizada durante 10 minutos. + A transferência através de dados móveis está desativada nas definições.\n\nAtivar temporariamente?\n\nA sua decisão será memorizada durante 10 minutos. Apenas adicionados à fila Ativar temporariamente @@ -222,6 +225,8 @@ Ir para a faixa seguinte ao terminar a reprodução Eliminar episódio ao terminar a reprodução Eliminação automática + Marcar episódios como reproduzidos mesmo que restem alguns segundos de reprodução + Marcar como reproduzido (inteligente) Reprodução Rede Intervalo entre atualizações @@ -246,7 +251,7 @@ Interface Tema Alterar itens da gaveta - Alterar os itens a aparecer na gaveta de navegação + Alterar os itens que aparecem na gaveta de navegação Mudar o aspeto do AntennaPod Transferência automática Configure a transferência automática dos episódios @@ -281,7 +286,7 @@ As versões Android anteriores à 4.1 não possuem suporte à expansão de notificações Colocar novos episódios no inicio da fila Novos episódios no inicio - Desativado + Desativada Ativar flattr automático Flattr de episódios ao atingir %d porcento de reprodução diff --git a/core/src/main/res/values-sv-rSE/strings.xml b/core/src/main/res/values-sv-rSE/strings.xml index 9e8057100..68d6f94f2 100644 --- a/core/src/main/res/values-sv-rSE/strings.xml +++ b/core/src/main/res/values-sv-rSE/strings.xml @@ -5,7 +5,7 @@ Flöden Lägg till podcast PODCASTS - AVSNITT + EPISODER Nya episoder Alla episoder Ny @@ -26,6 +26,7 @@ Öppna meny Stäng meny + Lådinställningar Öppna i webbläsare Kopiera URL @@ -39,6 +40,7 @@ Avbryt Skapare Språk + URL Inställningar Bild Fel @@ -48,7 +50,7 @@ Kapitel Shownotes Beskrivning - Senaste avsnittet:\u0020 + Senaste episoden:\u0020 \u0020episoder Längd:\u0020 Storlek:\u0020 @@ -67,6 +69,10 @@ Du kan söka efter podcasts baserat på namn, kategori eller populäritet med tjänsten gpodder.net Bläddra på gpodder.net + Markera alla som spelade + Markera alla episoder som spelade + Bekräfta att du verkligen vill markera alla episoder som spelade. + Bekräfta att du verkligen vill markera alla episoder i detta flöde som spelade. Visa information Ta bort podcast Dela hemsidans länk @@ -74,6 +80,16 @@ Bekräfta att du vill ta bort denna feed och ALLA avsnitt av denna feed som du har hämtat. Tar bort flöde Uppdatera hela flödet + Dölj episoder + Ospelade + Pausad + Spelad + Köad + Inte köad + Nedladdad + Inte nedladdad + Filtrerad + {fa-exclamation-circle} Senaste uppdateringen misslyckades Ladda ned Spela @@ -82,13 +98,20 @@ Strömma Ta bort Ta bort episod + Markera som spelad + Markera som ospelad + Markera som spelad Lägg till i kön + Lägg till i Kö Ta bort från Kön Besök websidan Flattra det här Lägg till alla i kön Ladda ner alla Hoppa över episod + Aktivera automatisk nedladdning + Avaktivera automatisk nedladdning + Nollställ uppspelningsposition lyckades misslyckades @@ -105,6 +128,10 @@ Okänd värd Autentiseringsproblem Avbryt alla nedladdningar + Nedladdning avbruten + Nedladdning avbruten\nStängde av Automatisk nedladdning för denna sak + Nedladdningar avslutades med fel + Nedladdningsrapport Felaktig webbadress IO fel Request fel @@ -120,6 +147,11 @@ Ett fel uppstod vid försöket att ladda ner filen:\u0020 Autentisering krävs Resursen du begärde kräver ett användarnamn och ett lösenord + Bekräfta mobil nedladdning + Nedladdning över mobil dataanslutning är avaktiverat i inställningarna.\n\nAktivera tillfälligt eller bara lägg till i kön?\n\nDitt val gäller i 10 minuter. + Nedladdning över mobil dataanslutning är avstängt i inställningarna.\n\nAktivera tillfälligt?\n\nDitt val gäller i 10 minuter. + Lägg bara till i kön + Aktivera tillfälligt Fel! Inget media spelar @@ -134,6 +166,8 @@ Spelar podcast AntannaPod - Okänd mediaknapp: %1$d + Lås kön + Lås upp kön Rensa kön Ångra Föremålet avlägsnades @@ -145,7 +179,7 @@ Längd Stigande Fallande - Bekräfta att du vill rensa kön från ALLA avsnitt. + Bekräfta att du vill rensa kön från ALLA episoder. Flattr inloggning 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. @@ -191,6 +225,8 @@ Hoppa till nästa i kön när uppspelningen är klar Ta bort episoden när uppspelningen är klar Automatisk borttagning + Markera episoder som spelade även om mindre än ett visst antal sekunder är kvar + Smart markering av uppspelat innehåll Uppspelning Nätverk Uppdateringsintervall @@ -214,6 +250,8 @@ Konfigurerar automatisk Flattring Användargränssnitt Välj tema + Ändra navigationslådan + Ändra vilka saker som visas i navigationslådan. Ändra utseendet på AntennaPod. Automatisk nedladdning Konfigurera automatisk nedladdning av episoder. @@ -222,7 +260,7 @@ Nedladdning vid batteridrift Tillåt automatisk nedladdning när batteriet inte laddas Parallella nedladdningar - Avsnittscache + Episodcache Ljust Mörkt Obegränsat @@ -237,6 +275,8 @@ Ändra inloggningsinformationen för ditt gpodder.net konto. Uppspelningshastigheter Anpassa de tillgängliga hastigheterna för variabel uppspelningshastighet. + Spola framåt + Spola bakåt Sätt värdnamn Använd standardvärden Expandera notifieringar @@ -244,15 +284,16 @@ Bestående uppspelningskontroller Behåll notifiering och kontroller på låsskärmen när uppspelningen pausas. Androidversioner före 4.1 har inte stöd för expanderade notifieringar. - Lägg till avsnitt först i kön. + Lägg till episoder först i kön. Köa först. + Avaktiverad Aktivera automatisk Flattring Flattra episoden så snart %d procent har spelats Flattra episoden när den startas Flattra episoden när den spelats klart - Sök efter flöden eller avsnitt + Sök efter flöden eller episoder Hittad i shownotes Hittad i kapitel Inga resultat hittades @@ -330,6 +371,8 @@ Välj standardmapp Pausa uppspelning istället för att sänka volymen när en annan app vill spela ljud Pausa för avbrott + Återuppta uppspelning när ett telefonsamtal avslutas + Återuppta efter samtal Prenumerera Prenumererar -- cgit v1.2.3 From bb3f7255a97dab4fe9f24141bd63beed2d2341dc Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Tue, 2 Jun 2015 16:20:45 +0200 Subject: Fix typo. --- core/src/main/res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 5150f9bd8..3cedfb8e5 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -161,8 +161,8 @@ Authentication required The resource you requested requires a username and a password Confirm Mobile Download - Downloading over mobile data connection is disabled in the settings.\n\nYou can choose to either only add the episode to the queue or you can allow downloading temporarily.\n\nYour choice will be remember for 10 minutes. - Downloading over mobile data connection is disabled in the settings.\n\nDo you want to allow downloading temporarily?\n\nYour choice will be remember for 10 minutes. + Downloading over mobile data connection is disabled in the settings.\n\nYou can choose to either only add the episode to the queue or you can allow downloading temporarily.\n\nYour choice will be remembered for 10 minutes. + Downloading over mobile data connection is disabled in the settings.\n\nDo you want to allow downloading temporarily?\n\nYour choice will be remembered for 10 minutes. Enqueue Allow temporarily -- cgit v1.2.3 From 451323dfcd6ad2599997b59fbb3cbf5823f80ddd Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 2 Jun 2015 19:33:13 -0400 Subject: restored translations that got messed up with transifex pull --- core/src/main/res/values-az/strings.xml | 5 +++++ core/src/main/res/values-ca/strings.xml | 8 ++++++++ core/src/main/res/values-da/strings.xml | 8 ++++++++ core/src/main/res/values-es-rES/strings.xml | 5 +++++ core/src/main/res/values-hi-rIN/strings.xml | 5 +++++ core/src/main/res/values-iw-rIL/strings.xml | 11 +++++++++++ core/src/main/res/values-nl/strings.xml | 5 +++++ core/src/main/res/values-pl-rPL/strings.xml | 8 ++++++++ core/src/main/res/values-pt-rBR/strings.xml | 5 +++++ core/src/main/res/values-ro-rRO/strings.xml | 5 +++++ core/src/main/res/values-tr/strings.xml | 11 +++++++++++ 11 files changed, 76 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/res/values-az/strings.xml b/core/src/main/res/values-az/strings.xml index 8c56cc671..b52ecf4a4 100644 --- a/core/src/main/res/values-az/strings.xml +++ b/core/src/main/res/values-az/strings.xml @@ -43,6 +43,7 @@ Kanalın URLı + Hamısını oxunmuş kimi işarələ Məlumatı göstər Web-səhifəyi paylaş Kanalı paylaş @@ -53,6 +54,8 @@ Pauza İnternetən yayimla Sil + Oxumuş kimi işarələ + Oxunmamış kimi işarələ Növbəyə əlavə et Növbədən sil Web-səhifəsini aç @@ -73,6 +76,8 @@ Əlaqə xətasi Naməlum xost Yükləmələrin hamısını ləğv et + Yükləmə ləğv olundu + Yükləmə başa çatdı Yanlış URL IO xətasi Tələbin xətası diff --git a/core/src/main/res/values-ca/strings.xml b/core/src/main/res/values-ca/strings.xml index b03ae3b6f..be7a73e6d 100644 --- a/core/src/main/res/values-ca/strings.xml +++ b/core/src/main/res/values-ca/strings.xml @@ -66,6 +66,8 @@ Podeu cercar nous podcasts al directori de gpodder.net mitjançant el seu nom, categoria o popularitat. Navega gpodder.net + Marca-ho tot com a llegit + S\'han marcat tots els episodis com a llegits Mostra informació Esborra podcast Comparteix l\'enllaç de la plana @@ -81,6 +83,8 @@ Reprodueix sense baixar Suprimeix Esborra episodi + Marca com a llegit + Marca com a pendent Afegeix a la cua Suprimeix de la cua Visita el lloc web @@ -104,6 +108,8 @@ Amfitrió desconegut Error d\'autenticació Cancel·la totes les baixades + S\'ha cancel·lat la baixada + Baixades completades URL mal formatada Error d\'E/S Error de petició @@ -234,6 +240,8 @@ Canvia les dades d\'inici de sessió del vostre compte de gpodder.net Velocitats de reproducció Personalitzeu les velocitats disponibles per a una velocitat de reproducció d\'àudio variable + Salta a l\'instant + Salta aquesta quantitat de segons en rebobinar o en avançar ràpidament Definex nom del servidor Utilitza el servidor per defecte Amplia la notificació diff --git a/core/src/main/res/values-da/strings.xml b/core/src/main/res/values-da/strings.xml index 2253a9e9c..ba7fafca6 100644 --- a/core/src/main/res/values-da/strings.xml +++ b/core/src/main/res/values-da/strings.xml @@ -66,6 +66,8 @@ Du kan søge efter nye podcasts efter navn, kategori eller popularitet i gpodder.net biblioteket Gennemse gpodder.net + Marker alle som læst + Marker alle episoder som læst Vis information Fjern podcast Del webside link @@ -81,6 +83,8 @@ Stream Fjern Fjern episode + Marker som læst + Marker som ulæst Tilføj til kø Fjern fra kø Besøg webside @@ -104,6 +108,8 @@ Ukendt vært Godkendelses fejl Annuller alle downloads + Download afbrudt + Downloads afsluttet Misdannet URL IO fejl Anmode fejl @@ -234,6 +240,8 @@ Skift din gpodder.net kontos login information. Afspilningshastigheder Tilpas tilgængelige hastigheder for variabelt afspilningshastigheds plugin + Søg tid + Søg så mange sekunder når der spoles tilbage eller frem Indstil værtsnavn Brug standard vært Udvid notifikation diff --git a/core/src/main/res/values-es-rES/strings.xml b/core/src/main/res/values-es-rES/strings.xml index bf753c113..d05c34876 100644 --- a/core/src/main/res/values-es-rES/strings.xml +++ b/core/src/main/res/values-es-rES/strings.xml @@ -39,6 +39,7 @@ URL del canal + Marcar todo como leído Información del programa Compartir el enlace de la web Compartir el enlace del canal @@ -49,6 +50,8 @@ Pausar Transmitir Quitar + Marcar como leído + Marcar como no leído Añadir a la cola Quitar de la cola Visitar el sitio web @@ -69,6 +72,8 @@ Error de conexión Host desconocido Cancelar todas las descargas + Descarga cancelada + Descargas completadas URL malformada Error de E/S Error de petición diff --git a/core/src/main/res/values-hi-rIN/strings.xml b/core/src/main/res/values-hi-rIN/strings.xml index d383765c5..f32c7c02f 100644 --- a/core/src/main/res/values-hi-rIN/strings.xml +++ b/core/src/main/res/values-hi-rIN/strings.xml @@ -52,6 +52,7 @@ यूआरएल द्वारा पॉडकास्ट जोड़ें पॉडकास्ट निर्देशिका + पढ़ने के रूप में सभी को चिह्नित करें जानकारी दिखाएँ पॉडकास्ट हटाएँ @@ -65,6 +66,8 @@ रोकें स्ट्रिम हटाएँ + पढ़ा हुआ के रूप में चिह्नित करें + ना पढ़ा हुआ के रूप में चिह्नित करें क़तार में जोड़ें क़तार से हटाएँ वेबसाइट पर जाएँ @@ -88,6 +91,8 @@ कनेक्शन त्रुटि अज्ञात होस्ट सभी डाउनलोड रद्द करें + डाउनलोड रद्द + डाउनलोड पूरा हो गया है गलत URL आईओ त्रुटि अनुरोध त्रुटि diff --git a/core/src/main/res/values-iw-rIL/strings.xml b/core/src/main/res/values-iw-rIL/strings.xml index cf0e79aec..9e9c0e6bc 100644 --- a/core/src/main/res/values-iw-rIL/strings.xml +++ b/core/src/main/res/values-iw-rIL/strings.xml @@ -67,6 +67,10 @@ אפשר לחפש פודקסטים חדשים לפי בשם, קטגוריה או פופולריות בספריית gpodder.net. עיין בgpodder.net + סמן הכל כנקרא + סמן את כל הפרקים כנקרא + אנא אשר שאתה רוצה לסמן את כל פרקים כנקראים. + אנא אשר שאתה רוצה לסמן את כל פרקים בהזנה זו כנקראים. הצג מידע הסר פודקאסט שתף קישור אתר @@ -82,6 +86,9 @@ הזרם הסר הסר פרק + סמן כנקרא + סמן כלא נקרא + סומן כנקרא הוסף לתור הסר מהתור בקר באתר @@ -105,6 +112,8 @@ שרת לא ידוע שגיאת אימות בטל את כל ההורדות + הורדה בוטלה + הורדות הושלמו כתובת אתר שגויה שגיאת קלט פלט שגיאת בקשה @@ -238,6 +247,8 @@ שנה פרטי התחברות של חשבון gpodder.net. מהירויות ניגון התאמת המהיריות הזמינות לניגון במהירות משתנה + זמן דילוג + דלג מספר שניות זה בדילוג לאחור או קדימה הגדר שם שרת השתמש בשרת ברירת מידל הרחב הודעה diff --git a/core/src/main/res/values-nl/strings.xml b/core/src/main/res/values-nl/strings.xml index baa800486..0f447d54a 100644 --- a/core/src/main/res/values-nl/strings.xml +++ b/core/src/main/res/values-nl/strings.xml @@ -51,6 +51,7 @@ Feed URL Podcast toevoegen bij URL + Alles als gelezen markeren Toon informatie Website link delen Feed link delen @@ -62,6 +63,8 @@ Pauze Stream Verwijderen + Als gelezen markeren + Als ongelezen markeren Voeg toe aan wachtrij Verwijder van wachtrij Website bezoeken @@ -83,6 +86,8 @@ Onbekende host Authenticatie fout Alle downloads annuleren + Download geannuleerd + Downloads afgerond Misvormde URL IO fout Fout in de aanvraag diff --git a/core/src/main/res/values-pl-rPL/strings.xml b/core/src/main/res/values-pl-rPL/strings.xml index 03b9a6b11..ba1a0bb91 100644 --- a/core/src/main/res/values-pl-rPL/strings.xml +++ b/core/src/main/res/values-pl-rPL/strings.xml @@ -66,6 +66,8 @@ Możesz wyszukiwać nowe podcasty ze względu na nazwę, kategorię lub popularność na gpodder.net Przeglądaj gpodder.net + Oznacz wszystkie jako przeczytane + Wszystkie odcinki zaznaczone jako przeczytane Pokaż informacje Usuń podcast Udostępnij stronę @@ -81,6 +83,8 @@ Strumień Usuń Usuń odcinek + Oznacz jako przeczytane + Oznacz jako nieprzeczytane Dodaj do kolejki Usuń z kolejki Odwiedź stronę @@ -104,6 +108,8 @@ Nieznany host Błąd autoryzacji Anuluj wszystkie pobierania + Pobieranie anulowane + Pobieranie ukończone Niepoprawny adres Błąd wejścia/wyjścia Błąd żądania @@ -232,6 +238,8 @@ Zmień dane logowania konta gpodder.net. Prędkość odtwarzania Dostosuj prędkości dostępne dla odtwarzania audio o zmiennej prędkości + Seek time + Przeskocz o tyle sekund przewijając Ustaw nazwę hosta Użyj domyślnego hosta Rozwiń Powiadomienia diff --git a/core/src/main/res/values-pt-rBR/strings.xml b/core/src/main/res/values-pt-rBR/strings.xml index d7d1e181c..c3523acfb 100644 --- a/core/src/main/res/values-pt-rBR/strings.xml +++ b/core/src/main/res/values-pt-rBR/strings.xml @@ -51,6 +51,7 @@ URL do Feed Adicionar podcast por URL + Marcar todos como lido Mostrar informação Compartilhar link do site Compartilhar link do feed @@ -62,6 +63,8 @@ Pausar Stream Remover + Marcar como lido + Marcar como não lido Adicionar à fila Remover da fila Visitar Website @@ -82,6 +85,8 @@ Erro de conexão Host desconhecido Cancelar todos os downloads + Download cancelado + Downloads finalizados URL inválida Erro de IO Erro de requisição diff --git a/core/src/main/res/values-ro-rRO/strings.xml b/core/src/main/res/values-ro-rRO/strings.xml index 82851530a..390f50767 100644 --- a/core/src/main/res/values-ro-rRO/strings.xml +++ b/core/src/main/res/values-ro-rRO/strings.xml @@ -47,6 +47,7 @@ Adresă feed + Marchează toate ca citite Arată informații Împarte adresă website Împarte adresă feed @@ -57,6 +58,8 @@ Pauză Stream Elimină + Marchează ca citit + Marchează ca necitit Adaugă la Coadă Șterge din Coadă Vizitează Website @@ -77,6 +80,8 @@ Eroare de conexiune Host necunoscut Anulează toate descărcările + Descărcare anulată + Descărcări terminate URL malformat Eroare IO Eroare cerere diff --git a/core/src/main/res/values-tr/strings.xml b/core/src/main/res/values-tr/strings.xml index 1af926e30..e83c9b48e 100644 --- a/core/src/main/res/values-tr/strings.xml +++ b/core/src/main/res/values-tr/strings.xml @@ -67,6 +67,10 @@ gdpodder.net dizininde yeni cep yayınlarını isme, kategoriye veya popülerliğe göre arayabilirsiniz veya iTunes mağazasında arama yapabilirsiniz. gpodder.net\'e gözat + Hepsini okundu olarak işaretle + Tüm bölümler okundu olarak işaretlendi + Lütfen tüm bölümleri okundu olarak işaretlemek istediğinizi onaylayın. + Lütfen bu besleme içindeki tüm bölümleri okundu olarak işaretlemek istediğinizi onaylayın. Bilgiyi göster Cep yayını kaldır Web sayfası bağlantısı paylaş @@ -82,6 +86,9 @@ Akış Kaldır Bölümü kaldır + Okundu olarak işaretle + Okunmadı olarak işaretle + Okundu olarak işaretlendi Kuyruğa Ekle Kuyruktan Kaldır Siteyi Ziyaret Et @@ -105,6 +112,8 @@ Bilinmeyen sunucu Yetkilendirme hatası Bütün indirmeleri iptal et + İndirme iptal edildi + İndirme tamamlandı Bozuk URL G/Ç Hatası İstek hatası @@ -237,6 +246,8 @@ gpodder.net hesabınız için giriş bilgisini değiştirin. Çalma hızları Değişken hızlı ses yürütmesi için kullanılabilir hızları özelleştirin + Arama zamanı + Geri veya ileri sararken bu kadar saniye atla Sunucu ismini ayarla Varsayılan sunucuyu kullan Bildirimi Genişlet -- cgit v1.2.3 From 813cf2fc4e88f82791c3da8030ebefc9ca307f14 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 2 Jun 2015 19:45:44 -0400 Subject: merged changes to translation files fixing prior tx pull mess up --- core/src/main/res/values-it-rIT/strings.xml | 7 +++++++ core/src/main/res/values-zh-rCN/strings.xml | 6 ++++++ 2 files changed, 13 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/res/values-it-rIT/strings.xml b/core/src/main/res/values-it-rIT/strings.xml index 849ba2c7a..33d7d6b4d 100644 --- a/core/src/main/res/values-it-rIT/strings.xml +++ b/core/src/main/res/values-it-rIT/strings.xml @@ -67,6 +67,8 @@ Puoi cercare dei nuovi podcast in base al nome, alla categoria o alla popolarità nella directory di gpodder.net. Esplora gpodder.net + Segna tutti come letti + Segnati tutti gli episodi come letti Informazioni Rimuovi un podcast Condividi il link al sito @@ -82,6 +84,9 @@ Stream Rimuovi Rimuovi l\'episodio + Segna come letto + Segna come non letto + Segnato come letto Aggiungi alla coda Rimuovi dalla coda Visita il sito @@ -105,6 +110,8 @@ Host sconosciuto Errore di autenticazione Annulla tutti i download + Download annullato + Download completati URL malformato Errore IO Errore della richiesta diff --git a/core/src/main/res/values-zh-rCN/strings.xml b/core/src/main/res/values-zh-rCN/strings.xml index 20caf6c67..594249a31 100644 --- a/core/src/main/res/values-zh-rCN/strings.xml +++ b/core/src/main/res/values-zh-rCN/strings.xml @@ -67,6 +67,8 @@ 您可以在 gpodder.net 通过名称、类别或热门来搜索新播客 浏览 gpodder.net + 全部标识已读 + 将所有曲目标记为已读 查看信息 删除播客 分享网站链接 @@ -82,6 +84,8 @@ 流媒体 删除 移除曲目 + 标记已读 + 标记未读 添加到播放列表 从播放列表中删除 访问网站 @@ -105,6 +109,8 @@ 未知主机 认证错误 取消所有下载 + 已取消下载 + 下载完成 畸形 URL IO 错误 请求出错 -- cgit v1.2.3 From 6a83057e28a1efc060016ef146b2b74b8c14fca2 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Wed, 3 Jun 2015 11:36:25 +0200 Subject: Fixes "gzip finished without exhausting source" error --- .../core/service/download/HttpDownloader.java | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java index ac0fe8036..61c922719 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java @@ -188,13 +188,17 @@ public class HttpDownloader extends Downloader { } Log.d(TAG, "Starting download"); - while (!cancelled - && (count = connection.read(buffer)) != -1) { - out.write(buffer, 0, count); - request.setSoFar(request.getSoFar() + count); - request.setProgressPercent((int) (((double) request - .getSoFar() / (double) request - .getSize()) * 100)); + try { + while (!cancelled + && (count = connection.read(buffer)) != -1) { + out.write(buffer, 0, count); + request.setSoFar(request.getSoFar() + count); + request.setProgressPercent((int) (((double) request + .getSoFar() / (double) request + .getSize()) * 100)); + } + } catch(IOException e) { + Log.e(TAG, Log.getStackTraceString(e)); } if (cancelled) { onCancelled(); @@ -210,6 +214,9 @@ public class HttpDownloader extends Downloader { request.getSize() ); return; + } else if(request.getSoFar() == 0){ + onFail(DownloadError.ERROR_IO_ERROR, "Download completed, but nothing was read"); + return; } onSuccess(); } -- cgit v1.2.3 From fbff9a90b1bdf5fc7d1660ecc36b462f3e913793 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Wed, 3 Jun 2015 20:06:56 -0400 Subject: latest update from transifex --- core/src/main/res/values-fr/strings.xml | 4 ++-- core/src/main/res/values-sv-rSE/strings.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml index 57e967c70..2f59e139d 100644 --- a/core/src/main/res/values-fr/strings.xml +++ b/core/src/main/res/values-fr/strings.xml @@ -64,7 +64,7 @@ URL ou flux ou site web Ajouter un podcast par son URL Trouver le podcast dans la bibliothèque - Vous pouvez chercher de nouveaux podcasts en filtrant par nom, catégorie ou popularité dans la bibliothèque gpodder.net + Vous pouvez chercher de nouveaux podcasts en filtrant par nom, catégorie ou popularité dans la bibliothèque gpodder.net, ou sur l\'iTunes Store. Chercher sur gpodder.net Tous marquer comme lus @@ -146,7 +146,7 @@ Effacer la liste Annuler Élément retiré - Déplacer vers le haut de haut de la liste + Déplacer vers le haut de la liste Déplacer vers le bas de la liste Trier Ordre alphabétique diff --git a/core/src/main/res/values-sv-rSE/strings.xml b/core/src/main/res/values-sv-rSE/strings.xml index 68d6f94f2..c0c49ca7d 100644 --- a/core/src/main/res/values-sv-rSE/strings.xml +++ b/core/src/main/res/values-sv-rSE/strings.xml @@ -66,7 +66,7 @@ URL till flöde eller webbsida Lägg till podcast via URL Hitta podcast i mapp - Du kan söka efter podcasts baserat på namn, kategori eller populäritet med tjänsten gpodder.net + Du kan söka efter podcasts baserat på namn, kategori eller populäritet med tjänsten gpodder.net eller på iTunes Store. Bläddra på gpodder.net Markera alla som spelade -- cgit v1.2.3 From dbf46dfcd8e35d52b6ca3f9ae534f6f3149443ac Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 4 Jun 2015 09:40:27 +0200 Subject: Fix tests --- .../java/de/danoeh/antennapod/core/service/download/HttpDownloader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java index 61c922719..40b7de170 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java @@ -214,7 +214,7 @@ public class HttpDownloader extends Downloader { request.getSize() ); return; - } else if(request.getSoFar() == 0){ + } else if(request.getSize() > 0 && request.getSoFar() == 0){ onFail(DownloadError.ERROR_IO_ERROR, "Download completed, but nothing was read"); return; } -- cgit v1.2.3 From 7f10d2be7c989ac785fe9484b340ee560da70be2 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 6 Jun 2015 13:30:20 -0400 Subject: now closing a lot of cursors that were otherwise staying open --- .../danoeh/antennapod/core/storage/DBReader.java | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index cc20b3d37..dc24c5784 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -261,8 +261,8 @@ public final class DBReader { item.getMedia().setItem(item); } } while (cursor.moveToNext()); - cursor.close(); } + cursor.close(); } private static FeedMedia extractFeedMediaFromCursorRow(final Cursor cursor) { @@ -401,6 +401,7 @@ public final class DBReader { queueIds.add(queueCursor.getLong(0)); } while (queueCursor.moveToNext()); } + queueCursor.close(); return queueIds; } @@ -533,6 +534,7 @@ public final class DBReader { i++; } while (cursor.moveToNext()); } + cursor.close(); return itemIds; } @@ -750,6 +752,7 @@ public final class DBReader { } } } + itemCursor.close(); return item; } @@ -775,6 +778,7 @@ public final class DBReader { } else { result = Collections.emptyList(); } + itemCursor.close(); return result; } @@ -813,6 +817,7 @@ public final class DBReader { } } } + itemCursor.close(); return item; } @@ -857,12 +862,16 @@ public final class DBReader { static String getImageAuthentication(final Context context, final String imageUrl, PodDBAdapter adapter) { String credentials = null; Cursor cursor = adapter.getImageAuthenticationCursor(imageUrl); - if (cursor.moveToFirst()) { - String username = cursor.getString(0); - String password = cursor.getString(1); - return username + ":" + password; + try { + if (cursor.moveToFirst()) { + String username = cursor.getString(0); + String password = cursor.getString(1); + return username + ":" + password; + } + return ""; + } finally { + cursor.close(); } - return ""; } /** @@ -902,6 +911,7 @@ public final class DBReader { item.setDescription(description); item.setContentEncoded(contentEncoded); } + extraCursor.close(); adapter.close(); } -- cgit v1.2.3 From abf4df6491323a51651f3d35bcc420c0f30d466b Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 6 Jun 2015 14:15:57 -0400 Subject: updated italian strings --- core/src/main/res/values-it-rIT/strings.xml | 35 ++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 6 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values-it-rIT/strings.xml b/core/src/main/res/values-it-rIT/strings.xml index 33d7d6b4d..b81e3f2ce 100644 --- a/core/src/main/res/values-it-rIT/strings.xml +++ b/core/src/main/res/values-it-rIT/strings.xml @@ -39,6 +39,7 @@ Annulla Autore Lingua + URL Impostazioni Immagine Errore @@ -67,8 +68,8 @@ Puoi cercare dei nuovi podcast in base al nome, alla categoria o alla popolarità nella directory di gpodder.net. Esplora gpodder.net - Segna tutti come letti - Segnati tutti gli episodi come letti + Segna tutti come riprodotti + Segnati tutti gli episodi come riprodotti Informazioni Rimuovi un podcast Condividi il link al sito @@ -76,6 +77,16 @@ Per favore conferma la cancellazione di questo feed e di TUTTI gli episodi collegati che sono stati precedentemente scaricati. Rimozione feed Ricarica il feed completo + Nascondi gli episodi + Non riprodotti + In pausa + Riprodotti + In coda + Non in coda + Scaricati + Non scaricati + Filtrati + {fa-exclamation-circle} Ultimo aggiornamento fallito Download Riproduci @@ -84,16 +95,20 @@ Stream Rimuovi Rimuovi l\'episodio - Segna come letto - Segna come non letto - Segnato come letto + Segna come riprodotto + Segna come non riprodotto + Segnato come riprodotto Aggiungi alla coda + Aggiunto alla coda Rimuovi dalla coda Visita il sito Carica questo su Flattr Accoda tutti Scarica tutti Salta l\'episodio + Attiva il download automatico + Disattiva il download automatico + Azzera la posizione della riproduzione successo fallito @@ -111,7 +126,7 @@ Errore di autenticazione Annulla tutti i download Download annullato - Download completati + Rapporto del downoad URL malformato Errore IO Errore della richiesta @@ -127,6 +142,9 @@ Rilevato errore durante il download del file:\u0020 Autenticazione richiesta La risorsa che hai richiesto richiede un nome utente e una password + Conferma il download su cellulare + Aggiungi solo alla coda + Abilita temporaneamente Errore! Nessun media in riproduzione @@ -141,6 +159,8 @@ Riproduzione del podcast in corso AntennaPod - Chiave dell\'elemento multimediale sconosciuta: %1$d + Blocca la coda + Sblocca la coda Svuota la coda Undo Oggetto rimosso @@ -250,6 +270,7 @@ Controlli di riproduzione persistenti Mantieni le notifiche e i controlli del blocco dello schermo quando la riproduzione è in pausa. Le versioni di Android prima della 4.1 non supportano le notifiche estese. + Disabilitato Abilita l\'esecuzione automatica di Flattr Carica l\'episodio su Flattr appena è stato riprodotto al %d percento @@ -272,6 +293,7 @@ La directory di importazione è vuota. Seleziona tutti Deseleziona tutti + Dal filesystem locale Utilizza un\'applicazione esterna Esportazione su OPML Esportazione in corso... @@ -330,6 +352,7 @@ Scegli la cartella predefinita Sospendi la riproduzione invece di abbassare il volume quando un\'altra app emette un suono Pausa su interruzione + Riprendi dopo la chiamata Abbonati Abbonato -- cgit v1.2.3 From 46c97da53a6d06a3bc7388b48e259e1884050a4e Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Wed, 10 Jun 2015 17:03:11 -0400 Subject: updating pt strings --- core/src/main/res/values-pt/strings.xml | 58 ++++++++++++++++----------------- 1 file changed, 29 insertions(+), 29 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values-pt/strings.xml b/core/src/main/res/values-pt/strings.xml index 964124b90..abbf97de6 100644 --- a/core/src/main/res/values-pt/strings.xml +++ b/core/src/main/res/values-pt/strings.xml @@ -19,14 +19,14 @@ Cancelar transferência Histórico de reprodução gpodder.net - Acesso gpodder.net + Dados gpodder.net Publicados recentemente Mostrar apenas novos episódios Abrir menu Fechar menu - Preferências da gaveta + Preferências do menu Abrir no navegador Copiar URL @@ -56,7 +56,7 @@ Tamanho:\u0020 A processar... A carregar... - Gravar utilizador e senha + Guardar utilizador e palavra-passe Fechar Tentar novamente Incluir nas transferências automáticas @@ -146,7 +146,7 @@ Imagem Ocorreu um erro ao transferir o ficheiro:\u0020 Requer autenticação - O recurso solicitado requer um utilizador e uma senha + O recurso solicitado requer um utilizador e uma palavra-passe Confirmação de transferência A transferência através de dados móveis está desativada nas definições.\n\nAtivar temporariamente ou apenas adicionar à fila?\n\nA sua decisão será memorizada durante 10 minutos. A transferência através de dados móveis está desativada nas definições.\n\nAtivar temporariamente?\n\nA sua decisão será memorizada durante 10 minutos. @@ -155,9 +155,9 @@ Erro! Nada em reprodução - A preparar + A preparar... Pronto - A procurar + A procurar... Erro de servidor Erro desconhecido Nada em reprodução @@ -190,7 +190,7 @@ Parece que a sua conta flattr não está integrada ao AntennaPod. Clique aqui para autenticar. Parece que a sua conta flattr não está vinculada ao AntennaPod. Pode vincular a sua conta ao AntennaPod ou aceder ao sítio web para fazer o flattr. Autenticar - Ação negada + Ação proibida O AntennaPod não possui as permissões para esta ação. É possível que o token de acesso ao flattr via AntennaPod tenha sido revogado. Pode efetuar nova autenticação ou aceder ao sítio web do item. Acesso revogado Você revogou o token de acesso do AntennaPod à sua conta. Para concluir o processo, tem que remover esta aplicação da lista de aplicações presentes nas definições de conta no sítio web do flattr. @@ -212,7 +212,7 @@ Para que a velocidade de reprodução variável funcione, tem que instalar um biblioteca de terceiros.\n\nClique em Transferir extra para a transferir no Google Play.\n\nQuaisquer problemas que ocorram na utilização do extra devem ser reportados diretamente ao seu programador. Velocidades de reprodução - Não existem itens nesta lista. + Não existem itens nesta lista Ainda não possui quaisquer fontes Outras @@ -220,7 +220,7 @@ Fila Serviços Flattr - Parar reprodução ao remover os auscultadores + Pausa na reprodução ao remover os auscultadores Continuar reprodução ao ligar os auscultadores Ir para a faixa seguinte ao terminar a reprodução Eliminar episódio ao terminar a reprodução @@ -237,7 +237,7 @@ Auscultadores removidos Auscultadores ligados Atualizações móveis - Permitir atualizações através da rede de dados + Permitir atualizações através da rede de dados móveis A atualizar Definições flattr Sessão flattr @@ -250,8 +250,8 @@ Configurar flattr automático Interface Tema - Alterar itens da gaveta - Alterar os itens que aparecem na gaveta de navegação + Alterar itens do menu + Alterar os itens que aparecem no menu de navegação Mudar o aspeto do AntennaPod Transferência automática Configure a transferência automática dos episódios @@ -274,11 +274,11 @@ Mudar informação de acesso Mudar informação de acesso à sua conta gpodder.net Velocidades de reprodução - Personalize as velocidades de reprodução disponíveis. + Personalize as velocidades de reprodução disponíveis Tempo a avançar Tempo a recuar Definir nome de servidor - Utilizar pré-definição + Utilizar predefinições Expansão de notificação Expandir sempre a notificação para mostrar os botões de reprodução Controlos de reprodução persistentes @@ -318,14 +318,14 @@ Exportação... Erro de exportação Exportação efetuada - O ficheiro .opml foi gravado em:\u0020 + O ficheiro .opml foi guardado em:\u0020 Definir temporizador Desativar temporizador - Introduza o tempo + Tempo Temporizador Tempo restante:\u0020 - Valor inválido. Tem que ser um inteiro. + Tem que introduzir um número inteiro segundos minutos horas @@ -339,7 +339,7 @@ Acesso Se ainda não possui uma conta, pode criar uma em:\nhttps://gpodder.net/register/ Utilizador - Senha + Palavra-passe Seleção de dispositivo Criar um novo dispositivo ou escolher um existente para aceder à sua conta gpodder.net ID do dispositivo:\u0020 @@ -353,21 +353,21 @@ Parabéns! A sua conta gpodder.net está vinculada ao seu dispositivo. Agora, já pode sincronizar as subscrições no dispositivo com a sua conta gpodder.net. Sincronizar agora Ir para o ecrã principal - Erro de autenticação gpodder.net - Utilizador ou senha inválido + Erro de autenticação no gpodder.net + Utilizador ou palavra-passe inválida Erro de sincronização gpodder.net Ocorreu um erro ao sincronizar:\u0020 Diretório escolhido: Criar pasta - Escolha o diretório - Criar um diretório com o nome \"%1$s\"? - Novo diretório criado - Não é possível gravar neste diretório - O diretório já existe - Não é possível criar o diretório - Diretório não vazio - O diretório escolhido não está vazio. As transferências serão colocadas neste diretório. Continuar? + Escolha a pasta de dados + Criar uma pasta com o nome \"%1$s\"? + Nova pasta criada + Não é possível guardar nesta pasta + A pasta já existe + Não é possível criar a pasta + A pasta não está vazia + A pasta escolhida não está vazia. As transferências multimédia e os ficheiros serão colocados nesta pasta. Continuar? Escolha a pasta pré-definida Pausa na reprodução em vez de baixar o volume se outra aplicação quiser reproduzir sons Pausa nas interrupções @@ -381,7 +381,7 @@ Mostrar capítulos Mostrar notas Mostrar imagem - Recuar + Recuo rápido Avanço rápido Áudio Vídeo -- cgit v1.2.3 From f29413f3b3c24270553fd560860228d7983d1083 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Wed, 17 Jun 2015 21:27:31 -0400 Subject: fix for NullPointerException in bitmap configs. Fixes AntennaPod/AntennaPod#887 --- .../danoeh/antennapod/core/asynctask/PicassoProvider.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java index 4f2d5b204..e454cec7d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java @@ -266,6 +266,11 @@ public class PicassoProvider { @Override public Bitmap transform(Bitmap source) { Bitmap result = fastblur(source, BLUR_RADIUS); + if (result == null) { + // just return the original + // for some reason we couldn't transform it. + return source; + } source.recycle(); return result; } @@ -305,8 +310,14 @@ public class PicassoProvider { // the following line: // // Stack Blur Algorithm by Mario Klingemann + Bitmap.Config config = sentBitmap.getConfig(); + if (config == null) { + // Sometimes the config can be null, in those cases + // we don't do a transform. + return null; + } - Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true); + Bitmap bitmap = sentBitmap.copy(config, true); if (radius < 1) { return (null); -- cgit v1.2.3 From ce6cd1a353e27f598c7197a360d26602dd894caa Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 18 Jun 2015 17:15:56 +0200 Subject: Don't propose to open malformed URLs --- .../de/danoeh/antennapod/core/util/IntentUtils.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java new file mode 100644 index 000000000..2d5a6e5a1 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/util/IntentUtils.java @@ -0,0 +1,18 @@ +package de.danoeh.antennapod.core.util; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; + +import java.util.List; + +public class IntentUtils { + + public static boolean isCallable(final Context context, final Intent intent) { + List list = context.getPackageManager().queryIntentActivities(intent, + PackageManager.MATCH_DEFAULT_ONLY); + return list.size() > 0; + } + +} -- cgit v1.2.3 From 3945fb2fd967254518ede49aa879a091e0ab9141 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Thu, 18 Jun 2015 18:29:58 -0400 Subject: Fallback for picasso even if we think it's impossible. Fixes AntennaPod/AntennaPod#891 --- .../java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java index e454cec7d..246adb4c1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java @@ -162,6 +162,14 @@ public class PicassoProvider { } if (bitmap == null) { + // this should never, happen, but sometimes it does, so fallback + // check for fallback Uri + String fallbackParam = data.uri.getQueryParameter(PicassoImageResource.PARAM_FALLBACK); + if (fallbackParam != null) { + Uri fallback = Uri.parse(fallbackParam); + bitmap = decodeStreamFromFile(data, fallback); + } + Log.wtf(TAG, "THIS SHOULD NEVER EVER HAPPEN!!"); } return new Result(bitmap, Picasso.LoadedFrom.DISK); -- cgit v1.2.3 From f8fb13e955f33f5f0fc268e1ecba08975890b2a9 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 19 Jun 2015 00:20:24 +0200 Subject: Fixes slow loading times. --- .../de/danoeh/antennapod/core/feed/FeedMedia.java | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index f875eb812..067095c32 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -35,7 +35,7 @@ public class FeedMedia extends FeedFile implements Playable { private String mime_type; private volatile FeedItem item; private Date playbackCompletionDate; - private boolean hasEmbeddedPicture; + private Boolean hasEmbeddedPicture; /* Used for loading item when restoring from parcel. */ private long itemID; @@ -52,7 +52,6 @@ public class FeedMedia extends FeedFile implements Playable { long size, String mime_type, String file_url, String download_url, boolean downloaded, Date playbackCompletionDate, int played_duration) { super(file_url, download_url, downloaded); - checkEmbeddedPicture(); this.id = id; this.item = item; this.duration = duration; @@ -230,7 +229,10 @@ public class FeedMedia extends FeedFile implements Playable { } public boolean hasEmbeddedPicture() { - return this.hasEmbeddedPicture; + if(hasEmbeddedPicture == null) { + checkEmbeddedPicture(); + } + return hasEmbeddedPicture; } @Override @@ -409,7 +411,7 @@ public class FeedMedia extends FeedFile implements Playable { @Override public Uri getImageUri() { - if (hasEmbeddedPicture) { + if (hasEmbeddedPicture()) { Uri.Builder builder = new Uri.Builder(); builder.scheme(SCHEME_MEDIA).encodedPath(getLocalMediaUrl()); return builder.build(); @@ -432,7 +434,7 @@ public class FeedMedia extends FeedFile implements Playable { private void checkEmbeddedPicture() { if (!localFileAvailable()) { - hasEmbeddedPicture = false; + hasEmbeddedPicture = Boolean.FALSE; return; } MediaMetadataRetriever mmr = new MediaMetadataRetriever(); @@ -440,14 +442,13 @@ public class FeedMedia extends FeedFile implements Playable { mmr.setDataSource(getLocalMediaUrl()); byte[] image = mmr.getEmbeddedPicture(); if(image != null) { - hasEmbeddedPicture = true; - } - else { - hasEmbeddedPicture = false; + hasEmbeddedPicture = Boolean.TRUE; + } else { + hasEmbeddedPicture = Boolean.FALSE; } } catch (Exception e) { e.printStackTrace(); - hasEmbeddedPicture = false; + hasEmbeddedPicture = Boolean.FALSE; } } } -- cgit v1.2.3 From 9e71e76edab6390b58c05bb731e396adf23e57ea Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Fri, 19 Jun 2015 16:33:06 -0400 Subject: Attempt to fix AntennaPod/AntennaPod#884 by removing StringUtils.join --- .../antennapod/core/storage/PodDBAdapter.java | 24 ++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'core/src/main') 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 4780098e0..6fabf9005 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -9,9 +9,9 @@ import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; +import android.text.TextUtils; import android.util.Log; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import java.util.Arrays; @@ -435,7 +435,7 @@ public class PodDBAdapter { values.put(KEY_IS_PAGED, feed.isPaged()); values.put(KEY_NEXT_PAGE_LINK, feed.getNextPageLink()); if(feed.getItemFilter() != null && feed.getItemFilter().getValues().length > 0) { - values.put(KEY_HIDE, StringUtils.join(feed.getItemFilter().getValues(), ",")); + values.put(KEY_HIDE, TextUtils.join( ",", feed.getItemFilter().getValues())); } else { values.put(KEY_HIDE, ""); } @@ -465,8 +465,8 @@ public class PodDBAdapter { public void setFeedItemFilter(long feedId, List filterValues) { ContentValues values = new ContentValues(); - values.put(KEY_HIDE, StringUtils.join(filterValues, ",")); - Log.d(TAG, StringUtils.join(filterValues, ",")); + values.put(KEY_HIDE, TextUtils.join(",", filterValues)); + Log.d(TAG, TextUtils.join(",", filterValues)); db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(feedId)}); } @@ -843,7 +843,7 @@ public class PodDBAdapter { ContentValues values = new ContentValues(); values.put(KEY_AUTO_DOWNLOAD, autoDownload); db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?", - new String[] { String.valueOf(feedItem.getId()) } ); + new String[]{String.valueOf(feedItem.getId())}); } public long getDownloadLogSize() { @@ -1294,9 +1294,21 @@ public class PodDBAdapter { } public final LongIntMap getNumberOfUnreadFeedItems(long... feedIds) { + // work around TextUtils.join wanting only boxed items + // and StringUtils.join() causing NoSuchMethodErrors on MIUI + StringBuilder builder = new StringBuilder(); + for (long id : feedIds) { + builder.append(id); + builder.append(','); + } + if (feedIds.length > 0) { + // there's an extra ',', get rid of it + builder.deleteCharAt(builder.length() - 1); + } + final String query = "SELECT " + KEY_FEED + ", COUNT(" + KEY_ID + ") AS count " + " FROM " + TABLE_NAME_FEED_ITEMS - + " WHERE " + KEY_FEED + " IN (" + StringUtils.join(feedIds, ',') + ") " + + " WHERE " + KEY_FEED + " IN (" + builder.toString() + ") " + " AND " + KEY_READ + " = 0" + " GROUP BY " + KEY_FEED; Cursor c = db.rawQuery(query, null); -- cgit v1.2.3 From aa789fa51dde0887f8f4785fdcf431ab91bcbf8f Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Fri, 19 Jun 2015 17:24:07 -0400 Subject: Have to set the fallback URL --- core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index 067095c32..999340900 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -414,6 +414,14 @@ public class FeedMedia extends FeedFile implements Playable { if (hasEmbeddedPicture()) { Uri.Builder builder = new Uri.Builder(); builder.scheme(SCHEME_MEDIA).encodedPath(getLocalMediaUrl()); + + if (item != null && item.getFeed() != null) { + final Uri feedImgUri = item.getFeed().getImageUri(); + if (feedImgUri != null) { + builder.appendQueryParameter(PARAM_FALLBACK, feedImgUri.toString()); + } + } + return builder.build(); } else { return item.getImageUri(); -- cgit v1.2.3 From 3d411388e6a2ba98f84bbf74d9e34baf7cd195c1 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Fri, 19 Jun 2015 23:28:33 -0400 Subject: remove log message --- .../main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java | 2 -- 1 file changed, 2 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java index 246adb4c1..09fe0d654 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java @@ -169,8 +169,6 @@ public class PicassoProvider { Uri fallback = Uri.parse(fallbackParam); bitmap = decodeStreamFromFile(data, fallback); } - - Log.wtf(TAG, "THIS SHOULD NEVER EVER HAPPEN!!"); } return new Result(bitmap, Picasso.LoadedFrom.DISK); -- cgit v1.2.3 From 1684358dadb72ea493993e72bc2414deb5f231c5 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 20 Jun 2015 15:57:54 +0200 Subject: Disable embedded images --- .../main/java/de/danoeh/antennapod/core/feed/FeedMedia.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index 999340900..ee05020cc 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -229,10 +229,12 @@ public class FeedMedia extends FeedFile implements Playable { } public boolean hasEmbeddedPicture() { - if(hasEmbeddedPicture == null) { - checkEmbeddedPicture(); - } - return hasEmbeddedPicture; + return false; + // TODO: reenable! + //if(hasEmbeddedPicture == null) { + // checkEmbeddedPicture(); + //} + //return hasEmbeddedPicture; } @Override @@ -421,7 +423,6 @@ public class FeedMedia extends FeedFile implements Playable { builder.appendQueryParameter(PARAM_FALLBACK, feedImgUri.toString()); } } - return builder.build(); } else { return item.getImageUri(); @@ -431,13 +432,11 @@ public class FeedMedia extends FeedFile implements Playable { @Override public void setDownloaded(boolean downloaded) { super.setDownloaded(downloaded); - checkEmbeddedPicture(); } @Override public void setFile_url(String file_url) { super.setFile_url(file_url); - checkEmbeddedPicture(); } private void checkEmbeddedPicture() { -- cgit v1.2.3 From b0ba5a08f7423e5e75c25a638418444e9a7b8f27 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 6 Jun 2015 00:05:19 +0200 Subject: Sharing in options and context menus --- .../de/danoeh/antennapod/core/util/ShareUtils.java | 56 ++++++++++++++++++---- core/src/main/res/values/strings.xml | 8 +++- 2 files changed, 52 insertions(+), 12 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java index 85f32ed50..bc310ae21 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java @@ -2,6 +2,8 @@ package de.danoeh.antennapod.core.util; import android.content.Context; import android.content.Intent; + +import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedItem; @@ -11,24 +13,58 @@ public class ShareUtils { private ShareUtils() {} - public static void shareLink(Context context, String link) { + public static void shareLink(Context context, String subject, String text) { Intent i = new Intent(Intent.ACTION_SEND); i.setType("text/plain"); - i.putExtra(Intent.EXTRA_SUBJECT, "Sharing URL"); - i.putExtra(Intent.EXTRA_TEXT, link); + i.putExtra(Intent.EXTRA_SUBJECT, subject); + i.putExtra(Intent.EXTRA_TEXT, text); context.startActivity(Intent.createChooser(i, "Share URL")); } - - public static void shareFeedItemLink(Context context, FeedItem item) { - shareLink(context, item.getLink()); + + public static void shareFeedlink(Context context, Feed feed) { + String subject = context.getString(R.string.share_link_label); + shareLink(context, subject, feed.getLink()); } public static void shareFeedDownloadLink(Context context, Feed feed) { - shareLink(context, feed.getDownload_url()); + String subject = context.getString(R.string.share_feed_url_label); + shareLink(context, subject, feed.getDownload_url()); } - - public static void shareFeedlink(Context context, Feed feed) { - shareLink(context, feed.getLink()); + + public static void shareFeedItemLink(Context context, FeedItem item) { + shareFeedItemLink(context, item, false); + } + + public static void shareFeedItemDownloadLink(Context context, FeedItem item) { + shareFeedItemDownloadLink(context, item, false); + } + + public static void shareFeedItemLink(Context context, FeedItem item, boolean withPosition) { + String subject; + String text; + if(withPosition) { + subject = context.getString(R.string.share_link_with_position_label); + int pos = item.getMedia().getPosition(); + text = item.getLink() + " [" + Converter.getDurationStringLong(pos) + "]"; + } else { + subject = context.getString(R.string.share_link_label); + text = item.getLink(); + } + shareLink(context, subject, text); + } + + public static void shareFeedItemDownloadLink(Context context, FeedItem item, boolean withPosition) { + String subject; + String text; + if(withPosition) { + subject = context.getString(R.string.share_item_url_with_position_label); + int pos = item.getMedia().getPosition(); + text = item.getMedia().getDownload_url() + " [" + Converter.getDurationStringLong(pos) + "]"; + } else { + subject = context.getString(R.string.share_item_url_label); + text = item.getMedia().getDownload_url(); + } + shareLink(context, subject, text); } } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 3cedfb8e5..462e0657c 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -86,8 +86,12 @@ Please confirm that you want to mark all episodes in this feed as being played. Show information Remove podcast - Share website link - Share feed link + Share... + Share Link + Share Link with Position + Share Feed URL + Share Episode URL + Share Episode URL with Position Please confirm that you want to delete this feed and ALL episodes of this feed that you have downloaded. Removing feed Refresh complete feed -- cgit v1.2.3 From 8a9229ede62e9f1efef0e2ac102f1d7e930280b0 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 6 Jun 2015 00:25:23 +0200 Subject: Capitalize titles --- .../de/danoeh/antennapod/core/util/ShareUtils.java | 21 ++-- core/src/main/res/values/strings.xml | 112 ++++++++++----------- 2 files changed, 62 insertions(+), 71 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java index bc310ae21..c065a62c3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java @@ -13,22 +13,19 @@ public class ShareUtils { private ShareUtils() {} - public static void shareLink(Context context, String subject, String text) { + public static void shareLink(Context context, String text) { Intent i = new Intent(Intent.ACTION_SEND); i.setType("text/plain"); - i.putExtra(Intent.EXTRA_SUBJECT, subject); i.putExtra(Intent.EXTRA_TEXT, text); - context.startActivity(Intent.createChooser(i, "Share URL")); + context.startActivity(Intent.createChooser(i, context.getString(R.string.share_url_label))); } public static void shareFeedlink(Context context, Feed feed) { - String subject = context.getString(R.string.share_link_label); - shareLink(context, subject, feed.getLink()); + shareLink(context, feed.getLink()); } public static void shareFeedDownloadLink(Context context, Feed feed) { - String subject = context.getString(R.string.share_feed_url_label); - shareLink(context, subject, feed.getDownload_url()); + shareLink(context, feed.getDownload_url()); } public static void shareFeedItemLink(Context context, FeedItem item) { @@ -40,31 +37,25 @@ public class ShareUtils { } public static void shareFeedItemLink(Context context, FeedItem item, boolean withPosition) { - String subject; String text; if(withPosition) { - subject = context.getString(R.string.share_link_with_position_label); int pos = item.getMedia().getPosition(); text = item.getLink() + " [" + Converter.getDurationStringLong(pos) + "]"; } else { - subject = context.getString(R.string.share_link_label); text = item.getLink(); } - shareLink(context, subject, text); + shareLink(context, text); } public static void shareFeedItemDownloadLink(Context context, FeedItem item, boolean withPosition) { - String subject; String text; if(withPosition) { - subject = context.getString(R.string.share_item_url_with_position_label); int pos = item.getMedia().getPosition(); text = item.getMedia().getDownload_url() + " [" + Converter.getDurationStringLong(pos) + "]"; } else { - subject = context.getString(R.string.share_item_url_label); text = item.getMedia().getDownload_url(); } - shareLink(context, subject, text); + shareLink(context, text); } } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 462e0657c..ac9255ac9 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -7,27 +7,27 @@ AntennaPod Feeds - Add podcast + Add Podcast PODCASTS EPISODES - New episodes - All episodes + New Episodes + All Episodes New - Waiting list + Waiting List Settings - Add podcast + Add Podcast Downloads Running Completed Log Cancel Download - Playback history + Playback History gpodder.net - gpodder.net login + gpodder.net Login Recently published - Show only new episodes + Show only new Episodes Open menu @@ -35,14 +35,14 @@ Drawer Preferences - Open in browser + Open in Browser Copy URL Share URL - Copied URL to clipboard. - Go to this position + Copied URL to Clipboard + Go to this Position - Clear history + Clear History Confirm @@ -59,7 +59,7 @@ Chapters Shownotes Description - Most Recent Episode:\u0020 + Most recent episode:\u0020 \u0020episodes Length:\u0020 Size:\u0020 @@ -75,17 +75,17 @@ Feed URL www.example.com/feed Add Podcast by URL - Find podcast in directory + Find Podcast in Directory You can search for new podcasts by name, category or popularity in the gpodder.net directory, or search the iTunes store. Browse gpodder.net Mark all as played - Marked all episodes as played + Marked all Episodes as played Please confirm that you want to mark all episodes as being played. Please confirm that you want to mark all episodes in this feed as being played. Show information - Remove podcast + Remove Podcast Share... Share Link Share Link with Position @@ -93,9 +93,9 @@ Share Episode URL Share Episode URL with Position Please confirm that you want to delete this feed and ALL episodes of this feed that you have downloaded. - Removing feed - Refresh complete feed - Hide episodes + Removing Feed + Refresh complete Feed + Hide Episodes Unplayed Paused Played @@ -104,7 +104,7 @@ Downloaded Not downloaded Filtered - {fa-exclamation-circle} Last refresh failed + {fa-exclamation-circle} Last Refresh failed Download @@ -113,7 +113,7 @@ Stop Stream Remove - Remove episode + Remove Episode Mark as played Mark as unplayed Marked as played @@ -125,39 +125,39 @@ Enqueue all Download all Skip episode - Activate auto download - Deactivate auto download - Reset playback position + Activate Auto Download + Deactivate Auto Download + Reset Playback Position successful failed Download pending Download running - Storage device not found - Insufficient space - File error + Storage Device not found + Insufficient Space + File Error HTTP Data Error Unknown Error Parser Exception - Unsupported Feed type - Connection error - Unknown host - Authentication error + Unsupported Feed Type + Connection Error + Unknown Host + Authentication Error Cancel all downloads Download canceled Download canceled\nDisabled Auto Download for this item Downloads completed with error(s) - Download report + Download Report Malformed URL IO Error - Request error - Database access error + Request Error + Database Access Error \u0020Downloads left Processing downloads Downloading podcast data %1$d downloads succeeded, %2$d failed - Unknown title + Unknown Title Feed Media file Image @@ -185,9 +185,9 @@ AntennaPod - Unknown media key: %1$d - Lock queue - Unlock queue - Clear queue + Lock Queue + Unlock Queue + Clear Queue Undo Item removed Move to top @@ -253,38 +253,38 @@ Smart mark as played Playback Network - Update interval + Update Interval Specify an interval in which the feeds are refreshed automatically or disable it Download media files only over WiFi - Continuous playback + Continuous Playback WiFi media download - Headphones disconnect - Headphones reconnect - Mobile updates + Headphones Disconnect + Headphones Reconnect + Mobile Updates Allow updates over the mobile data connection Refreshing Flattr settings Flattr sign-in Sign in to your flattr account to flattr things directly from the app. - Flattr this app + Flattr this App Support the development of AntennaPod by flattring it. Thanks! Revoke access Revoke the access permission to your flattr account for this app. Automatic Flattr Configure automatic flattring User Interface - Select theme - Change navigation drawer + Select Theme + Change Navigation Drawer Change which items appear in the navigation drawer. Change the appearance of AntennaPod. - Automatic download + Automatic Download Configure the automatic download of episodes. Enable Wi-Fi filter Allow automatic download only for selected Wi-Fi networks. Download when not charging Allow automatic download when the battery is not charging - Parallel downloads - Episode cache + Parallel Downloads + Episode Cache Light Dark Unlimited @@ -305,11 +305,11 @@ Use default host Expand Notification Always expand the notification to show playback buttons. - Persistent playback controls + Persistent Playback Controls Keep notification and lockscreen controls when playback is paused. Android versions before 4.1 do not support expanded notifications. Add new episodes to the front of the queue. - Enqueue at front. + Enqueue at Front Disabled @@ -332,7 +332,7 @@ Choose a specific file path from the local filesystem. Use an external applications like Dropbox, Google Drive or your favourite file manager to open an OPML file. Many applications like Google Mail, Dropbox, Google Drive and most file managers can open OPML files with AntennaPod. Start import - OPML import + OPML Import ERROR! Reading OPML file An error has occurred while reading the opml document: @@ -344,7 +344,7 @@ OPML export Exporting... Export error - OPML export successful. + OPML Export successful. The .opml file was written to:\u0020 @@ -392,7 +392,7 @@ Selected folder: Create folder - Choose data folder + Choose Data Folder Create new folder with name "%1$s"? Created new folder Cannot write to this folder @@ -402,9 +402,9 @@ The folder you have selected is not empty. Media downloads and other files will be placed directly in this folder. Continue anyway? Choose default folder Pause playback instead of lowering volume when another app wants to play sounds - Pause for interruptions + Pause for Interruptions Resume playback after a phone call completes - Resume after call + Resume after Call Subscribe -- cgit v1.2.3 From 7c944cbe65098ea46ee7e85166ada2cdb4b2a20b Mon Sep 17 00:00:00 2001 From: Simon Danner Date: Sun, 21 Jun 2015 12:46:42 +0200 Subject: Download Report: introduce setting to disable Give the use the option to disable the download report. While it is useful to see the failed downloads, if a user is subscribed to many podcasts, most of the times a few fail, which makes the notifications rather annonying. --- .../antennapod/core/preferences/UserPreferences.java | 16 ++++++++++++++++ .../core/service/download/DownloadService.java | 3 ++- core/src/main/res/values/strings.xml | 3 +++ 3 files changed, 21 insertions(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index 594241573..6ef91a22a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -44,6 +44,7 @@ public class UserPreferences implements public static final String PREF_HIDDEN_DRAWER_ITEMS = "prefHiddenDrawerItems"; public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify"; public static final String PREF_PERSISTENT_NOTIFICATION = "prefPersistNotify"; + public static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport"; // Queue public static final String PREF_QUEUE_ADD_TO_FRONT = "prefQueueAddToFront"; @@ -94,6 +95,7 @@ public class UserPreferences implements private List hiddenDrawerItems; private int notifyPriority; private boolean persistNotify; + private boolean showDownloadReport; // Queue private boolean enqueueAtFront; @@ -164,6 +166,7 @@ public class UserPreferences implements } hiddenDrawerItems = Arrays.asList(StringUtils.split(sp.getString(PREF_HIDDEN_DRAWER_ITEMS, ""), ',')); persistNotify = sp.getBoolean(PREF_PERSISTENT_NOTIFICATION, false); + showDownloadReport = sp.getBoolean(PREF_SHOW_DOWNLOAD_REPORT, true); // Queue enqueueAtFront = sp.getBoolean(PREF_QUEUE_ADD_TO_FRONT, false); @@ -307,6 +310,16 @@ public class UserPreferences implements return instance.persistNotify; } + /** + * Returns true if download reports are shown + * + * @return {@code true} if download reports are shown, {@code false} otherwise + */ + public static boolean showDownloadReport() { + instanceAvailable(); + return instance.showDownloadReport; + } + /** * Returns {@code true} if new queue elements are added to the front * @@ -463,6 +476,9 @@ public class UserPreferences implements case PREF_PERSISTENT_NOTIFICATION: persistNotify = sp.getBoolean(PREF_PERSISTENT_NOTIFICATION, false); break; + case PREF_SHOW_DOWNLOAD_REPORT: + showDownloadReport = sp.getBoolean(PREF_SHOW_DOWNLOAD_REPORT, true); + break; // Queue case PREF_QUEUE_ADD_TO_FRONT: enqueueAtFront = sp.getBoolean(PREF_QUEUE_ADD_TO_FRONT, false); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index e7b226eca..fae6dee1d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -309,7 +309,8 @@ public class DownloadService extends Service { Log.d(TAG, "Service shutting down"); isRunning = false; - if (ClientConfig.downloadServiceCallbacks.shouldCreateReport()) { + if (ClientConfig.downloadServiceCallbacks.shouldCreateReport() && + UserPreferences.showDownloadReport()) { updateReport(); } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 3cedfb8e5..cf0630ea0 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -303,6 +303,9 @@ Always expand the notification to show playback buttons. Persistent playback controls Keep notification and lockscreen controls when playback is paused. + Show Download Report + If downloads fail, generate a report that shows the details of the failure. + Android versions before 4.1 do not support expanded notifications. Add new episodes to the front of the queue. Enqueue at front. -- cgit v1.2.3 From 80c719d432d2bc2441a3adeefe542e45af6575da Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 21 Jun 2015 15:43:14 +0200 Subject: Fix datetime parsing (seconds absent) --- core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java index b6df2dc85..10512dd48 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java @@ -49,6 +49,10 @@ public class DateUtils { "EEE, dd MMMM yyyy HH:mm:ss Z", "EEEE, dd MMM yy HH:mm:ss Z", "EEE MMM d HH:mm:ss yyyy", + "EEE, dd MMM yyyy HH:mm Z", + "EEE, dd MMMM yyyy HH:mm Z", + "EEEE, dd MMM yy HH:mm Z", + "EEE MMM d HH:mm yyyy", "yyyy-MM-dd'T'HH:mm:ss", "yyyy-MM-dd'T'HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ss.SSS Z", -- cgit v1.2.3 From 978eadbc16a3a5fd675994796f0af84459af413a Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 21 Jun 2015 16:28:29 +0200 Subject: Fixes Queue transition from playing local to streaming --- .../de/danoeh/antennapod/core/service/playback/PlaybackService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index 3f6769ee4..43a91933c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -634,7 +634,7 @@ public class PlaybackService extends Service { writePlaybackPreferencesNoMediaPlaying(); if (nextMedia != null) { - stream = !playable.localFileAvailable(); + stream = !nextMedia.localFileAvailable(); mediaPlayer.playMediaObject(nextMedia, stream, startWhenPrepared, prepareImmediately); sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, (nextMedia.getMediaType() == MediaType.VIDEO) ? EXTRA_CODE_VIDEO : EXTRA_CODE_AUDIO); -- cgit v1.2.3 From c452d311e290d1b7c747ddb5df5c7c042398ab9a Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 19 Jun 2015 01:57:49 +0200 Subject: Store information if media has an embedded picture in the database --- .../antennapod/core/event/ProgressEvent.java | 36 ++++++++++++++++++++++ .../de/danoeh/antennapod/core/feed/FeedMedia.java | 15 +++++++++ .../core/service/download/DownloadService.java | 1 + .../danoeh/antennapod/core/storage/DBReader.java | 15 ++++++++- .../danoeh/antennapod/core/storage/DBWriter.java | 1 + .../antennapod/core/storage/PodDBAdapter.java | 14 ++++++++- core/src/main/res/values/strings.xml | 4 +++ 7 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/event/ProgressEvent.java (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/ProgressEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/ProgressEvent.java new file mode 100644 index 000000000..3769d6bb1 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/event/ProgressEvent.java @@ -0,0 +1,36 @@ +package de.danoeh.antennapod.core.event; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +public class ProgressEvent { + + public enum Action { + START, END + } + + public final Action action; + public final String message; + + private ProgressEvent(Action action, String message) { + this.action = action; + this.message = message; + } + + public static ProgressEvent start(String message) { + return new ProgressEvent(Action.START, message); + } + + public static ProgressEvent end() { + return new ProgressEvent(Action.END, null); + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("action", action) + .append("message", message) + .toString(); + } + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index ee05020cc..b4cca505c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -35,6 +35,8 @@ public class FeedMedia extends FeedFile implements Playable { private String mime_type; private volatile FeedItem item; private Date playbackCompletionDate; + + // if null: unknown, will be checked private Boolean hasEmbeddedPicture; /* Used for loading item when restoring from parcel. */ @@ -63,6 +65,15 @@ public class FeedMedia extends FeedFile implements Playable { ? null : (Date) playbackCompletionDate.clone(); } + public FeedMedia(long id, FeedItem item, int duration, int position, + long size, String mime_type, String file_url, String download_url, + boolean downloaded, Date playbackCompletionDate, int played_duration, + Boolean hasEmbeddedPicture) { + this(id, item, duration, position, size, mime_type, file_url, download_url, downloaded, + playbackCompletionDate, played_duration); + this.hasEmbeddedPicture = hasEmbeddedPicture; + } + @Override public String getHumanReadableIdentifier() { if (item != null && item.getTitle() != null) { @@ -429,6 +440,10 @@ public class FeedMedia extends FeedFile implements Playable { } } + public void setHasEmbeddedPicture(Boolean hasEmbeddedPicture) { + this.hasEmbeddedPicture = hasEmbeddedPicture; + } + @Override public void setDownloaded(boolean downloaded) { super.setDownloaded(downloaded); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index e7b226eca..06bca3129 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -1143,6 +1143,7 @@ public class DownloadService extends Service { boolean chaptersRead = false; media.setDownloaded(true); media.setFile_url(request.getDestination()); + media.setHasEmbeddedPicture(null); // Get duration MediaMetadataRetriever mmr = null; diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index dc24c5784..4a329c2f6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -274,6 +274,18 @@ public final class DBReader { playbackCompletionDate = new Date( playbackCompletionTime); } + Boolean hasEmbeddedPicture; + switch(cursor.getInt(cursor.getColumnIndex(PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE))) { + case 1: + hasEmbeddedPicture = Boolean.TRUE; + break; + case 0: + hasEmbeddedPicture = Boolean.FALSE; + break; + default: + hasEmbeddedPicture = null; + break; + } return new FeedMedia( mediaId, @@ -286,7 +298,8 @@ public final class DBReader { cursor.getString(PodDBAdapter.KEY_DOWNLOAD_URL_INDEX), cursor.getInt(PodDBAdapter.KEY_DOWNLOADED_INDEX) > 0, playbackCompletionDate, - cursor.getInt(PodDBAdapter.KEY_PLAYED_DURATION_INDEX)); + cursor.getInt(PodDBAdapter.KEY_PLAYED_DURATION_INDEX), + hasEmbeddedPicture); } private static Feed extractFeedFromCursorRow(PodDBAdapter adapter, diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index fe5d0dfd3..feeee48c5 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -100,6 +100,7 @@ public class DBWriter { } media.setDownloaded(false); media.setFile_url(null); + media.setHasEmbeddedPicture(false); PodDBAdapter adapter = new PodDBAdapter(context); adapter.open(); adapter.setMedia(media); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 6fabf9005..ed3cb71e9 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -19,6 +19,8 @@ import java.util.List; import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.ClientConfig; +import de.danoeh.antennapod.core.R; +import de.danoeh.antennapod.core.event.ProgressEvent; import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedComponent; @@ -29,6 +31,7 @@ import de.danoeh.antennapod.core.feed.FeedPreferences; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.util.LongIntMap; import de.danoeh.antennapod.core.util.flattr.FlattrStatus; +import de.greenrobot.event.EventBus; ; @@ -155,6 +158,8 @@ public class PodDBAdapter { public static final String KEY_NEXT_PAGE_LINK = "next_page_link"; public static final String KEY_HIDE = "hide"; public static final String KEY_LAST_UPDATE_FAILED = "last_update_failed"; + public static final String KEY_HAS_EMBEDDED_PICTURE = "has_embedded_picture"; + // Table names public static final String TABLE_NAME_FEEDS = "Feeds"; @@ -209,7 +214,7 @@ public class PodDBAdapter { + KEY_PLAYBACK_COMPLETION_DATE + " INTEGER," + KEY_FEEDITEM + " INTEGER," + KEY_PLAYED_DURATION + " INTEGER," - + KEY_AUTO_DOWNLOAD + " INTEGER)"; + + KEY_HAS_EMBEDDED_PICTURE + " INTEGER)"; public static final String CREATE_TABLE_DOWNLOAD_LOG = "CREATE TABLE " + TABLE_NAME_DOWNLOAD_LOG + " (" + TABLE_PRIMARY_KEY + KEY_FEEDFILE @@ -516,6 +521,7 @@ public class PodDBAdapter { values.put(KEY_DOWNLOAD_URL, media.getDownload_url()); values.put(KEY_DOWNLOADED, media.isDownloaded()); values.put(KEY_FILE_URL, media.getFile_url()); + values.put(KEY_HAS_EMBEDDED_PICTURE, media.hasEmbeddedPicture()); if (media.getPlaybackCompletionDate() != null) { values.put(KEY_PLAYBACK_COMPLETION_DATE, media @@ -1463,6 +1469,9 @@ public class PodDBAdapter { * Helper class for opening the Antennapod database. */ private static class PodDBHelper extends SQLiteOpenHelper { + + private Context context; + /** * Constructor. * @@ -1474,6 +1483,7 @@ public class PodDBAdapter { public PodDBHelper(final Context context, final String name, final CursorFactory factory, final int version) { super(context, name, factory, version); + this.context = context; } @Override @@ -1497,7 +1507,9 @@ public class PodDBAdapter { @Override public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) { + EventBus.getDefault().post(ProgressEvent.start(context.getString(R.string.progress_upgrading_database))); ClientConfig.storageCallbacks.onUpgrade(db, oldVersion, newVersion); + EventBus.getDefault().post(ProgressEvent.end()); } } } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index ac9255ac9..fe8c08e9e 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -435,6 +435,10 @@ Authentication Change your username and password for this podcast and its episodes. + + + Upgrading the database + Importing subscriptions from single-purpose apps… -- cgit v1.2.3 From 20ab6ec260f3e7bd3ba189a155111de631d1bc7d Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 21 Jun 2015 18:22:17 -0400 Subject: set autodownload == false once an item is downloaded --- .../antennapod/core/service/download/DownloadService.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 06bca3129..fb3f480ff 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -1171,12 +1171,16 @@ public class DownloadService extends Service { } try { - if (chaptersRead) { - DBWriter.setFeedItem(DownloadService.this, media.getItem()).get(); - } + // we've received the media, we don't want to autodownload it again + FeedItem item = media.getItem(); + item.setAutoDownload(false); + + // update the db + DBWriter.setFeedItem(DownloadService.this, item).get(); + DBWriter.setFeedMedia(DownloadService.this, media).get(); - if (!DBTasks.isInQueue(DownloadService.this, media.getItem().getId())) { - DBWriter.addQueueItem(DownloadService.this, media.getItem().getId()).get(); + if (!DBTasks.isInQueue(DownloadService.this, item.getId())) { + DBWriter.addQueueItem(DownloadService.this, item.getId()).get(); } } catch (ExecutionException e) { e.printStackTrace(); -- cgit v1.2.3 From c2ca3e1bbdfb67a5b8bc6dea6a4f80d900ac65c7 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Mon, 22 Jun 2015 20:06:28 -0400 Subject: Only call getPSMPInfo if you need both the status and the playable. Fixes AntennaPod/AntennaPod#942 --- .../core/service/playback/PlaybackService.java | 23 +++++++++------------ .../playback/PlaybackServiceMediaPlayer.java | 24 ++++++++++++++++++---- 2 files changed, 30 insertions(+), 17 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index 43a91933c..9ab3d93a1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -442,7 +442,7 @@ public class PlaybackService extends Service { } writePlayerStatusPlaybackPreferences(); - final Playable playable = mediaPlayer.getPSMPInfo().playable; + final Playable playable = newInfo.playable; // Gpodder: send play action if(GpodnetPreferences.loggedIn() && playable instanceof FeedMedia) { @@ -525,7 +525,7 @@ public class PlaybackService extends Service { public boolean onMediaPlayerError(Object inObj, int what, int extra) { final String TAG = "PlaybackService.onErrorListener"; Log.w(TAG, "An error has occured: " + what + " " + extra); - if (mediaPlayer.getPSMPInfo().playerStatus == PlayerStatus.PLAYING) { + if (mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING) { mediaPlayer.pause(true, false); } sendNotificationBroadcast(NOTIFICATION_TYPE_ERROR, what); @@ -549,7 +549,7 @@ public class PlaybackService extends Service { private void endPlayback(boolean playNextEpisode) { Log.d(TAG, "Playback ended"); - final Playable playable = mediaPlayer.getPSMPInfo().playable; + final Playable playable = mediaPlayer.getPlayable(); if (playable == null) { Log.e(TAG, "Cannot end playback: media was null"); return; @@ -744,8 +744,7 @@ public class PlaybackService extends Service { SharedPreferences.Editor editor = PreferenceManager .getDefaultSharedPreferences(getApplicationContext()).edit(); - PlaybackServiceMediaPlayer.PSMPInfo info = mediaPlayer.getPSMPInfo(); - int playerStatus = getCurrentPlayerStatusAsInt(info.playerStatus); + int playerStatus = getCurrentPlayerStatusAsInt(mediaPlayer.getPlayerStatus()); editor.putInt( PlaybackPreferences.PREF_CURRENT_PLAYER_STATUS, playerStatus); @@ -819,7 +818,7 @@ public class PlaybackService extends Service { if (mediaPlayer == null) { return; } - PlaybackServiceMediaPlayer.PSMPInfo newInfo = mediaPlayer.getPSMPInfo(); + PlayerStatus playerStatus = mediaPlayer.getPlayerStatus(); final int smallIcon = ClientConfig.playbackServiceCallbacks.getNotificationIconResource(getApplicationContext()); if (!isCancelled() && @@ -865,7 +864,7 @@ public class PlaybackService extends Service { .setLargeIcon(icon) .setSmallIcon(smallIcon) .setPriority(UserPreferences.getNotifyPriority()); // set notification priority - if (newInfo.playerStatus == PlayerStatus.PLAYING) { + if (playerStatus == PlayerStatus.PLAYING) { notificationBuilder.addAction(android.R.drawable.ic_media_pause, //pause action getString(R.string.pause_label), pauseButtonPendingIntent); @@ -923,7 +922,7 @@ public class PlaybackService extends Service { int position = getCurrentPosition(); int duration = getDuration(); float playbackSpeed = getCurrentPlaybackSpeed(); - final Playable playable = mediaPlayer.getPSMPInfo().playable; + final Playable playable = mediaPlayer.getPlayable(); if (position != INVALID_TIME && duration != INVALID_TIME && playable != null) { Log.d(TAG, "Saving current position to " + position); if (updatePlayedDuration && playable instanceof FeedMedia) { @@ -1200,12 +1199,10 @@ public class PlaybackService extends Service { } public PlayerStatus getStatus() { - return mediaPlayer.getPSMPInfo().playerStatus; + return mediaPlayer.getPlayerStatus(); } - public Playable getPlayable() { - return mediaPlayer.getPSMPInfo().playable; - } + public Playable getPlayable() { return mediaPlayer.getPlayable(); } public void setSpeed(float speed) { mediaPlayer.setSpeed(speed); @@ -1231,7 +1228,7 @@ public class PlaybackService extends Service { public void seekTo(final int t) { if(mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING && GpodnetPreferences.loggedIn()) { - final Playable playable = mediaPlayer.getPSMPInfo().playable; + final Playable playable = mediaPlayer.getPlayable(); if (playable instanceof FeedMedia) { FeedMedia media = (FeedMedia) playable; FeedItem item = media.getItem(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 7a8e38c59..d4b63fdb1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -623,10 +623,6 @@ public class PlaybackServiceMediaPlayer { return mediaType; } - public PlayerStatus getPlayerStatus() { - return playerStatus; - } - public boolean isStreaming() { return stream; } @@ -705,6 +701,26 @@ public class PlaybackServiceMediaPlayer { return new PSMPInfo(playerStatus, media); } + /** + * Returns the current status, if you need the media and the player status together, you should + * use getPSMPInfo() to make sure they're properly synchronized. Otherwise a race condition + * could result in nonsensical results (like a status of PLAYING, but a null playable) + * @return the current player status + */ + public PlayerStatus getPlayerStatus() { + return playerStatus; + } + + /** + * Returns the current media, if you need the media and the player status together, you should + * use getPSMPInfo() to make sure they're properly synchronized. Otherwise a race condition + * could result in nonsensical results (like a status of PLAYING, but a null playable) + * @return the current media. May be null + */ + public Playable getPlayable() { + return media; + } + /** * Returns a token to this object's MediaSession. The MediaSession should only be used for notifications * at the moment. -- cgit v1.2.3 From 33778e30ac156e22c9d748f905ddb26c65eadd78 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Mon, 22 Jun 2015 19:59:57 +0200 Subject: Don't cache shared preferences anymore. Some refactoring. --- .../core/preferences/UserPreferences.java | 547 ++++++--------------- .../danoeh/antennapod/core/storage/DBReader.java | 3 +- .../de/danoeh/antennapod/core/storage/DBTasks.java | 5 +- 3 files changed, 142 insertions(+), 413 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index 6ef91a22a..520bba72b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -29,17 +29,16 @@ import de.danoeh.antennapod.core.receiver.FeedUpdateReceiver; /** * Provides access to preferences set by the user in the settings screen. A * private instance of this class must first be instantiated via - * createInstance() or otherwise every public method will throw an Exception + * init() or otherwise every public method will throw an Exception * when called. */ -public class UserPreferences implements - SharedPreferences.OnSharedPreferenceChangeListener { +public class UserPreferences { public static final String IMPORT_DIR = "import/"; private static final String TAG = "UserPreferences"; - // User Infercasce + // User Interface public static final String PREF_THEME = "prefTheme"; public static final String PREF_HIDDEN_DRAWER_ITEMS = "prefHiddenDrawerItems"; public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify"; @@ -55,7 +54,7 @@ public class UserPreferences implements public static final String PREF_FOLLOW_QUEUE = "prefFollowQueue"; public static final String PREF_AUTO_DELETE = "prefAutoDelete"; public static final String PREF_SMART_MARK_AS_PLAYED_SECS = "prefSmartMarkAsPlayedSecs"; - private static final String PREF_PLAYBACK_SPEED_ARRAY = "prefPlaybackSpeedArray"; + public static final String PREF_PLAYBACK_SPEED_ARRAY = "prefPlaybackSpeedArray"; public static final String PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS = "prefPauseForFocusLoss"; public static final String PREF_RESUME_AFTER_CALL = "prefResumeAfterCall"; @@ -82,188 +81,26 @@ public class UserPreferences implements private static final String PREF_REWIND_SECS = "prefRewindSecs"; public static final String PREF_QUEUE_LOCKED = "prefQueueLocked"; - // TODO: Make this value configurable - private static final float PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD_DEFAULT = 0.8f; - + // Constants private static int EPISODE_CACHE_SIZE_UNLIMITED = -1; - private static UserPreferences instance; - private final Context context; - - // User Interface - private int theme; - private List hiddenDrawerItems; - private int notifyPriority; - private boolean persistNotify; - private boolean showDownloadReport; - - // Queue - private boolean enqueueAtFront; - - // Playback - private boolean pauseOnHeadsetDisconnect; - private boolean unpauseOnHeadsetReconnect; - private boolean followQueue; - private boolean autoDelete; - private int smartMarkAsPlayedSecs; - private String[] playbackSpeedArray; - private boolean pauseForFocusLoss; - private boolean resumeAfterCall; - - // Network - private long updateInterval; - private boolean allowMobileUpdate; - private int parallelDownloads; - private int episodeCacheSize; - private boolean enableAutodownload; - private boolean enableAutodownloadOnBattery; - private boolean enableAutodownloadWifiFilter; - private String[] autodownloadSelectedNetworks; - - // Services - private boolean autoFlattr; - private float autoFlattrPlayedDurationThreshold; - - // Settings somewhere in the GUI - private String playbackSpeed; - private int fastForwardSecs; - private int rewindSecs; - private boolean queueLocked; - - - private UserPreferences(Context context) { - this.context = context; - loadPreferences(); - } + private static Context context; + private static SharedPreferences prefs; /** * Sets up the UserPreferences class. * * @throws IllegalArgumentException if context is null */ - public static void createInstance(Context context) { + public static void init(Context context) { Log.d(TAG, "Creating new instance of UserPreferences"); Validate.notNull(context); - instance = new UserPreferences(context); + UserPreferences.context = context; + UserPreferences.prefs = PreferenceManager.getDefaultSharedPreferences(context); createImportDirectory(); createNoMediaFile(); - PreferenceManager.getDefaultSharedPreferences(context) - .registerOnSharedPreferenceChangeListener(instance); - - } - - private void loadPreferences() { - SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); - - // User Interface - theme = readThemeValue(sp.getString(PREF_THEME, "0")); - if (sp.getBoolean(PREF_EXPANDED_NOTIFICATION, false)) { - notifyPriority = NotificationCompat.PRIORITY_MAX; - } else { - notifyPriority = NotificationCompat.PRIORITY_DEFAULT; - } - hiddenDrawerItems = Arrays.asList(StringUtils.split(sp.getString(PREF_HIDDEN_DRAWER_ITEMS, ""), ',')); - persistNotify = sp.getBoolean(PREF_PERSISTENT_NOTIFICATION, false); - showDownloadReport = sp.getBoolean(PREF_SHOW_DOWNLOAD_REPORT, true); - - // Queue - enqueueAtFront = sp.getBoolean(PREF_QUEUE_ADD_TO_FRONT, false); - - // Playback - pauseOnHeadsetDisconnect = sp.getBoolean(PREF_PAUSE_ON_HEADSET_DISCONNECT, true); - unpauseOnHeadsetReconnect = sp.getBoolean(PREF_UNPAUSE_ON_HEADSET_RECONNECT, true); - followQueue = sp.getBoolean(PREF_FOLLOW_QUEUE, false); - autoDelete = sp.getBoolean(PREF_AUTO_DELETE, false); - smartMarkAsPlayedSecs = Integer.valueOf(sp.getString(PREF_SMART_MARK_AS_PLAYED_SECS, "30")); - playbackSpeedArray = readPlaybackSpeedArray(sp.getString( - PREF_PLAYBACK_SPEED_ARRAY, null)); - pauseForFocusLoss = sp.getBoolean(PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS, false); - - // Network - updateInterval = readUpdateInterval(sp.getString(PREF_UPDATE_INTERVAL, "0")); - allowMobileUpdate = sp.getBoolean(PREF_MOBILE_UPDATE, false); - parallelDownloads = Integer.valueOf(sp.getString(PREF_PARALLEL_DOWNLOADS, "6")); - EPISODE_CACHE_SIZE_UNLIMITED = context.getResources().getInteger( - R.integer.episode_cache_size_unlimited); - episodeCacheSize = readEpisodeCacheSizeInternal(sp.getString(PREF_EPISODE_CACHE_SIZE, "20")); - enableAutodownload = sp.getBoolean(PREF_ENABLE_AUTODL, false); - enableAutodownloadOnBattery = sp.getBoolean(PREF_ENABLE_AUTODL_ON_BATTERY, true); - enableAutodownloadWifiFilter = sp.getBoolean(PREF_ENABLE_AUTODL_WIFI_FILTER, false); - autodownloadSelectedNetworks = StringUtils.split( - sp.getString(PREF_AUTODL_SELECTED_NETWORKS, ""), ','); - - // Services - autoFlattr = sp.getBoolean(PREF_AUTO_FLATTR, false); - autoFlattrPlayedDurationThreshold = sp.getFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD, - PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD_DEFAULT); - - // MediaPlayer - playbackSpeed = sp.getString(PREF_PLAYBACK_SPEED, "1.0"); - fastForwardSecs = sp.getInt(PREF_FAST_FORWARD_SECS, 30); - rewindSecs = sp.getInt(PREF_REWIND_SECS, 30); - queueLocked = sp.getBoolean(PREF_QUEUE_LOCKED, false); - } - - private int readThemeValue(String valueFromPrefs) { - switch (Integer.parseInt(valueFromPrefs)) { - case 0: - return R.style.Theme_AntennaPod_Light; - case 1: - return R.style.Theme_AntennaPod_Dark; - default: - return R.style.Theme_AntennaPod_Light; - } - } - - private long readUpdateInterval(String valueFromPrefs) { - int hours = Integer.parseInt(valueFromPrefs); - return TimeUnit.HOURS.toMillis(hours); - } - - private int readEpisodeCacheSizeInternal(String valueFromPrefs) { - if (valueFromPrefs.equals(context - .getString(R.string.pref_episode_cache_unlimited))) { - return EPISODE_CACHE_SIZE_UNLIMITED; - } else { - return Integer.valueOf(valueFromPrefs); - } - } - - private String[] readPlaybackSpeedArray(String valueFromPrefs) { - String[] selectedSpeeds = null; - // If this preference hasn't been set yet, return the default options - if (valueFromPrefs == null) { - String[] allSpeeds = context.getResources().getStringArray( - R.array.playback_speed_values); - List speedList = new LinkedList(); - for (String speedStr : allSpeeds) { - float speed = Float.parseFloat(speedStr); - if (speed < 2.0001 && speed * 10 % 1 == 0) { - speedList.add(speedStr); - } - } - selectedSpeeds = speedList.toArray(new String[speedList.size()]); - } else { - try { - JSONArray jsonArray = new JSONArray(valueFromPrefs); - selectedSpeeds = new String[jsonArray.length()]; - for (int i = 0; i < jsonArray.length(); i++) { - selectedSpeeds[i] = jsonArray.getString(i); - } - } catch (JSONException e) { - Log.e(TAG, "Got JSON error when trying to get speeds from JSONArray"); - e.printStackTrace(); - } - } - return selectedSpeeds; - } - - private static void instanceAvailable() { - if (instance == null) { - throw new IllegalStateException("UserPreferences was used before being set up"); - } } /** @@ -272,8 +109,7 @@ public class UserPreferences implements * @return R.style.Theme_AntennaPod_Light or R.style.Theme_AntennaPod_Dark */ public static int getTheme() { - instanceAvailable(); - return instance.theme; + return readThemeValue(prefs.getString(PREF_THEME, "0")); } public static int getNoTitleTheme() { @@ -286,8 +122,8 @@ public class UserPreferences implements } public static List getHiddenDrawerItems() { - instanceAvailable(); - return new ArrayList(instance.hiddenDrawerItems); + String hiddenItems = prefs.getString(PREF_HIDDEN_DRAWER_ITEMS, ""); + return new ArrayList(Arrays.asList(StringUtils.split(hiddenItems, ','))); } /** @@ -296,8 +132,11 @@ public class UserPreferences implements * @return NotificationCompat.PRIORITY_MAX or NotificationCompat.PRIORITY_DEFAULT */ public static int getNotifyPriority() { - instanceAvailable(); - return instance.notifyPriority; + if (prefs.getBoolean(PREF_EXPANDED_NOTIFICATION, false)) { + return NotificationCompat.PRIORITY_MAX; + } else { + return NotificationCompat.PRIORITY_DEFAULT; + } } /** @@ -306,8 +145,7 @@ public class UserPreferences implements * @return {@code true} if notifications are persistent, {@code false} otherwise */ public static boolean isPersistNotify() { - instanceAvailable(); - return instance.persistNotify; + return prefs.getBoolean(PREF_PERSISTENT_NOTIFICATION, false); } /** @@ -316,8 +154,7 @@ public class UserPreferences implements * @return {@code true} if download reports are shown, {@code false} otherwise */ public static boolean showDownloadReport() { - instanceAvailable(); - return instance.showDownloadReport; + return prefs.getBoolean(PREF_SHOW_DOWNLOAD_REPORT, true); } /** @@ -326,73 +163,61 @@ public class UserPreferences implements * @return {@code true} if new queue elements are added to the front; {@code false} otherwise */ public static boolean enqueueAtFront() { - instanceAvailable(); - return instance.enqueueAtFront; + return prefs.getBoolean(PREF_QUEUE_ADD_TO_FRONT, false); } public static boolean isPauseOnHeadsetDisconnect() { - instanceAvailable(); - return instance.pauseOnHeadsetDisconnect; + return prefs.getBoolean(PREF_PAUSE_ON_HEADSET_DISCONNECT, true); } public static boolean isUnpauseOnHeadsetReconnect() { - instanceAvailable(); - return instance.unpauseOnHeadsetReconnect; + return prefs.getBoolean(PREF_UNPAUSE_ON_HEADSET_RECONNECT, true); } public static boolean isFollowQueue() { - instanceAvailable(); - return instance.followQueue; + return prefs.getBoolean(PREF_FOLLOW_QUEUE, false); } public static boolean isAutoDelete() { - instanceAvailable(); - return instance.autoDelete; + return prefs.getBoolean(PREF_AUTO_DELETE, false); } public static int getSmartMarkAsPlayedSecs() { - instanceAvailable(); - return instance.smartMarkAsPlayedSecs; + return Integer.valueOf(prefs.getString(PREF_SMART_MARK_AS_PLAYED_SECS, "30")); } public static boolean isAutoFlattr() { - instanceAvailable(); - return instance.autoFlattr; + return prefs.getBoolean(PREF_AUTO_FLATTR, false); } public static String getPlaybackSpeed() { - instanceAvailable(); - return instance.playbackSpeed; + return prefs.getString(PREF_PLAYBACK_SPEED, "1.0"); + } public static String[] getPlaybackSpeedArray() { - instanceAvailable(); - return instance.playbackSpeedArray; + return readPlaybackSpeedArray(prefs.getString(PREF_PLAYBACK_SPEED_ARRAY, null)); } public static boolean shouldPauseForFocusLoss() { - instanceAvailable(); - return instance.pauseForFocusLoss; + return prefs.getBoolean(PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS, false); } public static long getUpdateInterval() { - instanceAvailable(); - return instance.updateInterval; + return readUpdateInterval(prefs.getString(PREF_UPDATE_INTERVAL, "0")); } public static boolean isAllowMobileUpdate() { - instanceAvailable(); - return instance.allowMobileUpdate; + return prefs.getBoolean(PREF_MOBILE_UPDATE, false); } public static int getParallelDownloads() { - instanceAvailable(); - return instance.parallelDownloads; + return Integer.valueOf(prefs.getString(PREF_PARALLEL_DOWNLOADS, "4")); } public static int getEpisodeCacheSizeUnlimited() { - return EPISODE_CACHE_SIZE_UNLIMITED; + return context.getResources().getInteger(R.integer.episode_cache_size_unlimited); } /** @@ -401,33 +226,27 @@ public class UserPreferences implements * 'unlimited'. */ public static int getEpisodeCacheSize() { - instanceAvailable(); - return instance.episodeCacheSize; + return readEpisodeCacheSizeInternal(prefs.getString(PREF_EPISODE_CACHE_SIZE, "20")); } public static boolean isEnableAutodownload() { - instanceAvailable(); - return instance.enableAutodownload; + return prefs.getBoolean(PREF_ENABLE_AUTODL, false); } public static boolean isEnableAutodownloadOnBattery() { - instanceAvailable(); - return instance.enableAutodownloadOnBattery; + return prefs.getBoolean(PREF_ENABLE_AUTODL_ON_BATTERY, true); } public static boolean isEnableAutodownloadWifiFilter() { - instanceAvailable(); - return instance.enableAutodownloadWifiFilter; + return prefs.getBoolean(PREF_ENABLE_AUTODL_WIFI_FILTER, false); } public static int getFastFowardSecs() { - instanceAvailable(); - return instance.fastForwardSecs; + return prefs.getInt(PREF_FAST_FORWARD_SECS, 30); } public static int getRewindSecs() { - instanceAvailable(); - return instance.rewindSecs; + return prefs.getInt(PREF_REWIND_SECS, 30); } @@ -436,148 +255,40 @@ public class UserPreferences implements * duration. */ public static float getAutoFlattrPlayedDurationThreshold() { - instanceAvailable(); - return instance.autoFlattrPlayedDurationThreshold; + return prefs.getFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD, 0.8f); } public static String[] getAutodownloadSelectedNetworks() { - instanceAvailable(); - return instance.autodownloadSelectedNetworks; + String selectedNetWorks = prefs.getString(PREF_AUTODL_SELECTED_NETWORKS, ""); + return StringUtils.split(selectedNetWorks, ','); } public static boolean shouldResumeAfterCall() { - instanceAvailable(); - return instance.resumeAfterCall; + return prefs.getBoolean(PREF_RESUME_AFTER_CALL, true); } public static boolean isQueueLocked() { - instanceAvailable(); - return instance.queueLocked; - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sp, String key) { - Log.d(TAG, "Registered change of user preferences. Key: " + key); - switch(key) { - // User Interface - case PREF_THEME: - theme = readThemeValue(sp.getString(PREF_THEME, "")); - break; - case PREF_HIDDEN_DRAWER_ITEMS: - hiddenDrawerItems = Arrays.asList(StringUtils.split(sp.getString(PREF_HIDDEN_DRAWER_ITEMS, ""), ',')); - break; - case PREF_EXPANDED_NOTIFICATION: - if (sp.getBoolean(PREF_EXPANDED_NOTIFICATION, false)) { - notifyPriority = NotificationCompat.PRIORITY_MAX; - } else { - notifyPriority = NotificationCompat.PRIORITY_DEFAULT; - } - break; - case PREF_PERSISTENT_NOTIFICATION: - persistNotify = sp.getBoolean(PREF_PERSISTENT_NOTIFICATION, false); - break; - case PREF_SHOW_DOWNLOAD_REPORT: - showDownloadReport = sp.getBoolean(PREF_SHOW_DOWNLOAD_REPORT, true); - break; - // Queue - case PREF_QUEUE_ADD_TO_FRONT: - enqueueAtFront = sp.getBoolean(PREF_QUEUE_ADD_TO_FRONT, false); - break; - // Playback - case PREF_PAUSE_ON_HEADSET_DISCONNECT: - pauseOnHeadsetDisconnect = sp.getBoolean(PREF_PAUSE_ON_HEADSET_DISCONNECT, true); - break; - case PREF_UNPAUSE_ON_HEADSET_RECONNECT: - unpauseOnHeadsetReconnect = sp.getBoolean(PREF_UNPAUSE_ON_HEADSET_RECONNECT, true); - break; - case PREF_FOLLOW_QUEUE: - followQueue = sp.getBoolean(PREF_FOLLOW_QUEUE, false); - break; - case PREF_AUTO_DELETE: - autoDelete = sp.getBoolean(PREF_AUTO_DELETE, false); - break; - case PREF_SMART_MARK_AS_PLAYED_SECS: - smartMarkAsPlayedSecs = Integer.valueOf(sp.getString(PREF_SMART_MARK_AS_PLAYED_SECS, "30")); - break; - case PREF_PLAYBACK_SPEED_ARRAY: - playbackSpeedArray = readPlaybackSpeedArray(sp.getString(PREF_PLAYBACK_SPEED_ARRAY, null)); - break; - case PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS: - pauseForFocusLoss = sp.getBoolean(PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS, false); - break; - case PREF_RESUME_AFTER_CALL: - resumeAfterCall = sp.getBoolean(PREF_RESUME_AFTER_CALL, true); - break; - // Network - case PREF_UPDATE_INTERVAL: - updateInterval = readUpdateInterval(sp.getString(PREF_UPDATE_INTERVAL, "0")); - ClientConfig.applicationCallbacks.setUpdateInterval(updateInterval); - break; - case PREF_MOBILE_UPDATE: - allowMobileUpdate = sp.getBoolean(PREF_MOBILE_UPDATE, false); - break; - case PREF_PARALLEL_DOWNLOADS: - parallelDownloads = Integer.valueOf(sp.getString(PREF_PARALLEL_DOWNLOADS, "6")); - break; - case PREF_EPISODE_CACHE_SIZE: - episodeCacheSize = readEpisodeCacheSizeInternal(sp.getString(PREF_EPISODE_CACHE_SIZE, "20")); - break; - case PREF_ENABLE_AUTODL: - enableAutodownload = sp.getBoolean(PREF_ENABLE_AUTODL, false); - break; - case PREF_ENABLE_AUTODL_ON_BATTERY: - enableAutodownloadOnBattery = sp.getBoolean(PREF_ENABLE_AUTODL_ON_BATTERY, true); - break; - case PREF_ENABLE_AUTODL_WIFI_FILTER: - enableAutodownloadWifiFilter = sp.getBoolean(PREF_ENABLE_AUTODL_WIFI_FILTER, false); - break; - case PREF_AUTODL_SELECTED_NETWORKS: - autodownloadSelectedNetworks = StringUtils.split( - sp.getString(PREF_AUTODL_SELECTED_NETWORKS, ""), ','); - break; - // Services - case PREF_AUTO_FLATTR: - autoFlattr = sp.getBoolean(PREF_AUTO_FLATTR, false); - break; - case PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD: - autoFlattrPlayedDurationThreshold = sp.getFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD, - PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD_DEFAULT); - break; - // Mediaplayer - case PREF_PLAYBACK_SPEED: - playbackSpeed = sp.getString(PREF_PLAYBACK_SPEED, "1.0"); - break; - case PREF_FAST_FORWARD_SECS: - fastForwardSecs = sp.getInt(PREF_FAST_FORWARD_SECS, 30); - break; - case PREF_REWIND_SECS: - rewindSecs = sp.getInt(PREF_REWIND_SECS, 30); - break; - case PREF_QUEUE_LOCKED: - queueLocked = sp.getBoolean(PREF_QUEUE_LOCKED, false); - break; - default: - Log.w(TAG, "Unhandled key: " + key); - } + return prefs.getBoolean(PREF_QUEUE_LOCKED, false); } public static void setPrefFastForwardSecs(int secs) { Log.d(TAG, "setPrefFastForwardSecs(" + secs +")"); - SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(instance.context).edit(); + SharedPreferences.Editor editor = prefs.edit(); editor.putInt(PREF_FAST_FORWARD_SECS, secs); editor.commit(); } public static void setPrefRewindSecs(int secs) { Log.d(TAG, "setPrefRewindSecs(" + secs +")"); - SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(instance.context).edit(); - editor.putInt(PREF_REWIND_SECS, secs); - editor.commit(); + prefs.edit() + .putInt(PREF_REWIND_SECS, secs) + .apply(); } public static void setPlaybackSpeed(String speed) { - PreferenceManager.getDefaultSharedPreferences(instance.context).edit() - .putString(PREF_PLAYBACK_SPEED, speed).apply(); + prefs.edit() + .putString(PREF_PLAYBACK_SPEED, speed) + .apply(); } public static void setPlaybackSpeedArray(String[] speeds) { @@ -585,72 +296,105 @@ public class UserPreferences implements for (String speed : speeds) { jsonArray.put(speed); } - PreferenceManager.getDefaultSharedPreferences(instance.context).edit() - .putString(PREF_PLAYBACK_SPEED_ARRAY, jsonArray.toString()) - .apply(); - } - - public static void setAutodownloadSelectedNetworks(Context context, - String[] value) { - SharedPreferences.Editor editor = PreferenceManager - .getDefaultSharedPreferences(context.getApplicationContext()) - .edit(); - editor.putString(PREF_AUTODL_SELECTED_NETWORKS, - StringUtils.join(value, ',')); - editor.commit(); + prefs.edit() + .putString(PREF_PLAYBACK_SPEED_ARRAY, jsonArray.toString()) + .apply(); + } + + public static void setAutodownloadSelectedNetworks(String[] value) { + prefs.edit() + .putString(PREF_AUTODL_SELECTED_NETWORKS, StringUtils.join(value, ',')) + .apply(); } /** * Sets the update interval value. Should only be used for testing purposes! */ - public static void setUpdateInterval(Context context, long newValue) { - instanceAvailable(); - SharedPreferences.Editor editor = PreferenceManager - .getDefaultSharedPreferences(context.getApplicationContext()) - .edit(); - editor.putString(PREF_UPDATE_INTERVAL, - String.valueOf(newValue)); - editor.commit(); - instance.updateInterval = newValue; + public static void setUpdateInterval(long hours) { + prefs.edit() + .putString(PREF_UPDATE_INTERVAL, String.valueOf(hours)) + .apply(); + restartUpdateAlarm(TimeUnit.HOURS.toMillis(hours), TimeUnit.HOURS.toMillis(hours)); } /** * Change the auto-flattr settings * - * @param context For accessing the shared preferences * @param enabled Whether automatic flattring should be enabled at all * @param autoFlattrThreshold The percentage of playback time after which an episode should be * flattrd. Must be a value between 0 and 1 (inclusive) * */ - public static void setAutoFlattrSettings(Context context, boolean enabled, float autoFlattrThreshold) { - instanceAvailable(); + public static void setAutoFlattrSettings( boolean enabled, float autoFlattrThreshold) { Validate.inclusiveBetween(0.0, 1.0, autoFlattrThreshold); - PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()) - .edit() - .putBoolean(PREF_AUTO_FLATTR, enabled) - .putFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD, autoFlattrThreshold) - .commit(); - instance.autoFlattr = enabled; - instance.autoFlattrPlayedDurationThreshold = autoFlattrThreshold; + prefs.edit() + .putBoolean(PREF_AUTO_FLATTR, enabled) + .putFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD, autoFlattrThreshold) + .apply(); } public static void setHiddenDrawerItems(Context context, List items) { - instanceAvailable(); - instance.hiddenDrawerItems = items; String str = StringUtils.join(items, ','); - PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()) - .edit() - .putString(PREF_HIDDEN_DRAWER_ITEMS, str) - .commit(); + prefs.edit() + .putString(PREF_HIDDEN_DRAWER_ITEMS, str) + .apply(); } public static void setQueueLocked(boolean locked) { - instanceAvailable(); - instance.queueLocked = locked; - PreferenceManager.getDefaultSharedPreferences(instance.context) - .edit() - .putBoolean(PREF_QUEUE_LOCKED, locked) - .commit(); + prefs.edit() + .putBoolean(PREF_QUEUE_LOCKED, locked) + .apply(); + } + + private static int readThemeValue(String valueFromPrefs) { + switch (Integer.parseInt(valueFromPrefs)) { + case 0: + return R.style.Theme_AntennaPod_Light; + case 1: + return R.style.Theme_AntennaPod_Dark; + default: + return R.style.Theme_AntennaPod_Light; + } + } + + private static long readUpdateInterval(String valueFromPrefs) { + int hours = Integer.parseInt(valueFromPrefs); + return TimeUnit.HOURS.toMillis(hours); + } + + private static int readEpisodeCacheSizeInternal(String valueFromPrefs) { + if (valueFromPrefs.equals(context.getString(R.string.pref_episode_cache_unlimited))) { + return EPISODE_CACHE_SIZE_UNLIMITED; + } else { + return Integer.valueOf(valueFromPrefs); + } + } + + private static String[] readPlaybackSpeedArray(String valueFromPrefs) { + String[] selectedSpeeds = null; + // If this preference hasn't been set yet, return the default options + if (valueFromPrefs == null) { + String[] allSpeeds = context.getResources().getStringArray(R.array.playback_speed_values); + List speedList = new LinkedList(); + for (String speedStr : allSpeeds) { + float speed = Float.parseFloat(speedStr); + if (speed < 2.0001 && speed * 10 % 1 == 0) { + speedList.add(speedStr); + } + } + selectedSpeeds = speedList.toArray(new String[speedList.size()]); + } else { + try { + JSONArray jsonArray = new JSONArray(valueFromPrefs); + selectedSpeeds = new String[jsonArray.length()]; + for (int i = 0; i < jsonArray.length(); i++) { + selectedSpeeds[i] = jsonArray.getString(i); + } + } catch (JSONException e) { + Log.e(TAG, "Got JSON error when trying to get speeds from JSONArray"); + e.printStackTrace(); + } + } + return selectedSpeeds; } @@ -664,9 +408,6 @@ public class UserPreferences implements * could not be created. */ public static File getDataFolder(Context context, String type) { - instanceAvailable(); - SharedPreferences prefs = PreferenceManager - .getDefaultSharedPreferences(context.getApplicationContext()); String strDir = prefs.getString(PREF_DATA_FOLDER, null); if (strDir == null) { Log.d(TAG, "Using default data folder"); @@ -712,12 +453,9 @@ public class UserPreferences implements public static void setDataFolder(String dir) { Log.d(TAG, "Result from DirectoryChooser: " + dir); - instanceAvailable(); - SharedPreferences prefs = PreferenceManager - .getDefaultSharedPreferences(instance.context); - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(PREF_DATA_FOLDER, dir); - editor.commit(); + prefs.edit() + .putString(PREF_DATA_FOLDER, dir) + .apply(); createImportDirectory(); } @@ -725,8 +463,7 @@ public class UserPreferences implements * Create a .nomedia file to prevent scanning by the media scanner. */ private static void createNoMediaFile() { - File f = new File(instance.context.getExternalFilesDir(null), - ".nomedia"); + File f = new File(context.getExternalFilesDir(null), ".nomedia"); if (!f.exists()) { try { f.createNewFile(); @@ -743,8 +480,7 @@ public class UserPreferences implements * available */ private static void createImportDirectory() { - File importDir = getDataFolder(instance.context, - IMPORT_DIR); + File importDir = getDataFolder(context, IMPORT_DIR); if (importDir != null) { if (importDir.exists()) { Log.d(TAG, "Import directory already exists"); @@ -761,12 +497,10 @@ public class UserPreferences implements * Updates alarm registered with the AlarmManager service or deactivates it. */ public static void restartUpdateAlarm(long triggerAtMillis, long intervalMillis) { - instanceAvailable(); Log.d(TAG, "Restarting update alarm."); - AlarmManager alarmManager = (AlarmManager) instance.context - .getSystemService(Context.ALARM_SERVICE); - PendingIntent updateIntent = PendingIntent.getBroadcast( - instance.context, 0, new Intent(ClientConfig.applicationCallbacks.getApplicationInstance(), FeedUpdateReceiver.class), 0); + AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + PendingIntent updateIntent = PendingIntent.getBroadcast(context, 0, + new Intent(ClientConfig.applicationCallbacks.getApplicationInstance(), FeedUpdateReceiver.class), 0); alarmManager.cancel(updateIntent); if (intervalMillis != 0) { alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtMillis, intervalMillis, @@ -777,12 +511,11 @@ public class UserPreferences implements } } - /** * Reads episode cache size as it is saved in the episode_cache_size_values array. */ public static int readEpisodeCacheSize(String valueFromPrefs) { - instanceAvailable(); - return instance.readEpisodeCacheSizeInternal(valueFromPrefs); + return readEpisodeCacheSizeInternal(valueFromPrefs); } + } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 4a329c2f6..95c033dc5 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -124,8 +124,7 @@ public final class DBReader { * can be loaded separately with {@link #getFeedItemList(android.content.Context, de.danoeh.antennapod.core.feed.Feed)}. */ public static List getExpiredFeedsList(final Context context, final long expirationTime) { - if (BuildConfig.DEBUG) - Log.d(TAG, String.format("getExpiredFeedsList(%d)", expirationTime)); + Log.d(TAG, String.format("getExpiredFeedsList(%d)", expirationTime)); PodDBAdapter adapter = new PodDBAdapter(context); adapter.open(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index defce5930..711cd773e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -199,11 +199,8 @@ public final class DBTasks { */ public static List getExpiredFeeds(final Context context) { long millis = UserPreferences.getUpdateInterval(); - if (millis > 0) { - - List feedList = DBReader.getExpiredFeedsList(context, - millis); + List feedList = DBReader.getExpiredFeedsList(context, millis); if (feedList.size() > 0) { refreshFeeds(context, feedList); } -- cgit v1.2.3 From f2dd49d533475a9486ed00ba88abf30489b59519 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 23 Jun 2015 20:05:12 -0400 Subject: Return NULL instead of result when unable to load bitmap. There are still cases where 'bitmap' could be null. We shouldn't return a result when that's the case. Returnning null appears to be supported by Picasso. (see Picasso.NetworkRequestHandler) Fixes AntennaPod/AntennaPod#947 --- .../java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java index 09fe0d654..8e47a5b71 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java @@ -170,6 +170,12 @@ public class PicassoProvider { bitmap = decodeStreamFromFile(data, fallback); } } + + if (bitmap == null) { + Log.e(TAG, "Could not load media"); + return null; + } + return new Result(bitmap, Picasso.LoadedFrom.DISK); } -- cgit v1.2.3 From bf3ef27b384162cfe55694937b7d8e0c0e109dfc Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Wed, 24 Jun 2015 11:53:10 +0200 Subject: Cache DateTime parser --- core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java index 10512dd48..7b06128f9 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java @@ -16,6 +16,11 @@ public class DateUtils { private static final String TAG = "DateUtils"; + private static final SimpleDateFormat parser = new SimpleDateFormat("", Locale.US); + static { + parser.setLenient(false); + } + public static Date parse(final String input) { if(input == null) { throw new IllegalArgumentException("Date most not be null"); @@ -61,8 +66,7 @@ public class DateUtils { "yyyy-MM-ddZ", "yyyy-MM-dd" }; - SimpleDateFormat parser = new SimpleDateFormat("", Locale.US); - parser.setLenient(false); + ParsePosition pos = new ParsePosition(0); for(String pattern : patterns) { parser.applyPattern(pattern); -- cgit v1.2.3 From 717a6a645e3e9dfbcef7d3dd6b509be98c68ef22 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Wed, 24 Jun 2015 17:43:50 +0200 Subject: Set update interval or time of day --- .../core/preferences/UserPreferences.java | 68 ++++++++++++++++++++-- core/src/main/res/values/arrays.xml | 11 ---- core/src/main/res/values/strings.xml | 8 ++- 3 files changed, 69 insertions(+), 18 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index 5d53db5b3..d96d25fc2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -19,6 +19,7 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; import java.util.LinkedList; import java.util.List; import java.util.concurrent.TimeUnit; @@ -206,7 +207,24 @@ public class UserPreferences { } public static long getUpdateInterval() { - return readUpdateInterval(prefs.getString(PREF_UPDATE_INTERVAL, "0")); + String updateInterval = prefs.getString(PREF_UPDATE_INTERVAL, "0"); + if(false == updateInterval.contains(":")) { + return readUpdateInterval(updateInterval); + } else { + return 0; + } + } + + public static int[] getUpdateTimeOfDay() { + String datetime = prefs.getString(PREF_UPDATE_INTERVAL, ""); + if(datetime.length() >= 3 && datetime.contains(":")) { + String[] parts = datetime.split(":"); + int hourOfDay = Integer.valueOf(parts[0]); + int minute = Integer.valueOf(parts[1]); + return new int[] { hourOfDay, minute }; + } else { + return new int[0]; + } } public static boolean isAllowMobileUpdate() { @@ -316,6 +334,16 @@ public class UserPreferences { restartUpdateAlarm(); } + /** + * Sets the update interval value. Should only be used for testing purposes! + */ + public static void setUpdateTimeOfDay(int hourOfDay, int minute) { + prefs.edit() + .putString(PREF_UPDATE_INTERVAL, hourOfDay + ":" + minute) + .apply(); + restartUpdateAlarm(); + } + /** * Change the auto-flattr settings * @@ -493,14 +521,19 @@ public class UserPreferences { } public static void restartUpdateAlarm() { - long hours = getUpdateInterval(); - restartUpdateAlarm(TimeUnit.SECONDS.toMillis(10), hours); + int[] timeOfDay = getUpdateTimeOfDay(); + if (timeOfDay.length == 2) { + restartUpdateTimeOfDayAlarm(timeOfDay[0], timeOfDay[1]); + } else { + long hours = getUpdateInterval(); + restartUpdateIntervalAlarm(TimeUnit.SECONDS.toMillis(10), hours); + } } /** - * Updates alarm registered with the AlarmManager service or deactivates it. + * Sets the interval in which the feeds are refreshed automatically */ - public static void restartUpdateAlarm(long triggerAtMillis, long intervalMillis) { + public static void restartUpdateIntervalAlarm(long triggerAtMillis, long intervalMillis) { Log.d(TAG, "Restarting update alarm."); AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); PendingIntent updateIntent = PendingIntent.getBroadcast(context, 0, @@ -517,6 +550,31 @@ public class UserPreferences { } } + /** + * Sets time of day the feeds are refreshed automatically + */ + public static void restartUpdateTimeOfDayAlarm(int hoursOfDay, int minute) { + Log.d(TAG, "Restarting update alarm."); + AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); + PendingIntent updateIntent = PendingIntent.getBroadcast(context, 0, + new Intent(ClientConfig.applicationCallbacks.getApplicationInstance(), FeedUpdateReceiver.class), 0); + alarmManager.cancel(updateIntent); + + Calendar now = Calendar.getInstance(); + Calendar alarm = (Calendar)now.clone(); + alarm.set(Calendar.HOUR_OF_DAY, hoursOfDay); + alarm.set(Calendar.MINUTE, minute); + if(alarm.before(now)) { + alarm.add(Calendar.DATE, 1); + } + + alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, + alarm.getTimeInMillis(), + AlarmManager.INTERVAL_DAY, + updateIntent); + Log.d(TAG, "Changed alarm to new time of day " + hoursOfDay + ":" + minute); + } + /** * Reads episode cache size as it is saved in the episode_cache_size_values array. */ diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 4ecf2cf61..afcb31078 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -20,18 +20,7 @@ 60 - - Manual - 1 hour - 2 hours - 4 hours - 8 hours - 12 hours - 24 hours - - - 0 1 2 4 diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index c2147cccc..0f1830202 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -253,8 +253,12 @@ Smart mark as played Playback Network - Update Interval - Specify an interval in which the feeds are refreshed automatically or disable it + Update Interval or Time of Day + Specify an interval or a specific time of day to refresh the feeds automatically + You can set an interval like \"every 2 hours\", set a specific time of day like \"7:00 AM\" or disable automatic updates altogether.\n\nPlease note: Update times are inexact. You may encounter a short delay." + Disable + Set Interval + Set Time of Day Download media files only over WiFi Continuous Playback WiFi media download -- cgit v1.2.3 From e3d0f8fbe51c95c26e03ecdbdcd2e3a869117fd4 Mon Sep 17 00:00:00 2001 From: Simon Schubert <2@0x2c.org> Date: Thu, 25 Jun 2015 11:12:59 +0200 Subject: gpoddernet: do not crash on unknown remote actions According to [1] and my own episode actions feed, "action":"flattr" is a valid action. Future-proof the episode actions code by ignoring actions that we don't know and care about. This fixes the java.lang.IllegalArgumentException: FLATTR is not a constant exception when fetching the episode actions list. [1]: https://gpoddernet.readthedocs.org/en/latest/api/reference/events.html --- .../antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java index bd6210d13..efe39485e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java +++ b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/model/GpodnetEpisodeAction.java @@ -93,7 +93,12 @@ public class GpodnetEpisodeAction { if(StringUtils.isEmpty(podcast) || StringUtils.isEmpty(episode) || StringUtils.isEmpty(actionString)) { return null; } - GpodnetEpisodeAction.Action action = GpodnetEpisodeAction.Action.valueOf(actionString.toUpperCase()); + GpodnetEpisodeAction.Action action; + try { + action = GpodnetEpisodeAction.Action.valueOf(actionString.toUpperCase()); + } catch (IllegalArgumentException e) { + return null; + } String deviceId = object.optString("device", ""); GpodnetEpisodeAction.Builder builder = new GpodnetEpisodeAction.Builder(podcast, episode, action) .deviceId(deviceId); -- cgit v1.2.3 From d4fb1b09686cb998c850dc52abb9654e27bd31e9 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 27 Jun 2015 09:25:24 -0400 Subject: Return a copy of the downloads. This should prevent any IndexOutOfBounds errors fixes AntennaPod/AntennaPod#968 --- .../danoeh/antennapod/core/service/download/DownloadService.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 03e323aa3..1ad4a9d0d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -243,7 +243,7 @@ public class DownloadService extends Service { handler = new Handler(); newMediaFiles = Collections.synchronizedList(new ArrayList()); reportQueue = Collections.synchronizedList(new ArrayList()); - downloads = new ArrayList(); + downloads = Collections.synchronizedList(new ArrayList()); numberOfDownloads = new AtomicInteger(0); IntentFilter cancelDownloadReceiverFilter = new IntentFilter(); @@ -1246,7 +1246,10 @@ public class DownloadService extends Service { } public List getDownloads() { - return downloads; + // return a copy of downloads, but the copy doesn't need to be synchronized. + synchronized (downloads) { + return new ArrayList(downloads); + } } } -- cgit v1.2.3 From 8399da878faff6f6b649ad4c893f212e3f9beb7b Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 27 Jun 2015 10:05:33 -0400 Subject: Guard use of 'media' It can be null in this class, so we should make sure it isn't accessed if it is. fixes AntennaPod/AntennaPod#972 --- .../de/danoeh/antennapod/core/util/playback/PlaybackController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java index a0d12d3e7..ba5428b81 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/PlaybackController.java @@ -555,7 +555,7 @@ public abstract class PlaybackController { * Should be used by classes which implement the OnSeekBarChanged interface. */ public void onSeekBarStopTrackingTouch(SeekBar seekBar, float prog) { - if (playbackService != null) { + if (playbackService != null && media != null) { playbackService.seekTo((int) (prog * media.getDuration())); setupPositionObserver(); } -- cgit v1.2.3 From c64217e2b485f3c6b997a55b1ef910c8b72779d3 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 26 Jun 2015 02:39:22 +0200 Subject: Add episode action fragment --- .../danoeh/antennapod/core/storage/DBWriter.java | 14 +++++++++--- core/src/main/res/values/strings.xml | 25 +++++++++++++++++++++- 2 files changed, 35 insertions(+), 4 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index feeee48c5..7d60746e1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -375,14 +375,21 @@ public class DBWriter { } + public static Future addQueueItem(final Context context, + final long... itemIds) { + return addQueueItem(context, false, itemIds); + } + + /** * Appends FeedItem objects to the end of the queue. The 'read'-attribute of all items will be set to true. * If a FeedItem is already in the queue, the FeedItem will not change its position in the queue. * * @param context A context that is used for opening a database connection. + * @param performAutoDownload true if an auto-download process should be started after the operation. * @param itemIds IDs of the FeedItem objects that should be added to the queue. */ - public static Future addQueueItem(final Context context, + public static Future addQueueItem(final Context context, final boolean performAutoDownload, final long... itemIds) { return dbExec.submit(new Runnable() { @@ -423,11 +430,12 @@ public class DBWriter { } } adapter.close(); - DBTasks.autodownloadUndownloadedItems(context); + if (performAutoDownload) { + DBTasks.autodownloadUndownloadedItems(context); + } } } }); - } /** diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 0f1830202..7ee026fa2 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -96,6 +96,7 @@ Removing Feed Refresh complete Feed Hide Episodes + Apply actions Unplayed Paused Played @@ -115,8 +116,8 @@ Remove Remove Episode Mark as played - Mark as unplayed Marked as played + Mark as unplayed Add to Queue Added to Queue Remove from Queue @@ -346,6 +347,7 @@ The import directory is empty. Select all Deselect all + Select ... From local filesystem Use external application OPML export @@ -450,4 +452,25 @@ Importing subscriptions from single-purpose apps… Search iTunes + + Select ... + All + Selected all Episodes + None + Deselected all Episodes + Played + Selected played Episodes + Unplayed + Selected unplayed Episodes + Downloaded + Selected downloaded Episodes + Unplayed + Selected not downloaded Episodes + Sort by ... + Title (A \u2192 Z) + Title (Z \u2192 A) + Date (New \u2192 Old) + Date (Old \u2192 New) + Duration (Short \u2192 Long) + Duration (Long \u2192 Short) -- cgit v1.2.3 From 473444291f68c7f8a205712c1b51fad74b0b1420 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 27 Jun 2015 14:55:48 -0400 Subject: Folks weren't always getting the updated copy of the download list, now they are. fixes AntennaPod/AntennaPod#968 --- .../antennapod/core/asynctask/DownloadObserver.java | 15 +++++++++------ .../antennapod/core/service/download/DownloadService.java | 7 +++++++ 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java index a13130082..85b1f699f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java @@ -12,6 +12,7 @@ import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.service.download.DownloadService; import de.danoeh.antennapod.core.service.download.Downloader; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; @@ -85,15 +86,15 @@ public class DownloadObserver { if (downloadService == null) { connectToDownloadService(); } - callback.onContentChanged(); + if (downloadService != null) { + callback.onContentChanged(downloadService.getDownloads()); + } startRefresher(); } }; public interface Callback { - void onContentChanged(); - - void onDownloadDataAvailable(List downloaderList); + void onContentChanged(List downloaderList); } private void connectToDownloadService() { @@ -116,7 +117,7 @@ public class DownloadObserver { Log.d(TAG, "Connection to service established"); List downloaderList = downloadService.getDownloads(); if (downloaderList != null && !downloaderList.isEmpty()) { - callback.onDownloadDataAvailable(downloaderList); + callback.onContentChanged(downloaderList); startRefresher(); } } @@ -156,12 +157,14 @@ public class DownloadObserver { handler.post(new Runnable() { @Override public void run() { - callback.onContentChanged(); if (downloadService != null) { List downloaderList = downloadService.getDownloads(); + callback.onContentChanged(downloaderList); if (downloaderList == null || downloaderList.isEmpty()) { Thread.currentThread().interrupt(); } + } else { + callback.onContentChanged(new ArrayList()); } } }); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 1ad4a9d0d..238cad763 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -435,6 +435,7 @@ public class DownloadService extends Service { } else { Log.e(TAG, "Could not cancel download with url " + url); } + sendBroadcast(new Intent(ACTION_DOWNLOADS_CONTENT_CHANGED)); } else if (StringUtils.equals(intent.getAction(), ACTION_CANCEL_ALL_DOWNLOADS)) { for (Downloader d : downloads) { @@ -1246,6 +1247,12 @@ public class DownloadService extends Service { } public List getDownloads() { + if (downloads == null) { + // this is unusual, but it should be OK, we'll return + // an empty list to make it easy for people + return new ArrayList(); + } + // return a copy of downloads, but the copy doesn't need to be synchronized. synchronized (downloads) { return new ArrayList(downloads); -- cgit v1.2.3 From 957497d787e1268e09b629de42db8a689a3edd0e Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 27 Jun 2015 22:17:18 +0200 Subject: Enqueue and items in the currently display order, submit changes on bulk --- .../de/danoeh/antennapod/core/storage/DBWriter.java | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index 7d60746e1..2c403d9ca 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -603,16 +603,24 @@ public class DBWriter { adapter.close(); } - /** - * Sets the 'read'-attribute of a FeedItem to the specified value. + /* + * Sets the 'read'-attribute of all specified FeedItems * * @param context A context that is used for opening a database connection. - * @param itemId ID of the FeedItem * @param read New value of the 'read'-attribute + * @param itemIds IDs of the FeedItems. */ - public static Future markItemRead(final Context context, final long itemId, - final boolean read) { - return markItemRead(context, itemId, read, 0, false); + public static Future markItemRead(final Context context, final boolean read, final long... itemIds) { + return dbExec.submit(new Runnable() { + @Override + public void run() { + final PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + adapter.setFeedItemRead(read, itemIds); + adapter.close(); + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + } + }); } -- cgit v1.2.3 From 23e1594165f8d3d67f00d7076db237becd1b7c33 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 27 Jun 2015 17:05:19 -0400 Subject: need to handle cases where the download service is gone --- .../java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java index 85b1f699f..732fa2d27 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java @@ -88,6 +88,9 @@ public class DownloadObserver { } if (downloadService != null) { callback.onContentChanged(downloadService.getDownloads()); + } else { + // the service is gone, there are no more downloads. + callback.onContentChanged(new ArrayList()); } startRefresher(); } -- cgit v1.2.3 From c7256d8152cf062c8e608b87e62f645ef2c72642 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 28 Jun 2015 21:53:40 +0200 Subject: Fix enqueueing order, prevent NPEs --- core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java | 2 +- core/src/main/res/values/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index 2c403d9ca..e103007e3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -415,7 +415,7 @@ public class DBWriter { boolean addToFront = UserPreferences.enqueueAtFront(); if(addToFront){ - queue.add(0, item); + queue.add(0+i, item); } else { queue.add(item); } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 7ee026fa2..00d7ed1bd 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -464,7 +464,7 @@ Selected unplayed Episodes Downloaded Selected downloaded Episodes - Unplayed + Not downloaded Selected not downloaded Episodes Sort by ... Title (A \u2192 Z) -- cgit v1.2.3 From 5178de86810594342b283565584cbc21f0983a5d Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Tue, 23 Jun 2015 18:34:03 +0200 Subject: Make new explicit --- .../de/danoeh/antennapod/core/feed/FeedItem.java | 43 ++++++++---- .../antennapod/core/feed/FeedItemFilter.java | 4 +- .../de/danoeh/antennapod/core/feed/FeedMedia.java | 6 ++ .../core/service/download/DownloadService.java | 2 +- .../core/storage/APCleanupAlgorithm.java | 2 +- .../danoeh/antennapod/core/storage/DBReader.java | 19 +---- .../de/danoeh/antennapod/core/storage/DBTasks.java | 12 ++-- .../danoeh/antennapod/core/storage/DBWriter.java | 14 ++-- .../antennapod/core/storage/PodDBAdapter.java | 82 +++++++++------------- 9 files changed, 85 insertions(+), 99 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java index 1168c60e4..e93aea9ac 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java @@ -44,7 +44,11 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr private Feed feed; private long feedId; - private boolean read; + private int state; + public final static int NEW = -1; + public final static int UNPLAYED = 0; + public final static int PLAYED = 1; + private String paymentLink; private FlattrStatus flattrStatus; @@ -66,7 +70,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr private boolean autoDownload = true; public FeedItem() { - this.read = true; + this.state = UNPLAYED; this.flattrStatus = new FlattrStatus(); this.hasChapters = false; } @@ -75,7 +79,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr * This constructor is used by DBReader. * */ public FeedItem(long id, String title, String link, Date pubDate, String paymentLink, long feedId, - FlattrStatus flattrStatus, boolean hasChapters, FeedImage image, boolean read, + FlattrStatus flattrStatus, boolean hasChapters, FeedImage image, int state, String itemIdentifier, boolean autoDownload) { this.id = id; this.title = title; @@ -86,7 +90,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr this.flattrStatus = flattrStatus; this.hasChapters = hasChapters; this.image = image; - this.read = read; + this.state = state; this.itemIdentifier = itemIdentifier; this.autoDownload = autoDownload; } @@ -94,13 +98,13 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr /** * This constructor should be used for creating test objects. */ - public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, boolean read, Feed feed) { + public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, int state, Feed feed) { this.id = id; this.title = title; this.itemIdentifier = itemIdentifier; this.link = link; this.pubDate = (pubDate != null) ? (Date) pubDate.clone() : null; - this.read = read; + this.state = state; this.feed = feed; this.flattrStatus = new FlattrStatus(); this.hasChapters = false; @@ -109,13 +113,13 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr /** * This constructor should be used for creating test objects involving chapter marks. */ - public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, boolean read, Feed feed, boolean hasChapters) { + public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, int read, Feed feed, boolean hasChapters) { this.id = id; this.title = title; this.itemIdentifier = itemIdentifier; this.link = link; this.pubDate = (pubDate != null) ? (Date) pubDate.clone() : null; - this.read = read; + this.state = state; this.feed = feed; this.flattrStatus = new FlattrStatus(); this.hasChapters = hasChapters; @@ -238,12 +242,25 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr this.feed = feed; } - public boolean isRead() { - return read; + public boolean isNew() { + return state == NEW; + } + + + public void setNew() { + state = NEW; + } + + public boolean isPlayed() { + return state == PLAYED; } - public void setRead(boolean read) { - this.read = read; + public void setPlayed(boolean played) { + if(played) { + state = PLAYED; + } else { + state = UNPLAYED; + } } private boolean isInProgress() { @@ -342,7 +359,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr return State.IN_PROGRESS; } } - return (isRead() ? State.READ : State.UNREAD); + return (isPlayed() ? State.READ : State.UNREAD); } public long getFeedId() { diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java index 4ad084b39..2fd5666c8 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java @@ -61,9 +61,9 @@ public class FeedItemFilter { } List result = new ArrayList(); for(FeedItem item : items) { - if(hideUnplayed && false == item.isRead()) continue; + if(hideUnplayed && false == item.isPlayed()) continue; if(hidePaused && item.getState() == FeedItem.State.IN_PROGRESS) continue; - if(hidePlayed && item.isRead()) continue; + if(hidePlayed && item.isPlayed()) continue; boolean isQueued = DBReader.getQueueIDList(context).contains(item.getId()); if(hideQueued && isQueued) continue; if(hideNotQueued && false == isQueued) continue; diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index b4cca505c..bd5fc58b8 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -186,6 +186,9 @@ public class FeedMedia extends FeedFile implements Playable { public void setPosition(int position) { this.position = position; + if(position > 0) { + this.item.setPlayed(false); + } } public long getSize() { @@ -447,6 +450,9 @@ public class FeedMedia extends FeedFile implements Playable { @Override public void setDownloaded(boolean downloaded) { super.setDownloaded(downloaded); + if(downloaded) { + item.setPlayed(false); + } } @Override diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 238cad763..7fb878680 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -815,7 +815,7 @@ public class DownloadService extends Service { e.printStackTrace(); } } - if (!item.isRead() && item.hasMedia() && !item.getMedia().isDownloaded()) { + if (!item.isPlayed() && item.hasMedia() && !item.getMedia().isDownloaded()) { newMediaFiles.add(item.getMedia().getId()); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java index f647fd537..a07705e69 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java @@ -28,7 +28,7 @@ public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm { List delete; for (FeedItem item : downloadedItems) { if (item.hasMedia() && item.getMedia().isDownloaded() - && !queue.contains(item.getId()) && item.isRead()) { + && !queue.contains(item.getId()) && item.isPlayed()) { candidates.add(item); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 95c033dc5..0347c1b72 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -229,7 +229,7 @@ public final class DBReader { new FlattrStatus(itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_FLATTR_STATUS)), itemlistCursor.getInt(PodDBAdapter.IDX_FI_SMALL_HAS_CHAPTERS) > 0, image, - (itemlistCursor.getInt(PodDBAdapter.IDX_FI_SMALL_READ) > 0), + itemlistCursor.getInt(PodDBAdapter.IDX_FI_SMALL_READ), itemlistCursor.getString(PodDBAdapter.IDX_FI_SMALL_ITEM_IDENTIFIER), itemlistCursor.getInt(itemlistCursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DOWNLOAD)) > 0 ); @@ -481,8 +481,7 @@ public final class DBReader { * Loads a list of FeedItems whose 'read'-attribute is set to false. * * @param context A context that is used for opening a database connection. - * @return A list of FeedItems whose 'read'-attribute it set to false. If the FeedItems in the list are not used, - * consider using {@link #getUnreadItemIds(android.content.Context)} instead. + * @return A list of FeedItems whose 'read'-attribute it set to false. */ public static List getUnreadItemsList(Context context) { if (BuildConfig.DEBUG) @@ -1012,20 +1011,6 @@ public final class DBReader { return result; } - /** - * Returns a map containing the number of unread items per feed - * - * @param context A context that is used for opening a database connection. - * @return The number of unread items per feed. - */ - public static LongIntMap getNumberOfUnreadFeedItems(final Context context, long... feedIds) { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - final LongIntMap result = adapter.getNumberOfUnreadFeedItems(feedIds); - adapter.close(); - return result; - } - /** * Searches the DB for a FeedImage of the given id. * diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index 711cd773e..9273cf11e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -561,7 +561,7 @@ public final class DBTasks { // all new feeds will have the most recent item marked as unplayed FeedItem mostRecent = newFeed.getMostRecentItem(); if (mostRecent != null) { - mostRecent.setRead(false); + mostRecent.setNew(); } newFeedsList.add(newFeed); @@ -572,16 +572,16 @@ public final class DBTasks { Collections.sort(newFeed.getItems(), new FeedItemPubdateComparator()); - final boolean markNewItemsAsUnread; + final boolean markNewItems; if (newFeed.getPageNr() == savedFeed.getPageNr()) { if (savedFeed.compareWithOther(newFeed)) { Log.d(TAG, "Feed has updated attribute values. Updating old feed's attributes"); savedFeed.updateFromOther(newFeed); } - markNewItemsAsUnread = true; + markNewItems = true; } else { Log.d(TAG, "New feed has a higher page number. Merging without marking as unread"); - markNewItemsAsUnread = false; + markNewItems = false; savedFeed.setNextPageLink(newFeed.getNextPageLink()); } if (savedFeed.getPreferences().compareWithOther(newFeed.getPreferences())) { @@ -599,8 +599,8 @@ public final class DBTasks { item.setFeed(savedFeed); item.setAutoDownload(savedFeed.getPreferences().getAutoDownload()); savedFeed.getItems().add(i, item); - if (markNewItemsAsUnread) { - item.setRead(false); + if (markNewItems) { + item.setNew(); } } else { oldItem.updateFromOther(item); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index e103007e3..278d897b6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -16,7 +16,6 @@ import java.net.URLEncoder; import java.util.Collections; import java.util.Comparator; import java.util.Date; -import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; @@ -352,7 +351,7 @@ public class DBWriter { final PodDBAdapter adapter = new PodDBAdapter(context); adapter.open(); final List queue = DBReader.getQueue(context, adapter); - FeedItem item = null; + FeedItem item; if (queue != null) { if (!itemListContains(queue, itemId)) { @@ -403,23 +402,18 @@ public class DBWriter { if (queue != null) { boolean queueModified = false; - boolean unreadItemsModified = false; - List itemsToSave = new LinkedList(); for (int i = 0; i < itemIds.length; i++) { if (!itemListContains(queue, itemIds[i])) { - final FeedItem item = DBReader.getFeedItem( - context, itemIds[i]); + final FeedItem item = DBReader.getFeedItem(context, itemIds[i]); if (item != null) { // add item to either front ot back of queue boolean addToFront = UserPreferences.enqueueAtFront(); - if(addToFront){ queue.add(0+i, item); } else { queue.add(item); } - queueModified = true; } } @@ -677,7 +671,7 @@ public class DBWriter { itemCursor.moveToNext(); } itemCursor.close(); - adapter.setFeedItemRead(true, itemIds); + adapter.setFeedItemRead(FeedItem.PLAYED, itemIds); adapter.close(); EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); @@ -706,7 +700,7 @@ public class DBWriter { itemCursor.moveToNext(); } itemCursor.close(); - adapter.setFeedItemRead(true, itemIds); + adapter.setFeedItemRead(FeedItem.PLAYED, itemIds); adapter.close(); EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index ed3cb71e9..50df0f0a7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -742,7 +742,13 @@ public class PodDBAdapter { setFeed(item.getFeed()); } values.put(KEY_FEED, item.getFeed().getId()); - values.put(KEY_READ, item.isRead()); + if(item.isNew()) { + values.put(KEY_READ, FeedItem.NEW); + } else if(item.isPlayed()) { + values.put(KEY_READ, FeedItem.PLAYED); + } else { + values.put(KEY_READ, FeedItem.UNPLAYED); + } values.put(KEY_HAS_CHAPTERS, item.getChapters() != null || item.hasChapters()); values.put(KEY_ITEM_IDENTIFIER, item.getItemIdentifier()); values.put(KEY_FLATTR_STATUS, item.getFlattrStatus().toLong()); @@ -774,7 +780,7 @@ public class PodDBAdapter { db.beginTransaction(); ContentValues values = new ContentValues(); - values.put(KEY_READ, read); + values.put(KEY_READ, read ? FeedItem.PLAYED : FeedItem.UNPLAYED); db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?", new String[]{String.valueOf(itemId)}); if (resetMediaPosition) { @@ -787,7 +793,7 @@ public class PodDBAdapter { db.endTransaction(); } - public void setFeedItemRead(boolean read, long... itemIds) { + public void setFeedItemRead(int read, long... itemIds) { db.beginTransaction(); ContentValues values = new ContentValues(); for (long id : itemIds) { @@ -873,18 +879,23 @@ public class PodDBAdapter { public void setQueue(List queue) { ContentValues values = new ContentValues(); + long[] ids = new long[queue.size()]; db.beginTransaction(); db.delete(TABLE_NAME_QUEUE, null, null); for (int i = 0; i < queue.size(); i++) { FeedItem item = queue.get(i); + ids[i] = item.getId(); values.put(KEY_ID, i); values.put(KEY_FEEDITEM, item.getId()); values.put(KEY_FEED, item.getFeed().getId()); - db.insertWithOnConflict(TABLE_NAME_QUEUE, null, values, - SQLiteDatabase.CONFLICT_REPLACE); + db.insertWithOnConflict(TABLE_NAME_QUEUE, null, values, SQLiteDatabase.CONFLICT_REPLACE); } db.setTransactionSuccessful(); db.endTransaction(); + db.execSQL("UPDATE " + TABLE_NAME_FEED_ITEMS + + " SET " + KEY_READ + "=" + FeedItem.UNPLAYED + + " WHERE " + KEY_ID + " IN(" + TextUtils.join(",", Arrays.asList(ids)) + ")" + + " AND " + KEY_READ + "=" + FeedItem.NEW); } public void clearQueue() { @@ -1059,6 +1070,7 @@ public class PodDBAdapter { /** * Returns a cursor which contains all feed items in the queue. The returned * cursor uses the FEEDITEM_SEL_FI_SMALL selection. + * cursor uses the FEEDITEM_SEL_FI_SMALL selection. */ public final Cursor getQueueCursor() { Object[] args = (Object[]) new String[]{ @@ -1090,24 +1102,14 @@ public class PodDBAdapter { */ public final Cursor getUnreadItemsCursor() { Cursor c = db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL, KEY_READ - + "=0", null, null, null, KEY_PUBDATE + " DESC"); + + "<" + FeedItem.PLAYED, null, null, null, KEY_PUBDATE + " DESC"); return c; } public final Cursor getNewItemIdsCursor() { - final String query = "SELECT " + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + final String query = "SELECT " + KEY_ID + " FROM " + TABLE_NAME_FEED_ITEMS - + " INNER JOIN " + TABLE_NAME_FEED_MEDIA + " ON " - + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" - + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM - + " LEFT OUTER JOIN " + TABLE_NAME_QUEUE + " ON " - + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" - + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM - + " WHERE " - + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed - + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded - + TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played - + TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL"; // not in queue + + " WHERE " + KEY_READ + "=" + FeedItem.NEW; return db.rawQuery(query, null); } @@ -1116,18 +1118,9 @@ public class PodDBAdapter { * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection. */ public final Cursor getNewItemsCursor() { - final String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS - + " INNER JOIN " + TABLE_NAME_FEED_MEDIA + " ON " - + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" - + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM - + " LEFT OUTER JOIN " + TABLE_NAME_QUEUE + " ON " - + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" - + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM - + " WHERE " - + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed - + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded - + TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played - + TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL" // not in queue + final String query = "SELECT " + SEL_FI_SMALL_STR + + " FROM " + TABLE_NAME_FEED_ITEMS + + " WHERE " + KEY_READ + "=" + FeedItem.NEW + " ORDER BY " + KEY_PUBDATE + " DESC"; Cursor c = db.rawQuery(query, null); return c; @@ -1139,11 +1132,11 @@ public class PodDBAdapter { } public Cursor getDownloadedItemsCursor() { - final String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS - + " INNER JOIN " + TABLE_NAME_FEED_MEDIA + " ON " - + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" - + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + " WHERE " - + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + ">0"; + final String query = "SELECT " + SEL_FI_SMALL_STR + + " FROM " + TABLE_NAME_FEED_ITEMS + + " INNER JOIN " + TABLE_NAME_FEED_MEDIA + + " ON " + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + + " WHERE " + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + ">0"; Cursor c = db.rawQuery(query, null); return c; } @@ -1277,19 +1270,9 @@ public class PodDBAdapter { } public final int getNumberOfNewItems() { - final String query = "SELECT COUNT(" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + ")" - +" FROM " + TABLE_NAME_FEED_ITEMS - + " LEFT JOIN " + TABLE_NAME_FEED_MEDIA + " ON " - + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" - + TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM - + " LEFT JOIN " + TABLE_NAME_QUEUE + " ON " - + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" - + TABLE_NAME_QUEUE + "." + KEY_FEEDITEM - + " WHERE " - + TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed - + TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded - + TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played - + TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL"; // not in queue + final String query = "SELECT COUNT(" + KEY_ID + ")" + + " FROM " + TABLE_NAME_FEED_ITEMS + + " WHERE " + KEY_READ + "=" + FeedItem.NEW; Cursor c = db.rawQuery(query, null); int result = 0; if (c.moveToFirst()) { @@ -1315,7 +1298,8 @@ public class PodDBAdapter { final String query = "SELECT " + KEY_FEED + ", COUNT(" + KEY_ID + ") AS count " + " FROM " + TABLE_NAME_FEED_ITEMS + " WHERE " + KEY_FEED + " IN (" + builder.toString() + ") " - + " AND " + KEY_READ + " = 0" + + " AND (" + KEY_READ + "=" + FeedItem.NEW + + " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")" + " GROUP BY " + KEY_FEED; Cursor c = db.rawQuery(query, null); LongIntMap result = new LongIntMap(c.getCount()); -- cgit v1.2.3 From 5643933a51027e58c4381a3f06f3b7e8e9bc30fa Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Tue, 30 Jun 2015 00:04:06 +0200 Subject: Set subscription order and counter in the preferences --- .../core/preferences/UserPreferences.java | 18 ++++++++++++++++++ core/src/main/res/values/arrays.xml | 22 ++++++++++++++++++++++ core/src/main/res/values/strings.xml | 15 ++++++++++++++- 3 files changed, 54 insertions(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index d96d25fc2..573f01765 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -43,6 +43,8 @@ public class UserPreferences { // User Interface public static final String PREF_THEME = "prefTheme"; public static final String PREF_HIDDEN_DRAWER_ITEMS = "prefHiddenDrawerItems"; + public static final String PREF_DRAWER_FEED_ORDER = "prefDrawerFeedOrder"; + public static final String PREF_DRAWER_FEED_INDICATOR = "prefDrawerFeedIndicator"; public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify"; public static final String PREF_PERSISTENT_NOTIFICATION = "prefPersistNotify"; public static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport"; @@ -85,6 +87,12 @@ public class UserPreferences { // Constants private static int EPISODE_CACHE_SIZE_UNLIMITED = -1; + public static int ORDER_UNPLAYED_EPISODES = 0; + public static int ORDER_ALPHABETICAL = 1; + public static int SHOW_NEW_UNPLAYED_SUM = 0; + public static int SHOW_NEW = 1; + public static int SHOW_UNPLAYED = 2; + public static int SHOW_NONE= 3; private static Context context; private static SharedPreferences prefs; @@ -128,6 +136,16 @@ public class UserPreferences { return new ArrayList(Arrays.asList(StringUtils.split(hiddenItems, ','))); } + public static int getFeedOrder() { + String value = prefs.getString(PREF_DRAWER_FEED_ORDER, "0"); + return Integer.valueOf(value); + } + + public static int getFeedIndicator() { + String value = prefs.getString(PREF_DRAWER_FEED_INDICATOR, "0"); + return Integer.valueOf(value); + } + /** * Returns notification priority. * diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index afcb31078..82596e970 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -126,6 +126,28 @@ @string/add_feed_label + + @string/drawer_feed_order_unplayed_episodes + @string/drawer_feed_order_alphabetical + + + 0 + 1 + + + + @string/drawer_feed_indicator_new_unplayed + @string/drawer_feed_indicator_new + @string/drawer_feed_indicator_unplayed + @string/drawer_feed_indicator_none + + + 0 + 1 + 2 + 3 + + @string/hide_unplayed_episodes_label @string/hide_paused_episodes_label diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 00d7ed1bd..9cebfa26e 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -33,6 +33,12 @@ Open menu Close menu Drawer Preferences + Sort by counter + Sort alphabetically + Number of new and unplayed episodes + Number of new episodes + Number of unplayed episodes + None Open in Browser @@ -84,6 +90,7 @@ Marked all Episodes as played Please confirm that you want to mark all episodes as being played. Please confirm that you want to mark all episodes in this feed as being played. + Mark all as seen Show information Remove Podcast Share... @@ -279,8 +286,14 @@ Configure automatic flattring User Interface Select Theme - Change Navigation Drawer + Customize Navigation Drawer + Customize the appearance of the navigation drawer. + Set Navigation Drawer items Change which items appear in the navigation drawer. + Set Subscription Order + Change the order of your subscriptions + Set Subscription Counter + Change the information displayed by the subscription counter Change the appearance of AntennaPod. Automatic Download Configure the automatic download of episodes. -- cgit v1.2.3 From 936ecc2b8e7fc5a392ef8206fe773757821a8e95 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Tue, 30 Jun 2015 00:18:24 +0200 Subject: Nav drawer subscriptions context menu --- .../de/danoeh/antennapod/core/ClientConfig.java | 2 - .../danoeh/antennapod/core/StorageCallbacks.java | 27 --- .../java/de/danoeh/antennapod/core/feed/Feed.java | 19 +- .../core/storage/APSPCleanupAlgorithm.java | 139 ------------ .../core/storage/APSPDownloadAlgorithm.java | 72 ------- .../danoeh/antennapod/core/storage/DBReader.java | 60 ++++-- .../danoeh/antennapod/core/storage/DBWriter.java | 37 +++- .../antennapod/core/storage/PodDBAdapter.java | 232 +++++++++++++++++++-- 8 files changed, 306 insertions(+), 282 deletions(-) delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/StorageCallbacks.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java b/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java index 1a2671555..6619e706b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java +++ b/core/src/main/java/de/danoeh/antennapod/core/ClientConfig.java @@ -21,7 +21,5 @@ public class ClientConfig { public static FlattrCallbacks flattrCallbacks; - public static StorageCallbacks storageCallbacks; - public static DBTasksCallbacks dbTasksCallbacks; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/StorageCallbacks.java b/core/src/main/java/de/danoeh/antennapod/core/StorageCallbacks.java deleted file mode 100644 index 5d1a0fffc..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/StorageCallbacks.java +++ /dev/null @@ -1,27 +0,0 @@ -package de.danoeh.antennapod.core; - -import android.database.sqlite.SQLiteDatabase; - -/** - * Callbacks for the classes in the storage package of the core module. - */ -public interface StorageCallbacks { - - /** - * Returns the current version of the database. - * - * @return The non-negative version number of the database. - */ - public int getDatabaseVersion(); - - /** - * Upgrades the given database from an old version to a newer version. - * - * @param db The database that is supposed to be upgraded. - * @param oldVersion The old version of the database. - * @param newVersion The version that the database is supposed to be upgraded to. - */ - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion); - - -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java index 29ba721fe..25b3a9ae6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java @@ -177,10 +177,21 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource */ public boolean hasNewItems() { for (FeedItem item : items) { - if (item.getState() == FeedItem.State.UNREAD) { - if (item.getMedia() != null) { - return true; - } + if (item.isNew()) { + return true; + } + } + return false; + } + + /** + * Returns true if at least one item in the itemlist is unread. + * + */ + public boolean hasUnplayedItems() { + for (FeedItem item : items) { + if (false == item.isNew() && false == item.isPlayed()) { + return true; } } return false; diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java deleted file mode 100644 index 420bbc09d..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APSPCleanupAlgorithm.java +++ /dev/null @@ -1,139 +0,0 @@ -package de.danoeh.antennapod.core.storage; - -import android.content.Context; -import android.util.Log; - -import org.apache.commons.io.FileUtils; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.ExecutionException; - -import de.danoeh.antennapod.core.feed.FeedItem; - -/** - * Implementation of the EpisodeCleanupAlgorithm interface used by AntennaPodSP apps. - */ -public class APSPCleanupAlgorithm implements EpisodeCleanupAlgorithm { - private static final String TAG = "APSPCleanupAlgorithm"; - - final int numberOfNewAutomaticallyDownloadedEpisodes; - - public APSPCleanupAlgorithm(int numberOfNewAutomaticallyDownloadedEpisodes) { - this.numberOfNewAutomaticallyDownloadedEpisodes = numberOfNewAutomaticallyDownloadedEpisodes; - } - - /** - * Performs an automatic cleanup. Episodes that have been downloaded first will also be deleted first. - * The episode that is currently playing as well as the n most recent episodes (the exact value is determined - * by AppPreferences.numberOfNewAutomaticallyDownloadedEpisodes) will never be deleted. - * - * @param context - * @param episodeSize The maximum amount of space that should be freed by this method - * @return The number of episodes that have been deleted - */ - @Override - public int performCleanup(Context context, Integer episodeSize) { - Log.i(TAG, String.format("performAutoCleanup(%d)", episodeSize)); - if (episodeSize <= 0) { - return 0; - } - - List candidates = getAutoCleanupCandidates(context); - List deleteList = new ArrayList(); - long deletedEpisodesSize = 0; - Collections.sort(candidates, new Comparator() { - @Override - public int compare(FeedItem lhs, FeedItem rhs) { - File lFile = new File(lhs.getMedia().getFile_url()); - File rFile = new File(rhs.getMedia().getFile_url()); - if (!lFile.exists() || !rFile.exists()) { - return 0; - } - if (FileUtils.isFileOlder(lFile, rFile)) { - return -1; - } else { - return 1; - } - } - }); - // listened episodes will be deleted first - Iterator it = candidates.iterator(); - if (it.hasNext()) { - for (FeedItem i = it.next(); it.hasNext() && deletedEpisodesSize <= episodeSize; i = it.next()) { - if (!i.getMedia().isPlaying() && i.getMedia().getPlaybackCompletionDate() != null) { - it.remove(); - deleteList.add(i); - deletedEpisodesSize += i.getMedia().getSize(); - } - } - } - - // delete unlistened old episodes if necessary - it = candidates.iterator(); - if (it.hasNext()) { - for (FeedItem i = it.next(); it.hasNext() && deletedEpisodesSize <= episodeSize; i = it.next()) { - if (!i.getMedia().isPlaying()) { - it.remove(); - deleteList.add(i); - deletedEpisodesSize += i.getMedia().getSize(); - } - } - } - for (FeedItem item : deleteList) { - try { - DBWriter.deleteFeedMediaOfItem(context, item.getMedia().getId()).get(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } - } - Log.i(TAG, String.format("performAutoCleanup(%d) deleted %d episodes and freed %d bytes of memory", - episodeSize, deleteList.size(), deletedEpisodesSize)); - return deleteList.size(); - } - - @Override - public Integer getDefaultCleanupParameter(Context context) { - return 0; - } - - @Override - public Integer getPerformCleanupParameter(Context context, List items) { - int episodeSize = 0; - for (FeedItem item : items) { - if (item.hasMedia() && !item.getMedia().isDownloaded()) { - episodeSize += item.getMedia().getSize(); - } - } - return episodeSize; - } - - /** - * Returns list of FeedItems that have been downloaded, but are not one of the - * [numberOfNewAutomaticallyDownloadedEpisodes] most recent items. - */ - private List getAutoCleanupCandidates(Context context) { - List downloaded = new ArrayList(DBReader.getDownloadedItems(context)); - List recent = new ArrayList(DBReader.getRecentlyPublishedEpisodes(context, - numberOfNewAutomaticallyDownloadedEpisodes)); - for (FeedItem r : recent) { - if (r.hasMedia() && r.getMedia().isDownloaded()) { - for (int i = 0; i < downloaded.size(); i++) { - if (downloaded.get(i).getId() == r.getId()) { - downloaded.remove(i); - break; - } - } - } - } - - return downloaded; - - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java deleted file mode 100644 index f760ec0ce..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APSPDownloadAlgorithm.java +++ /dev/null @@ -1,72 +0,0 @@ -package de.danoeh.antennapod.core.storage; - -import android.content.Context; -import android.util.Log; - -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; - -import de.danoeh.antennapod.core.BuildConfig; -import de.danoeh.antennapod.core.feed.FeedItem; -import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.util.NetworkUtils; - -/** - * Implements the automatic download algorithm used by AntennaPodSP apps. - */ -public class APSPDownloadAlgorithm implements AutomaticDownloadAlgorithm { - private static final String TAG = "APSPDownloadAlgorithm"; - - private final int numberOfNewAutomaticallyDownloadedEpisodes; - - public APSPDownloadAlgorithm(int numberOfNewAutomaticallyDownloadedEpisodes) { - this.numberOfNewAutomaticallyDownloadedEpisodes = numberOfNewAutomaticallyDownloadedEpisodes; - } - - /** - * Downloads the most recent episodes automatically. The exact number of - * episodes that will be downloaded can be set in the AppPreferences. - * - * @param context Used for accessing the DB. - * @return A Runnable that will be submitted to an ExecutorService. - */ - @Override - public Runnable autoDownloadUndownloadedItems(final Context context, final long... mediaIds) { - return new Runnable() { - @Override - public void run() { - if (BuildConfig.DEBUG) - Log.d(TAG, "Performing auto-dl of undownloaded episodes"); - if (NetworkUtils.autodownloadNetworkAvailable(context) - && UserPreferences.isEnableAutodownload()) { - - Arrays.sort(mediaIds); - List itemsToDownload = DBReader.getRecentlyPublishedEpisodes(context, - numberOfNewAutomaticallyDownloadedEpisodes); - Iterator it = itemsToDownload.iterator(); - - for (FeedItem item = it.next(); it.hasNext(); item = it.next()) { - if (!item.hasMedia() - || item.getMedia().isDownloaded() - || Arrays.binarySearch(mediaIds, item.getMedia().getId()) < 0) { - it.remove(); - } - } - if (BuildConfig.DEBUG) - Log.d(TAG, "Enqueueing " + itemsToDownload.size() - + " items for automatic download"); - if (!itemsToDownload.isEmpty()) { - try { - DBTasks.downloadFeedItems(false, context, - itemsToDownload.toArray(new FeedItem[itemsToDownload - .size()])); - } catch (DownloadRequestException e) { - e.printStackTrace(); - } - } - } - } - }; - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 0347c1b72..3b33c28df 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -22,6 +22,7 @@ import de.danoeh.antennapod.core.feed.FeedPreferences; import de.danoeh.antennapod.core.feed.ID3Chapter; import de.danoeh.antennapod.core.feed.SimpleChapter; import de.danoeh.antennapod.core.feed.VorbisCommentChapter; +import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.util.DownloadError; import de.danoeh.antennapod.core.util.LongIntMap; @@ -1139,27 +1140,42 @@ public final class DBReader { for(int i=0; i < feeds.size(); i++) { feedIds[i] = feeds.get(i).getId(); } - final LongIntMap numUnreadFeedItems = adapter.getNumberOfUnreadFeedItems(feedIds); - Collections.sort(feeds, new Comparator() { - @Override - public int compare(Feed lhs, Feed rhs) { - long numUnreadLhs = numUnreadFeedItems.get(lhs.getId()); - Log.d(TAG, "feed with id " + lhs.getId() + " has " + numUnreadLhs + " unread items"); - long numUnreadRhs = numUnreadFeedItems.get(rhs.getId()); - Log.d(TAG, "feed with id " + rhs.getId() + " has " + numUnreadRhs + " unread items"); - if(numUnreadLhs > numUnreadRhs) { - // reverse natural order: podcast with most unplayed episodes first - return -1; - } else if(numUnreadLhs == numUnreadRhs) { + final LongIntMap feedCounters = adapter.getFeedCounters(feedIds); + + Comparator comparator; + int feedOrder = UserPreferences.getFeedOrder(); + if(feedOrder == UserPreferences.ORDER_UNPLAYED_EPISODES) { + comparator = new Comparator() { + @Override + public int compare(Feed lhs, Feed rhs) { + long counterLhs = feedCounters.get(lhs.getId()); + long counterRhs = feedCounters.get(rhs.getId()); + if(counterLhs > counterRhs) { + // reverse natural order: podcast with most unplayed episodes first + return -1; + } else if(counterLhs == counterRhs) { + return lhs.getTitle().compareTo(rhs.getTitle()); + } else { + return 1; + } + } + }; + } else { + comparator = new Comparator() { + @Override + public int compare(Feed lhs, Feed rhs) { + if(lhs.getTitle() == null) { + return 1; + } return lhs.getTitle().compareTo(rhs.getTitle()); - } else { - return 1; } - } - }); + }; + } + + Collections.sort(feeds, comparator); int queueSize = adapter.getQueueSize(); int numNewItems = adapter.getNumberOfNewItems(); - NavDrawerData result = new NavDrawerData(feeds, queueSize, numNewItems, numUnreadFeedItems); + NavDrawerData result = new NavDrawerData(feeds, queueSize, numNewItems, feedCounters); adapter.close(); return result; } @@ -1168,14 +1184,16 @@ public final class DBReader { public List feeds; public int queueSize; public int numNewItems; - public LongIntMap numUnreadFeedItems; + public LongIntMap feedCounters; - public NavDrawerData(List feeds, int queueSize, int numNewItems, - LongIntMap numUnreadFeedItems) { + public NavDrawerData(List feeds, + int queueSize, + int numNewItems, + LongIntMap feedIndicatorValues) { this.feeds = feeds; this.queueSize = queueSize; this.numNewItems = numNewItems; - this.numUnreadFeedItems = numUnreadFeedItems; + this.feedCounters = feedIndicatorValues; } } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index 278d897b6..d0da0b194 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -409,8 +409,8 @@ public class DBWriter { if (item != null) { // add item to either front ot back of queue boolean addToFront = UserPreferences.enqueueAtFront(); - if(addToFront){ - queue.add(0+i, item); + if (addToFront) { + queue.add(0 + i, item); } else { queue.add(item); } @@ -610,7 +610,8 @@ public class DBWriter { public void run() { final PodDBAdapter adapter = new PodDBAdapter(context); adapter.open(); - adapter.setFeedItemRead(read, itemIds); + int played = read ? FeedItem.PLAYED : FeedItem.UNPLAYED; + adapter.setFeedItemRead(played, itemIds); adapter.close(); EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); } @@ -650,6 +651,35 @@ public class DBWriter { }); } + /** + * Sets the 'read'-attribute of all FeedItems of a specific Feed to true. + * + * @param context A context that is used for opening a database connection. + * @param feedId ID of the Feed. + */ + public static Future markFeedSeen(final Context context, final long feedId) { + return dbExec.submit(new Runnable() { + + @Override + public void run() { + final PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + Cursor itemCursor = adapter.getNewItemsIdsCursor(feedId); + long[] ids = new long[itemCursor.getCount()]; + itemCursor.moveToFirst(); + for (int i = 0; i < ids.length; i++) { + ids[i] = itemCursor.getLong(0); + itemCursor.moveToNext(); + } + itemCursor.close(); + adapter.setFeedItemRead(FeedItem.UNPLAYED, ids); + adapter.close(); + + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + } + }); + } + /** * Sets the 'read'-attribute of all FeedItems of a specific Feed to true. * @@ -677,7 +707,6 @@ public class DBWriter { EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); } }); - } /** diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 50df0f0a7..c3466c621 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -9,6 +9,7 @@ import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; +import android.media.MediaMetadataRetriever; import android.text.TextUtils; import android.util.Log; @@ -18,7 +19,6 @@ import java.util.Arrays; import java.util.List; import de.danoeh.antennapod.core.BuildConfig; -import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.event.ProgressEvent; import de.danoeh.antennapod.core.feed.Chapter; @@ -28,13 +28,12 @@ import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.FeedPreferences; +import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.util.LongIntMap; import de.danoeh.antennapod.core.util.flattr.FlattrStatus; import de.greenrobot.event.EventBus; -; - // TODO Remove media column from feeditem table /** @@ -369,8 +368,7 @@ public class PodDBAdapter { private static synchronized PodDBHelper getDbHelperSingleton(Context appContext) { if (dbHelperSingleton == null) { - dbHelperSingleton = new PodDBHelper(appContext, DATABASE_NAME, null, - ClientConfig.storageCallbacks.getDatabaseVersion()); + dbHelperSingleton = new PodDBHelper(appContext, DATABASE_NAME, null); } return dbHelperSingleton; } @@ -1113,6 +1111,20 @@ public class PodDBAdapter { return db.rawQuery(query, null); } + /** + * Returns a cursor which contains all items of a feed that are considered new. + * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection. + */ + public final Cursor getNewItemsIdsCursor(long feedId) { + final String query = "SELECT " + KEY_ID + + " FROM " + TABLE_NAME_FEED_ITEMS + + " WHERE " + KEY_FEED + "=" + feedId + + " AND " + KEY_READ + "=" + FeedItem.NEW + + " ORDER BY " + KEY_PUBDATE + " DESC"; + Cursor c = db.rawQuery(query, null); + return c; + } + /** * Returns a cursor which contains all feed items that are considered new. * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection. @@ -1282,7 +1294,20 @@ public class PodDBAdapter { return result; } - public final LongIntMap getNumberOfUnreadFeedItems(long... feedIds) { + public final LongIntMap getFeedCounters(long... feedIds) { + int indicator = UserPreferences.getFeedIndicator(); + String whereRead; + if(indicator == UserPreferences.SHOW_NEW_UNPLAYED_SUM) { + whereRead = "(" + KEY_READ + "=" + FeedItem.NEW + + " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")"; + } else if(indicator == UserPreferences.SHOW_NEW) { + whereRead = KEY_READ + "=" + FeedItem.NEW; + } else if(indicator == UserPreferences.SHOW_UNPLAYED) { + whereRead = KEY_READ + "=" + FeedItem.UNPLAYED; + } else { + return new LongIntMap(0); + } + // work around TextUtils.join wanting only boxed items // and StringUtils.join() causing NoSuchMethodErrors on MIUI StringBuilder builder = new StringBuilder(); @@ -1298,9 +1323,8 @@ public class PodDBAdapter { final String query = "SELECT " + KEY_FEED + ", COUNT(" + KEY_ID + ") AS count " + " FROM " + TABLE_NAME_FEED_ITEMS + " WHERE " + KEY_FEED + " IN (" + builder.toString() + ") " - + " AND (" + KEY_READ + "=" + FeedItem.NEW - + " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")" - + " GROUP BY " + KEY_FEED; + + " AND " + whereRead + " GROUP BY " + KEY_FEED; + Cursor c = db.rawQuery(query, null); LongIntMap result = new LongIntMap(c.getCount()); if (c.moveToFirst()) { @@ -1454,6 +1478,8 @@ public class PodDBAdapter { */ private static class PodDBHelper extends SQLiteOpenHelper { + private final static int VERSION = 17; + private Context context; /** @@ -1462,11 +1488,10 @@ public class PodDBAdapter { * @param context Context to use * @param name Name of the database * @param factory to use for creating cursor objects - * @param version number of the database */ public PodDBHelper(final Context context, final String name, - final CursorFactory factory, final int version) { - super(context, name, factory, version); + final CursorFactory factory) { + super(context, name, factory, VERSION); this.context = context; } @@ -1492,7 +1517,188 @@ public class PodDBAdapter { public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) { EventBus.getDefault().post(ProgressEvent.start(context.getString(R.string.progress_upgrading_database))); - ClientConfig.storageCallbacks.onUpgrade(db, oldVersion, newVersion); + Log.w("DBAdapter", "Upgrading from version " + oldVersion + " to " + + newVersion + "."); + if (oldVersion <= 1) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " + + KEY_TYPE + " TEXT"); + } + if (oldVersion <= 2) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS + + " ADD COLUMN " + KEY_LINK + " TEXT"); + } + if (oldVersion <= 3) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + + " ADD COLUMN " + KEY_ITEM_IDENTIFIER + " TEXT"); + } + if (oldVersion <= 4) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " + + KEY_FEED_IDENTIFIER + " TEXT"); + } + if (oldVersion <= 5) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG + + " ADD COLUMN " + KEY_REASON_DETAILED + " TEXT"); + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_DOWNLOAD_LOG + + " ADD COLUMN " + KEY_DOWNLOADSTATUS_TITLE + " TEXT"); + } + if (oldVersion <= 6) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS + + " ADD COLUMN " + KEY_CHAPTER_TYPE + " INTEGER"); + } + if (oldVersion <= 7) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " ADD COLUMN " + KEY_PLAYBACK_COMPLETION_DATE + + " INTEGER"); + } + if (oldVersion <= 8) { + final int KEY_ID_POSITION = 0; + final int KEY_MEDIA_POSITION = 1; + + // Add feeditem column to feedmedia table + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " ADD COLUMN " + KEY_FEEDITEM + + " INTEGER"); + Cursor feeditemCursor = db.query(PodDBAdapter.TABLE_NAME_FEED_ITEMS, + new String[]{KEY_ID, KEY_MEDIA}, "? > 0", + new String[]{KEY_MEDIA}, null, null, null); + if (feeditemCursor.moveToFirst()) { + db.beginTransaction(); + ContentValues contentValues = new ContentValues(); + do { + long mediaId = feeditemCursor.getLong(KEY_MEDIA_POSITION); + contentValues.put(KEY_FEEDITEM, feeditemCursor.getLong(KEY_ID_POSITION)); + db.update(PodDBAdapter.TABLE_NAME_FEED_MEDIA, contentValues, KEY_ID + "=?", new String[]{String.valueOf(mediaId)}); + contentValues.clear(); + } while (feeditemCursor.moveToNext()); + db.setTransactionSuccessful(); + db.endTransaction(); + } + feeditemCursor.close(); + } + if (oldVersion <= 9) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + KEY_AUTO_DOWNLOAD + + " INTEGER DEFAULT 1"); + } + if (oldVersion <= 10) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + KEY_FLATTR_STATUS + + " INTEGER"); + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + + " ADD COLUMN " + KEY_FLATTR_STATUS + + " INTEGER"); + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " ADD COLUMN " + KEY_PLAYED_DURATION + + " INTEGER"); + } + if (oldVersion <= 11) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + KEY_USERNAME + + " TEXT"); + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + KEY_PASSWORD + + " TEXT"); + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + + " ADD COLUMN " + KEY_IMAGE + + " INTEGER"); + } + if (oldVersion <= 12) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + KEY_IS_PAGED + " INTEGER DEFAULT 0"); + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + KEY_NEXT_PAGE_LINK + " TEXT"); + } + if (oldVersion <= 13) { + // remove duplicate rows in "Chapters" table that were created because of a bug. + db.execSQL(String.format("DELETE FROM %s WHERE %s NOT IN " + + "(SELECT MIN(%s) as %s FROM %s GROUP BY %s,%s,%s,%s,%s)", + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS, + KEY_ID, + KEY_ID, + KEY_ID, + PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS, + KEY_TITLE, + KEY_START, + KEY_FEEDITEM, + KEY_LINK, + KEY_CHAPTER_TYPE)); + } + if(oldVersion <= 14) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + + " ADD COLUMN " + KEY_AUTO_DOWNLOAD + " INTEGER"); + db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + + " SET " + KEY_AUTO_DOWNLOAD + " = " + + "(SELECT " + KEY_AUTO_DOWNLOAD + + " FROM " + PodDBAdapter.TABLE_NAME_FEEDS + + " WHERE " + PodDBAdapter.TABLE_NAME_FEEDS + "." + KEY_ID + + " = " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_FEED + ")"); + + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + KEY_HIDE + " TEXT"); + + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0"); + + // create indexes + db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_FEED); + db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDITEMS_IMAGE); + db.execSQL(PodDBAdapter.CREATE_INDEX_FEEDMEDIA_FEEDITEM); + db.execSQL(PodDBAdapter.CREATE_INDEX_QUEUE_FEEDITEM); + db.execSQL(PodDBAdapter.CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM); + } + if(oldVersion <= 15) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " ADD COLUMN " + KEY_HAS_EMBEDDED_PICTURE + " INTEGER DEFAULT -1"); + db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " SET " + KEY_HAS_EMBEDDED_PICTURE + "=0" + + " WHERE " + KEY_DOWNLOADED + "=0"); + Cursor c = db.rawQuery("SELECT " + KEY_FILE_URL + + " FROM " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " WHERE " + KEY_DOWNLOADED + "=1 " + + " AND " + KEY_HAS_EMBEDDED_PICTURE + "=-1", null); + if(c.moveToFirst()) { + MediaMetadataRetriever mmr = new MediaMetadataRetriever(); + do { + String fileUrl = c.getString(0); + try { + mmr.setDataSource(fileUrl); + byte[] image = mmr.getEmbeddedPicture(); + if (image != null) { + db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " SET " + KEY_HAS_EMBEDDED_PICTURE + "=1" + + " WHERE " + KEY_FILE_URL + "='"+ fileUrl + "'"); + } else { + db.execSQL("UPDATE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " SET " + KEY_HAS_EMBEDDED_PICTURE + "=0" + + " WHERE " + KEY_FILE_URL + "='"+ fileUrl + "'"); + } + } catch(Exception e) { + e.printStackTrace(); + } + } while(c.moveToNext()); + } + c.close(); + } + if(oldVersion <= 16) { + String selectNew = "SELECT " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID + + " FROM " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + + " INNER JOIN " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + " ON " + + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" + + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_FEEDITEM + + " LEFT OUTER JOIN " + PodDBAdapter.TABLE_NAME_QUEUE + " ON " + + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" + + PodDBAdapter.TABLE_NAME_QUEUE + "." + KEY_FEEDITEM + + " WHERE " + + PodDBAdapter.TABLE_NAME_FEED_ITEMS + "." + KEY_READ + " = 0 AND " // unplayed + + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_DOWNLOADED + " = 0 AND " // undownloaded + + PodDBAdapter.TABLE_NAME_FEED_MEDIA + "." + KEY_POSITION + " = 0 AND " // not partially played + + PodDBAdapter.TABLE_NAME_QUEUE + "." + KEY_ID + " IS NULL"; // not in queue + String sql = "UPDATE " + PodDBAdapter.TABLE_NAME_FEED_ITEMS + + " SET " + KEY_READ + "=" + FeedItem.NEW + + " WHERE " + KEY_ID + " IN (" + selectNew + ")"; + Log.d("Migration", "SQL: " + sql); + db.execSQL(sql); + } EventBus.getDefault().post(ProgressEvent.end()); } } -- cgit v1.2.3 From dd898d1abe25853fedf16f1b955229671eda6ae6 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 2 Jul 2015 17:21:51 +0200 Subject: Call former indicator "counter" --- .../java/de/danoeh/antennapod/core/feed/FeedMedia.java | 6 ++++-- .../antennapod/core/preferences/UserPreferences.java | 18 +++++++++--------- .../de/danoeh/antennapod/core/storage/DBReader.java | 2 +- .../de/danoeh/antennapod/core/storage/DBWriter.java | 17 ++++++++++++++--- .../danoeh/antennapod/core/storage/PodDBAdapter.java | 8 ++++---- core/src/main/res/values/arrays.xml | 12 ++++++------ core/src/main/res/values/strings.xml | 12 ++++++------ 7 files changed, 44 insertions(+), 31 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index bd5fc58b8..302e4e2dd 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -368,14 +368,16 @@ public class FeedMedia extends FeedFile implements Playable { @Override public void saveCurrentPosition(SharedPreferences pref, int newPosition) { - setPosition(newPosition); DBWriter.setFeedMediaPlaybackInformation(ClientConfig.applicationCallbacks.getApplicationInstance(), this); + if(item.isNew()) { + DBWriter.markItemRead(ClientConfig.applicationCallbacks.getApplicationInstance(), false, item.getId()); + } + setPosition(newPosition); } @Override public void onPlaybackStart() { } - @Override public void onPlaybackCompleted() { diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index 573f01765..c9bfe2153 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -44,7 +44,7 @@ public class UserPreferences { public static final String PREF_THEME = "prefTheme"; public static final String PREF_HIDDEN_DRAWER_ITEMS = "prefHiddenDrawerItems"; public static final String PREF_DRAWER_FEED_ORDER = "prefDrawerFeedOrder"; - public static final String PREF_DRAWER_FEED_INDICATOR = "prefDrawerFeedIndicator"; + public static final String PREF_DRAWER_FEED_COUNTER = "prefDrawerFeedCounter"; public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify"; public static final String PREF_PERSISTENT_NOTIFICATION = "prefPersistNotify"; public static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport"; @@ -87,12 +87,12 @@ public class UserPreferences { // Constants private static int EPISODE_CACHE_SIZE_UNLIMITED = -1; - public static int ORDER_UNPLAYED_EPISODES = 0; - public static int ORDER_ALPHABETICAL = 1; - public static int SHOW_NEW_UNPLAYED_SUM = 0; - public static int SHOW_NEW = 1; - public static int SHOW_UNPLAYED = 2; - public static int SHOW_NONE= 3; + public static int FEED_ORDER_UNPLAYED_EPISODES = 0; + public static int FEED_ORDER_ALPHABETICAL = 1; + public static int FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM = 0; + public static int FEED_COUNTER_SHOW_NEW = 1; + public static int FEED_COUNTER_SHOW_UNPLAYED = 2; + public static int FEED_COUNTER_SHOW_NONE = 3; private static Context context; private static SharedPreferences prefs; @@ -141,8 +141,8 @@ public class UserPreferences { return Integer.valueOf(value); } - public static int getFeedIndicator() { - String value = prefs.getString(PREF_DRAWER_FEED_INDICATOR, "0"); + public static int getFeedCounter() { + String value = prefs.getString(PREF_DRAWER_FEED_COUNTER, "0"); return Integer.valueOf(value); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 3b33c28df..93aec54c8 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -1144,7 +1144,7 @@ public final class DBReader { Comparator comparator; int feedOrder = UserPreferences.getFeedOrder(); - if(feedOrder == UserPreferences.ORDER_UNPLAYED_EPISODES) { + if(feedOrder == UserPreferences.FEED_ORDER_UNPLAYED_EPISODES) { comparator = new Comparator() { @Override public int compare(Feed lhs, Feed rhs) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index d0da0b194..216d1bde2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -360,6 +360,10 @@ public class DBWriter { queue.add(index, item); adapter.setQueue(queue); EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED, item, index)); + if(item.isNew()) { + adapter.setFeedItemRead(FeedItem.UNPLAYED, item.getId()); + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + } } } } @@ -379,7 +383,6 @@ public class DBWriter { return addQueueItem(context, false, itemIds); } - /** * Appends FeedItem objects to the end of the queue. The 'read'-attribute of all items will be set to true. * If a FeedItem is already in the queue, the FeedItem will not change its position in the queue. @@ -397,11 +400,11 @@ public class DBWriter { if (itemIds.length > 0) { final PodDBAdapter adapter = new PodDBAdapter(context); adapter.open(); - final List queue = DBReader.getQueue(context, - adapter); + final List queue = DBReader.getQueue(context, adapter); if (queue != null) { boolean queueModified = false; + LongList markAsUnplayedIds = new LongList(); for (int i = 0; i < itemIds.length; i++) { if (!itemListContains(queue, itemIds[i])) { final FeedItem item = DBReader.getFeedItem(context, itemIds[i]); @@ -415,12 +418,20 @@ public class DBWriter { queue.add(item); } queueModified = true; + if(item.isNew()) { + markAsUnplayedIds.add(item.getId()); + } } } } if (queueModified) { adapter.setQueue(queue); EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED_ITEMS, queue)); + Log.d(TAG, "# mark as unplayed: " + markAsUnplayedIds.size()); + if(markAsUnplayedIds.size() > 0) { + adapter.setFeedItemRead(FeedItem.UNPLAYED, markAsUnplayedIds.toArray()); + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + } } } adapter.close(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index c3466c621..91a8e2ed0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -1295,14 +1295,14 @@ public class PodDBAdapter { } public final LongIntMap getFeedCounters(long... feedIds) { - int indicator = UserPreferences.getFeedIndicator(); + int counter = UserPreferences.getFeedCounter(); String whereRead; - if(indicator == UserPreferences.SHOW_NEW_UNPLAYED_SUM) { + if(counter == UserPreferences.FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM) { whereRead = "(" + KEY_READ + "=" + FeedItem.NEW + " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")"; - } else if(indicator == UserPreferences.SHOW_NEW) { + } else if(counter == UserPreferences.FEED_COUNTER_SHOW_NEW) { whereRead = KEY_READ + "=" + FeedItem.NEW; - } else if(indicator == UserPreferences.SHOW_UNPLAYED) { + } else if(counter == UserPreferences.FEED_COUNTER_SHOW_UNPLAYED) { whereRead = KEY_READ + "=" + FeedItem.UNPLAYED; } else { return new LongIntMap(0); diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 82596e970..5fe5f24e8 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -135,13 +135,13 @@ 1 - - @string/drawer_feed_indicator_new_unplayed - @string/drawer_feed_indicator_new - @string/drawer_feed_indicator_unplayed - @string/drawer_feed_indicator_none + + @string/drawer_feed_counter_new_unplayed + @string/drawer_feed_counter_new + @string/drawer_feed_counter_unplayed + @string/drawer_feed_counter_none - + 0 1 2 diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 9cebfa26e..d2c0844aa 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -35,10 +35,10 @@ Drawer Preferences Sort by counter Sort alphabetically - Number of new and unplayed episodes - Number of new episodes - Number of unplayed episodes - None + Number of new and unplayed episodes + Number of new episodes + Number of unplayed episodes + None Open in Browser @@ -292,8 +292,8 @@ Change which items appear in the navigation drawer. Set Subscription Order Change the order of your subscriptions - Set Subscription Counter - Change the information displayed by the subscription counter + Set Subscription Counter + Change the information displayed by the subscription counter Change the appearance of AntennaPod. Automatic Download Configure the automatic download of episodes. -- cgit v1.2.3 From 8538f7b9f29bfceaa3f2d29f6f4bd71f428188f9 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 2 Jul 2015 18:50:10 +0200 Subject: Fix DB problem --- core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java | 7 ++----- .../main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 4 ---- 2 files changed, 2 insertions(+), 9 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index 216d1bde2..d1f67cd29 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -361,8 +361,7 @@ public class DBWriter { adapter.setQueue(queue); EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED, item, index)); if(item.isNew()) { - adapter.setFeedItemRead(FeedItem.UNPLAYED, item.getId()); - EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + DBWriter.markItemRead(context, false, item.getId()); } } } @@ -427,10 +426,8 @@ public class DBWriter { if (queueModified) { adapter.setQueue(queue); EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED_ITEMS, queue)); - Log.d(TAG, "# mark as unplayed: " + markAsUnplayedIds.size()); if(markAsUnplayedIds.size() > 0) { - adapter.setFeedItemRead(FeedItem.UNPLAYED, markAsUnplayedIds.toArray()); - EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + DBWriter.markItemRead(context, false, markAsUnplayedIds.toArray()); } } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 91a8e2ed0..8f09ff3c2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -890,10 +890,6 @@ public class PodDBAdapter { } db.setTransactionSuccessful(); db.endTransaction(); - db.execSQL("UPDATE " + TABLE_NAME_FEED_ITEMS - + " SET " + KEY_READ + "=" + FeedItem.UNPLAYED - + " WHERE " + KEY_ID + " IN(" + TextUtils.join(",", Arrays.asList(ids)) + ")" - + " AND " + KEY_READ + "=" + FeedItem.NEW); } public void clearQueue() { -- cgit v1.2.3 From 6427a40da2406290bc854b25b0e0a9217b627dcb Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 2 Jul 2015 20:16:12 +0200 Subject: Fix tests --- core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java index e93aea9ac..96a6c2ba1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java @@ -113,7 +113,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr /** * This constructor should be used for creating test objects involving chapter marks. */ - public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, int read, Feed feed, boolean hasChapters) { + public FeedItem(long id, String title, String itemIdentifier, String link, Date pubDate, int state, Feed feed, boolean hasChapters) { this.id = id; this.title = title; this.itemIdentifier = itemIdentifier; -- cgit v1.2.3 From bcff6277f2c3a82ee0a934fd2b985227a00ba224 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 4 Jul 2015 15:38:16 +0200 Subject: Tell Queue fragment to refresh --- .../main/java/de/danoeh/antennapod/core/feed/QueueEvent.java | 2 +- .../main/java/de/danoeh/antennapod/core/storage/DBWriter.java | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java b/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java index c8497f509..97d086e5b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java @@ -8,7 +8,7 @@ import java.util.List; public class QueueEvent { public enum Action { - ADDED, ADDED_ITEMS, REMOVED, CLEARED, DELETED_MEDIA, SORTED, MOVED + ADDED, ADDED_ITEMS, REMOVED, IRREVERSIBLE_REMOVED, CLEARED, DELETED_MEDIA, SORTED, MOVED } public final Action action; diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index d1f67cd29..acdcf5f85 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -13,6 +13,7 @@ import org.shredzone.flattr4j.model.Flattr; import java.io.File; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; +import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Date; @@ -184,13 +185,15 @@ public class DBWriter { } // delete stored media files and mark them as read List queue = DBReader.getQueue(context); - boolean queueWasModified = false; + List removed = new ArrayList<>(); if (feed.getItems() == null) { DBReader.getFeedItemList(context, feed); } for (FeedItem item : feed.getItems()) { - queueWasModified |= queue.remove(item); + if(queue.remove(item)) { + removed.add(item); + } if (item.getMedia() != null && item.getMedia().isDownloaded()) { File mediaFile = new File(item.getMedia() @@ -213,8 +216,10 @@ public class DBWriter { } PodDBAdapter adapter = new PodDBAdapter(context); adapter.open(); - if (queueWasModified) { + if (removed.size() > 0) { adapter.setQueue(queue); + EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.IRREVERSIBLE_REMOVED, + removed)); } adapter.removeFeed(feed); adapter.close(); -- cgit v1.2.3 From a9de7631fd4e4de3ca94bbb2775dbd4c1eb900e5 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 4 Jul 2015 17:33:35 +0200 Subject: Fix button moving and icon being cut --- core/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 00d7ed1bd..94c02a2d2 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -20,7 +20,7 @@ Running Completed Log - Cancel Download + Cancel\nDownload Playback History gpodder.net gpodder.net Login -- cgit v1.2.3 From 9cae7c5bfbe252158ddfa6195519db2dbb0a950e Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 5 Jul 2015 15:28:30 +0200 Subject: Small fixes. --- core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java | 2 +- core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index 302e4e2dd..33dd9d636 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -186,7 +186,7 @@ public class FeedMedia extends FeedFile implements Playable { public void setPosition(int position) { this.position = position; - if(position > 0) { + if(position > 0 && item.isNew()) { this.item.setPlayed(false); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 8f09ff3c2..2be53047d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -877,12 +877,10 @@ public class PodDBAdapter { public void setQueue(List queue) { ContentValues values = new ContentValues(); - long[] ids = new long[queue.size()]; db.beginTransaction(); db.delete(TABLE_NAME_QUEUE, null, null); for (int i = 0; i < queue.size(); i++) { FeedItem item = queue.get(i); - ids[i] = item.getId(); values.put(KEY_ID, i); values.put(KEY_FEEDITEM, item.getId()); values.put(KEY_FEED, item.getFeed().getId()); -- cgit v1.2.3 From 0314d0f95d86752d2d5a6d506153d2b8087d95e4 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 7 Jul 2015 19:51:48 -0400 Subject: setRepeating is setInexactRepeating on API 19+, that means we can go as long as interval*2 before updates. Switched to use 'set()' instead to get behavior that matches what users expect. --- .../core/preferences/UserPreferences.java | 27 +++++++++++++--------- .../core/receiver/AlarmUpdateReceiver.java | 2 +- .../core/receiver/FeedUpdateReceiver.java | 2 ++ 3 files changed, 19 insertions(+), 12 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index c9bfe2153..c1b913c27 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -343,23 +343,25 @@ public class UserPreferences { } /** - * Sets the update interval value. Should only be used for testing purposes! + * Sets the update interval value. */ public static void setUpdateInterval(long hours) { prefs.edit() .putString(PREF_UPDATE_INTERVAL, String.valueOf(hours)) .apply(); - restartUpdateAlarm(); + // when updating with an interval, we assume the user wants + // to update *now* and then every 'hours' interval thereafter. + restartUpdateAlarm(true); } /** - * Sets the update interval value. Should only be used for testing purposes! + * Sets the update interval value. */ public static void setUpdateTimeOfDay(int hourOfDay, int minute) { prefs.edit() .putString(PREF_UPDATE_INTERVAL, hourOfDay + ":" + minute) .apply(); - restartUpdateAlarm(); + restartUpdateAlarm(false); } /** @@ -538,13 +540,18 @@ public class UserPreferences { } } - public static void restartUpdateAlarm() { + public static void restartUpdateAlarm(boolean now) { int[] timeOfDay = getUpdateTimeOfDay(); + Log.d(TAG, "timeOfDay: " + Arrays.toString(timeOfDay)); if (timeOfDay.length == 2) { restartUpdateTimeOfDayAlarm(timeOfDay[0], timeOfDay[1]); } else { long hours = getUpdateInterval(); - restartUpdateIntervalAlarm(TimeUnit.SECONDS.toMillis(10), hours); + long startTrigger = hours; + if (now) { + startTrigger = TimeUnit.SECONDS.toMillis(10); + } + restartUpdateIntervalAlarm(startTrigger, hours); } } @@ -558,9 +565,8 @@ public class UserPreferences { new Intent(ClientConfig.applicationCallbacks.getApplicationInstance(), FeedUpdateReceiver.class), 0); alarmManager.cancel(updateIntent); if (intervalMillis > 0) { - alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, + alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + triggerAtMillis, - intervalMillis, updateIntent); Log.d(TAG, "Changed alarm to new interval " + TimeUnit.MILLISECONDS.toHours(intervalMillis) + " h"); } else { @@ -585,10 +591,9 @@ public class UserPreferences { if(alarm.before(now)) { alarm.add(Calendar.DATE, 1); } - - alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, + Log.d(TAG, "Alarm set for: " + alarm.toString() + " : " + alarm.getTimeInMillis()); + alarmManager.set(AlarmManager.RTC_WAKEUP, alarm.getTimeInMillis(), - AlarmManager.INTERVAL_DAY, updateIntent); Log.d(TAG, "Changed alarm to new time of day " + hoursOfDay + ":" + minute); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java b/core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java index ec3e9d9ea..7fa92f30c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java +++ b/core/src/main/java/de/danoeh/antennapod/core/receiver/AlarmUpdateReceiver.java @@ -25,7 +25,7 @@ public class AlarmUpdateReceiver extends BroadcastReceiver { } PlaybackPreferences.init(context); UserPreferences.init(context); - UserPreferences.restartUpdateAlarm(); + UserPreferences.restartUpdateAlarm(false); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java index d37f97a5f..d98086003 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java +++ b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java @@ -5,6 +5,7 @@ import android.content.Context; import android.content.Intent; import android.util.Log; +import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.util.NetworkUtils; @@ -23,6 +24,7 @@ public class FeedUpdateReceiver extends BroadcastReceiver { } else { Log.d(TAG, "Blocking automatic update: no wifi available / no mobile updates allowed"); } + UserPreferences.restartUpdateAlarm(false); } } -- cgit v1.2.3 From 85598f64a9169042742344ff4d6724119303e3d9 Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Wed, 24 Jun 2015 23:13:44 +0300 Subject: Added new per-feed auto download override flag. --- .../java/de/danoeh/antennapod/core/feed/Feed.java | 2 +- .../antennapod/core/feed/FeedPreferences.java | 35 ++++++++++++++++++++-- .../core/service/download/DownloadService.java | 2 +- .../core/service/playback/PlaybackService.java | 2 +- .../playback/PlaybackServiceMediaPlayer.java | 2 +- .../danoeh/antennapod/core/storage/DBReader.java | 2 +- .../antennapod/core/storage/PodDBAdapter.java | 7 ++++- core/src/main/res/values-iw-rIL/strings.xml | 1 + core/src/main/res/values/arrays.xml | 6 ++++ core/src/main/res/values/strings.xml | 1 + 10 files changed, 51 insertions(+), 9 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java index 25b3a9ae6..f6322d6f4 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java @@ -167,7 +167,7 @@ public class Feed extends FeedFile implements FlattrThing, PicassoImageResource */ public Feed(String url, Date lastUpdate, String title, String username, String password) { this(url, lastUpdate, title); - preferences = new FeedPreferences(0, true, username, password); + preferences = new FeedPreferences(0, true, FeedPreferences.AutoDeleteAction.GLOBAL, username, password); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java index 2f0304182..cb264db03 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java @@ -11,19 +11,26 @@ public class FeedPreferences { private long feedID; private boolean autoDownload; + public enum AutoDeleteAction { + GLOBAL, + YES, + NO + } + private AutoDeleteAction auto_delete_action; private String username; private String password; - public FeedPreferences(long feedID, boolean autoDownload, String username, String password) { + public FeedPreferences(long feedID, boolean autoDownload, AutoDeleteAction auto_delete_action, String username, String password) { this.feedID = feedID; this.autoDownload = autoDownload; + this.auto_delete_action = auto_delete_action; this.username = username; this.password = password; } /** - * Compare another FeedPreferences with this one. The feedID and autoDownload attribute are excluded from the + * Compare another FeedPreferences with this one. The feedID, autoDownload and AutoDeleteAction attribute are excluded from the * comparison. * * @return True if the two objects are different. @@ -41,7 +48,7 @@ public class FeedPreferences { } /** - * Update this FeedPreferences object from another one. The feedID and autoDownload attributes are excluded + * Update this FeedPreferences object from another one. The feedID, autoDownload and AutoDeleteAction attributes are excluded * from the update. */ public void updateFromOther(FeedPreferences other) { @@ -67,6 +74,28 @@ public class FeedPreferences { this.autoDownload = autoDownload; } + public AutoDeleteAction getAutoDeleteAction() { + return auto_delete_action; + } + + public void setAutoDeleteAction(AutoDeleteAction auto_delete_action) { + this.auto_delete_action = auto_delete_action; + } + + public boolean getCurrentAutoDelete(boolean isAutoDelete) { + switch (auto_delete_action) { + case GLOBAL: + return isAutoDelete; + + case YES: + return true; + + case NO: + return false; + } + return false; // TODO - add exceptions here + } + public void save(Context context) { DBWriter.setFeedPreferences(context, this); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 7fb878680..578bce854 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -891,7 +891,7 @@ public class DownloadService extends Service { feed.setFile_url(request.getDestination()); feed.setId(request.getFeedfileId()); feed.setDownloaded(true); - feed.setPreferences(new FeedPreferences(0, true, + feed.setPreferences(new FeedPreferences(0, true, FeedPreferences.AutoDeleteAction.GLOBAL, request.getUsername(), request.getPassword())); feed.setPageNr(request.getArguments().getInt(DownloadRequester.REQUEST_ARG_PAGE_NR, 0)); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index 9ab3d93a1..6db77540f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -584,7 +584,7 @@ public class PlaybackService extends Service { } // Delete episode if enabled - if(UserPreferences.isAutoDelete()) { + if(item.getFeed().getPreferences().getCurrentAutoDelete(UserPreferences.isAutoDelete())) { DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId()); Log.d(TAG, "Episode Deleted"); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index d4b63fdb1..76ecf09b6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -196,7 +196,7 @@ public class PlaybackServiceMediaPlayer { DBWriter.markItemRead(context, item, true, false); DBWriter.removeQueueItem(context, item, false); DBWriter.addItemToPlaybackHistory(context, oldMedia); - if (UserPreferences.isAutoDelete()) { + if (item.getFeed().getPreferences().getCurrentAutoDelete(UserPreferences.isAutoDelete())) { Log.d(TAG, "Delete " + oldMedia.toString()); DBWriter.deleteFeedMediaOfItem(context, oldMedia.getId()); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 93aec54c8..634563099 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -338,9 +338,9 @@ public final class DBReader { if (image != null) { image.setOwner(feed); } - FeedPreferences preferences = new FeedPreferences(cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_ID), cursor.getInt(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_AUTO_DOWNLOAD) > 0, + FeedPreferences.AutoDeleteAction.values()[cursor.getInt(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_AUTO_DELETE_ACTION)], cursor.getString(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_USERNAME), cursor.getString(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_PASSWORD)); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 2be53047d..d6740212e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -150,6 +150,7 @@ public class PodDBAdapter { public static final String KEY_CHAPTER_TYPE = "type"; public static final String KEY_PLAYBACK_COMPLETION_DATE = "playback_completion_date"; public static final String KEY_AUTO_DOWNLOAD = "auto_download"; + public static final String KEY_AUTO_DELETE_ACTION = "auto_delete_action"; public static final String KEY_PLAYED_DURATION = "played_duration"; public static final String KEY_USERNAME = "username"; public static final String KEY_PASSWORD = "password"; @@ -187,7 +188,8 @@ public class PodDBAdapter { + KEY_IS_PAGED + " INTEGER DEFAULT 0," + KEY_NEXT_PAGE_LINK + " TEXT," + KEY_HIDE + " TEXT," - + KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0)"; + + KEY_LAST_UPDATE_FAILED + " INTEGER DEFAULT 0," + + KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0)"; public static final String CREATE_TABLE_FEED_ITEMS = "CREATE TABLE " + TABLE_NAME_FEED_ITEMS + " (" + TABLE_PRIMARY_KEY + KEY_TITLE @@ -283,6 +285,7 @@ public class PodDBAdapter { TABLE_NAME_FEEDS + "." + KEY_PASSWORD, TABLE_NAME_FEEDS + "." + KEY_HIDE, TABLE_NAME_FEEDS + "." + KEY_LAST_UPDATE_FAILED, + TABLE_NAME_FEEDS + "." + KEY_AUTO_DELETE_ACTION, }; // column indices for FEED_SEL_STD @@ -306,6 +309,7 @@ public class PodDBAdapter { public static final int IDX_FEED_SEL_STD_NEXT_PAGE_LINK = 17; public static final int IDX_FEED_SEL_PREFERENCES_USERNAME = 18; public static final int IDX_FEED_SEL_PREFERENCES_PASSWORD = 19; + public static final int IDX_FEED_SEL_PREFERENCES_AUTO_DELETE_ACTION = 22; /** * Select all columns from the feeditems-table except description and @@ -461,6 +465,7 @@ public class PodDBAdapter { } ContentValues values = new ContentValues(); values.put(KEY_AUTO_DOWNLOAD, prefs.getAutoDownload()); + values.put(KEY_AUTO_DELETE_ACTION,prefs.getAutoDeleteAction().ordinal()); values.put(KEY_USERNAME, prefs.getUsername()); values.put(KEY_PASSWORD, prefs.getPassword()); db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(prefs.getFeedID())}); diff --git a/core/src/main/res/values-iw-rIL/strings.xml b/core/src/main/res/values-iw-rIL/strings.xml index 9e9c0e6bc..321d0dab6 100644 --- a/core/src/main/res/values-iw-rIL/strings.xml +++ b/core/src/main/res/values-iw-rIL/strings.xml @@ -58,6 +58,7 @@ סגור נסה שוב כלול בהורדות אוטומטיות + מחק לאחר ההשמעה (גובר על ההגדרה הגלובלית) \u0020הורדות במקביל כתובת הזנה diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 5fe5f24e8..6b45d1aef 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -1,6 +1,12 @@ + + Global + Always + Never + + 0 15 diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 232ba238e..b0888111d 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -75,6 +75,7 @@ Close Retry Include in auto downloads + Auto Delete Episode\n(override global default) \u0020parallel downloads -- cgit v1.2.3 From 48bfdaa2b32b81492b8e8ad57a8feab29656689d Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Mon, 6 Jul 2015 23:41:02 +0300 Subject: Spinner items now taken from the string resources and can be localized. Also fixed the TextView Hebrew string (break into 2 lines). --- core/src/main/res/values-iw-rIL/strings.xml | 5 ++++- core/src/main/res/values/arrays.xml | 6 +++--- core/src/main/res/values/strings.xml | 3 +++ 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values-iw-rIL/strings.xml b/core/src/main/res/values-iw-rIL/strings.xml index 321d0dab6..20ddd6d71 100644 --- a/core/src/main/res/values-iw-rIL/strings.xml +++ b/core/src/main/res/values-iw-rIL/strings.xml @@ -58,8 +58,11 @@ סגור נסה שוב כלול בהורדות אוטומטיות - מחק לאחר ההשמעה (גובר על ההגדרה הגלובלית) + מחק לאחר ההשמעה\n(גובר על ההגדרה הגלובלית) \u0020הורדות במקביל + לפי הגדרה גלובלית + תמיד + אף פעם כתובת הזנה כתובת של הזנה או אתר אינטרנט diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 6b45d1aef..3c852360c 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -2,9 +2,9 @@ - Global - Always - Never + @string/feed_auto_download_global + @string/feed_auto_download_always + @string/feed_auto_download_never diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index b0888111d..5079950fa 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -77,6 +77,9 @@ Include in auto downloads Auto Delete Episode\n(override global default) \u0020parallel downloads + Global + Always + Never Feed URL -- cgit v1.2.3 From a22fa8660bccae0f9e740bcf09d00006e878c5d5 Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Tue, 7 Jul 2015 22:13:32 +0300 Subject: FeedPreferences.getCurrentAutoDelete() now calls UserPreferences.isAutoDelete() by itself, instead of receiving it as a parameter. --- .../main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java | 5 +++-- .../de/danoeh/antennapod/core/service/playback/PlaybackService.java | 2 +- .../antennapod/core/service/playback/PlaybackServiceMediaPlayer.java | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java index cb264db03..88da865cc 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod.core.feed; import android.content.Context; import de.danoeh.antennapod.core.storage.DBWriter; import org.apache.commons.lang3.StringUtils; +import de.danoeh.antennapod.core.preferences.UserPreferences; /** * Contains preferences for a single feed. @@ -82,10 +83,10 @@ public class FeedPreferences { this.auto_delete_action = auto_delete_action; } - public boolean getCurrentAutoDelete(boolean isAutoDelete) { + public boolean getCurrentAutoDelete() { switch (auto_delete_action) { case GLOBAL: - return isAutoDelete; + return UserPreferences.isAutoDelete(); case YES: return true; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index 6db77540f..737f0aefd 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -584,7 +584,7 @@ public class PlaybackService extends Service { } // Delete episode if enabled - if(item.getFeed().getPreferences().getCurrentAutoDelete(UserPreferences.isAutoDelete())) { + if(item.getFeed().getPreferences().getCurrentAutoDelete()) { DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId()); Log.d(TAG, "Episode Deleted"); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 76ecf09b6..835a8c1d1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -196,7 +196,7 @@ public class PlaybackServiceMediaPlayer { DBWriter.markItemRead(context, item, true, false); DBWriter.removeQueueItem(context, item, false); DBWriter.addItemToPlaybackHistory(context, oldMedia); - if (item.getFeed().getPreferences().getCurrentAutoDelete(UserPreferences.isAutoDelete())) { + if (item.getFeed().getPreferences().getCurrentAutoDelete()) { Log.d(TAG, "Delete " + oldMedia.toString()); DBWriter.deleteFeedMediaOfItem(context, oldMedia.getId()); } -- cgit v1.2.3 From cbbed8933ebd46ddfa54a85dcff544ed87f94342 Mon Sep 17 00:00:00 2001 From: Udi Finkelstein Date: Thu, 9 Jul 2015 01:50:27 +0300 Subject: Fix DB to version 18 --- .../main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index d6740212e..c4b879091 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -1477,7 +1477,7 @@ public class PodDBAdapter { */ private static class PodDBHelper extends SQLiteOpenHelper { - private final static int VERSION = 17; + private final static int VERSION = 18; private Context context; @@ -1698,6 +1698,10 @@ public class PodDBAdapter { Log.d("Migration", "SQL: " + sql); db.execSQL(sql); } + if(oldVersion <= 17) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0"); + } EventBus.getDefault().post(ProgressEvent.end()); } } -- cgit v1.2.3 From 4f84ceff734889748dc9d846bdf117db5fac4dce Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 3 Jul 2015 18:21:20 +0200 Subject: Determine media file size if feed doesn't report it correctly --- core/src/main/AndroidManifest.xml | 3 ++ .../core/service/FeedMediaSizeService.java | 47 ++++++++++++++++++++++ .../danoeh/antennapod/core/storage/DBReader.java | 22 ++++++++++ .../de/danoeh/antennapod/core/storage/DBTasks.java | 10 ++++- .../antennapod/core/storage/PodDBAdapter.java | 7 ++++ 5 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java (limited to 'core/src/main') diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index 3ec519844..17dcb4ad8 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -23,6 +23,9 @@ + list = DBReader.getFeedMediaUnknownSize(this); + for (FeedMedia media : list) { + long size = -1; + try { + URL url = new URL(media.getDownload_url()); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + size = conn.getContentLength(); + conn.disconnect(); + } catch (IOException e) { + e.printStackTrace(); + } + media.setSize(size); + DBWriter.setFeedMedia(this, media); + } + } + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 93aec54c8..1af0fa0a9 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -550,6 +550,28 @@ public final class DBReader { return itemIds; } + /** + * Loads the IDs of the FeedItems whose 'read'-attribute is set to false. + * + * @param context A context that is used for opening a database connection. + * @return A list of IDs of the FeedItems whose 'read'-attribute is set to false. This method should be preferred + * over {@link #getUnreadItemsList(android.content.Context)} if the FeedItems in the UnreadItems list are not used. + */ + public static List getFeedMediaUnknownSize(Context context) { + PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + Cursor cursor = adapter.getFeedMediaUnknownSizeCursor(); + List result = new ArrayList<>(cursor.getCount()); + if (cursor.moveToFirst()) { + do { + FeedMedia media = extractFeedMediaFromCursorRow(cursor); + result.add(media); + } while (cursor.moveToNext()); + } + cursor.close(); + return result; + } + /** * Loads a list of FeedItems sorted by pubDate in descending order. diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index 9273cf11e..1f6d0abd8 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -5,6 +5,9 @@ import android.content.Intent; import android.database.Cursor; import android.util.Log; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -29,6 +32,7 @@ import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.service.FeedMediaSizeService; import de.danoeh.antennapod.core.service.GpodnetSyncService; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.service.playback.PlaybackService; @@ -595,15 +599,15 @@ public final class DBTasks { item.getIdentifyingValue()); if (oldItem == null) { // item is new - final int i = idx; item.setFeed(savedFeed); item.setAutoDownload(savedFeed.getPreferences().getAutoDownload()); - savedFeed.getItems().add(i, item); + savedFeed.getItems().add(item); if (markNewItems) { item.setNew(); } } else { oldItem.updateFromOther(item); + savedFeed.getItems().add(oldItem); } } // update attributes @@ -629,6 +633,8 @@ public final class DBTasks { EventDistributor.getInstance().sendFeedUpdateBroadcast(); + context.startService(new Intent(context, FeedMediaSizeService.class)); + return resultFeeds; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 2be53047d..d42b67459 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -1105,6 +1105,13 @@ public class PodDBAdapter { return db.rawQuery(query, null); } + public final Cursor getFeedMediaUnknownSizeCursor() { + final String query = "SELECT * " + + " FROM " + TABLE_NAME_FEED_MEDIA + + " WHERE " + KEY_SIZE + "=0"; + return db.rawQuery(query, null); + } + /** * Returns a cursor which contains all items of a feed that are considered new. * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection. -- cgit v1.2.3 From 23a3e7c766a4dfbba9101672d8628b65ad16c855 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 3 Jul 2015 23:59:40 +0200 Subject: Check network for every media file, manually check suspiciously low file sizes --- .../de/danoeh/antennapod/core/service/FeedMediaSizeService.java | 9 ++++++++- .../main/java/de/danoeh/antennapod/core/storage/DBReader.java | 6 +++--- .../java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 2 +- .../de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java | 4 ++++ 4 files changed, 16 insertions(+), 5 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index b4542aae8..1f7dfa386 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -30,13 +30,20 @@ public class FeedMediaSizeService extends IntentService { } List list = DBReader.getFeedMediaUnknownSize(this); for (FeedMedia media : list) { - long size = -1; + if(false == NetworkUtils.networkAvailable(this)) { + return; + } + long size = Integer.MIN_VALUE; + Log.d(TAG, media.getDownload_url()); try { URL url = new URL(media.getDownload_url()); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestProperty( "Accept-Encoding", "" ); + conn.setRequestMethod("HEAD"); size = conn.getContentLength(); conn.disconnect(); } catch (IOException e) { + Log.d(TAG, media.getDownload_url()); e.printStackTrace(); } media.setSize(size); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 1af0fa0a9..26a974616 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -551,11 +551,11 @@ public final class DBReader { } /** - * Loads the IDs of the FeedItems whose 'read'-attribute is set to false. + * Loads FeedMedia whose file size is unknown * * @param context A context that is used for opening a database connection. - * @return A list of IDs of the FeedItems whose 'read'-attribute is set to false. This method should be preferred - * over {@link #getUnreadItemsList(android.content.Context)} if the FeedItems in the UnreadItems list are not used. + * @return A list of FeedMedia items whose size is 0 (unknown and never tried to + * determine the correct size) */ public static List getFeedMediaUnknownSize(Context context) { PodDBAdapter adapter = new PodDBAdapter(context); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index d42b67459..319987cb2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -1108,7 +1108,7 @@ public class PodDBAdapter { public final Cursor getFeedMediaUnknownSizeCursor() { final String query = "SELECT * " + " FROM " + TABLE_NAME_FEED_MEDIA - + " WHERE " + KEY_SIZE + "=0"; + + " WHERE " + KEY_SIZE + ">" + Integer.MIN_VALUE; return db.rawQuery(query, null); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java index 6455332be..31eb2efd6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java @@ -57,6 +57,10 @@ public class NSRSS20 extends Namespace { long size = 0; try { size = Long.parseLong(attributes.getValue(ENC_LEN)); + if(size < 16384) { + // less than 16kb is suspicious, check manually + size = 0; + } } catch (NumberFormatException e) { if (BuildConfig.DEBUG) Log.d(TAG, "Length attribute could not be parsed."); -- cgit v1.2.3 From be1fde6f8e416cd6ddc4be9d7b01de0e718fed55 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 4 Jul 2015 11:31:32 +0200 Subject: Post FeedMedia event --- .../antennapod/core/event/FeedMediaEvent.java | 24 ++++++++++++++++++++++ .../core/service/FeedMediaSizeService.java | 3 +++ 2 files changed, 27 insertions(+) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java new file mode 100644 index 000000000..94e186b7a --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java @@ -0,0 +1,24 @@ +package de.danoeh.antennapod.core.event; + +import de.danoeh.antennapod.core.feed.FeedMedia; + +public class FeedMediaEvent { + + public enum Action { + UPDATE + } + + public final Action action; + public final FeedMedia media; + + private FeedMediaEvent(Action action, FeedMedia media) { + this.action = action; + this.media = media; + } + + public static FeedMediaEvent update(FeedMedia media) { + return new FeedMediaEvent(Action.UPDATE, media); + } + + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index 1f7dfa386..ad047f10a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -9,10 +9,12 @@ import java.net.HttpURLConnection; import java.net.URL; import java.util.List; +import de.danoeh.antennapod.core.event.FeedMediaEvent; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.NetworkUtils; +import de.greenrobot.event.EventBus; public class FeedMediaSizeService extends IntentService { @@ -48,6 +50,7 @@ public class FeedMediaSizeService extends IntentService { } media.setSize(size); DBWriter.setFeedMedia(this, media); + EventBus.getDefault().post(FeedMediaEvent.update(media)); } } -- cgit v1.2.3 From 5608d228be2da4e06cfc07d9a133235298da8a68 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 5 Jul 2015 15:33:10 +0200 Subject: Close URL connection --- .../de/danoeh/antennapod/core/service/FeedMediaSizeService.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index ad047f10a..d6a1ce62c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -36,10 +36,10 @@ public class FeedMediaSizeService extends IntentService { return; } long size = Integer.MIN_VALUE; - Log.d(TAG, media.getDownload_url()); + HttpURLConnection conn = null; try { URL url = new URL(media.getDownload_url()); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn = (HttpURLConnection) url.openConnection(); conn.setRequestProperty( "Accept-Encoding", "" ); conn.setRequestMethod("HEAD"); size = conn.getContentLength(); @@ -47,6 +47,10 @@ public class FeedMediaSizeService extends IntentService { } catch (IOException e) { Log.d(TAG, media.getDownload_url()); e.printStackTrace(); + } finally { + if(conn != null) { + conn.disconnect(); + } } media.setSize(size); DBWriter.setFeedMedia(this, media); -- cgit v1.2.3 From 65611129e15f6a8b8f1a260f373bb6e89fc0c3ea Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 12 Jul 2015 21:17:22 +0200 Subject: Use local file size if episode is downloaded --- .../core/service/FeedMediaSizeService.java | 34 +++++++++++++--------- 1 file changed, 21 insertions(+), 13 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index d6a1ce62c..e64a38901 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -4,6 +4,7 @@ import android.app.IntentService; import android.content.Intent; import android.util.Log; +import java.io.File; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; @@ -36,20 +37,27 @@ public class FeedMediaSizeService extends IntentService { return; } long size = Integer.MIN_VALUE; - HttpURLConnection conn = null; - try { - URL url = new URL(media.getDownload_url()); - conn = (HttpURLConnection) url.openConnection(); - conn.setRequestProperty( "Accept-Encoding", "" ); - conn.setRequestMethod("HEAD"); - size = conn.getContentLength(); - conn.disconnect(); - } catch (IOException e) { - Log.d(TAG, media.getDownload_url()); - e.printStackTrace(); - } finally { - if(conn != null) { + if(media.isDownloaded()) { + File mediaFile = new File(media.getLocalMediaUrl()); + if(mediaFile.exists()) { + size = mediaFile.length(); + } + } else { + HttpURLConnection conn = null; + try { + URL url = new URL(media.getDownload_url()); + conn = (HttpURLConnection) url.openConnection(); + conn.setRequestProperty("Accept-Encoding", ""); + conn.setRequestMethod("HEAD"); + size = conn.getContentLength(); conn.disconnect(); + } catch (IOException e) { + Log.d(TAG, media.getDownload_url()); + e.printStackTrace(); + } finally { + if (conn != null) { + conn.disconnect(); + } } } media.setSize(size); -- cgit v1.2.3 From 97827cde2d822fca93f6900527e3bda56076a0d5 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 12 Jul 2015 22:07:45 +0200 Subject: Fixed tests and bug --- core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index 1f6d0abd8..a90df433e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -601,13 +601,12 @@ public final class DBTasks { // item is new item.setFeed(savedFeed); item.setAutoDownload(savedFeed.getPreferences().getAutoDownload()); - savedFeed.getItems().add(item); + savedFeed.getItems().add(idx, item); if (markNewItems) { item.setNew(); } } else { oldItem.updateFromOther(item); - savedFeed.getItems().add(oldItem); } } // update attributes -- cgit v1.2.3 From bbb72e7047a073b51db51ce45bb8738d75f6b367 Mon Sep 17 00:00:00 2001 From: Katrin Leinweber Date: Sun, 19 Jul 2015 10:32:14 +0200 Subject: add 3 & 7 day update interval --- core/src/main/res/values/arrays.xml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 3c852360c..724f667c3 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -33,6 +33,8 @@ 8 12 24 + 72 + 168 @string/pref_episode_cache_unlimited -- cgit v1.2.3 From 76393e1e7c029ff5837b2210a9ef891b897df1b8 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 19 Jul 2015 10:35:28 +0200 Subject: Info text has smaller font, conversion moved utility class --- .../de/danoeh/antennapod/core/util/Converter.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java b/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java index a0b514bd6..917f99564 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java @@ -1,7 +1,10 @@ package de.danoeh.antennapod.core.util; +import android.content.Context; import android.util.Log; +import de.danoeh.antennapod.core.R; + /** Provides methods for converting various units. */ public final class Converter { /** Class shall not be instantiated. */ @@ -99,5 +102,21 @@ public final class Converter { return Integer.valueOf(parts[0]) * 3600 * 1000 + Integer.valueOf(parts[1]) * 1000 * 60; } + + /** Converts milliseconds to a localized string containing hours and minutes */ + public static String getDurationStringLocalized(Context context, int duration) { + int h = duration / HOURS_MIL; + int rest = duration - h * HOURS_MIL; + int m = rest / MINUTES_MIL; + + String result = ""; + if(h > 0) { + String hours = context.getString(R.string.time_unit_hours); + result += h + " " + hours + " "; + } + String minutes = context.getString(R.string.time_unit_minutes); + result += m + " " + minutes; + return result; + } } -- cgit v1.2.3 From 9fb4b790f37cc297a50130f5afda3e77a774ee4e Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 19 Jul 2015 22:28:20 -0400 Subject: * DB qeury only returns items with size <= 0 * We only check for size if download is allowed (maybe we don't need to do this) * If we check using the network and fail we don't check again * removed an unneeded conn.disconnect() (it's handled in the 'finally' block) fixes AntennaPod/AntennaPod#1026 --- .../de/danoeh/antennapod/core/feed/FeedMedia.java | 21 +++++++++++++++++++++ .../core/service/FeedMediaSizeService.java | 16 +++++++++++----- .../antennapod/core/storage/PodDBAdapter.java | 2 +- 3 files changed, 33 insertions(+), 6 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index 33dd9d636..55ab46335 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -28,6 +28,15 @@ public class FeedMedia extends FeedFile implements Playable { public static final String PREF_MEDIA_ID = "FeedMedia.PrefMediaId"; public static final String PREF_FEED_ID = "FeedMedia.PrefFeedId"; + /** + * Indicates we've checked on the size of the item via the network + * and got an invalid response. Using Integer.MIN_VALUE because + * 1) we'll still check on it in case it gets downloaded (it's <= 0) + * 2) By default all FeedMedia have a size of 0 if we don't know it, + * so this won't conflict with existing practice. + */ + private static final int CHECKED_ON_SIZE = Integer.MIN_VALUE; + private int duration; private int position; // Current position in file private int played_duration; // How many ms of this file have been played (for autoflattring) @@ -199,6 +208,18 @@ public class FeedMedia extends FeedFile implements Playable { this.size = size; } + /** + * Indicates we asked the service what the size was, but didn't + * get a valid answer and we shoudln't check using the network again. + */ + public void setCheckedOnSize() { + this.size = CHECKED_ON_SIZE; + } + + public boolean checkedOnSize() { + return (CHECKED_ON_SIZE == this.size); + } + public String getMime_type() { return mime_type; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index e64a38901..9a98093ba 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -28,21 +28,23 @@ public class FeedMediaSizeService extends IntentService { @Override protected void onHandleIntent(Intent intent) { Log.d(TAG, "onHandleIntent()"); - if(false == NetworkUtils.networkAvailable(this)) { + if(false == NetworkUtils.isDownloadAllowed(this)) { return; } List list = DBReader.getFeedMediaUnknownSize(this); for (FeedMedia media : list) { - if(false == NetworkUtils.networkAvailable(this)) { + Log.d(TAG, "Getting size currently " + media.getSize() + " for " + media.getDownload_url()); + if(false == NetworkUtils.isDownloadAllowed(this)) { return; } long size = Integer.MIN_VALUE; - if(media.isDownloaded()) { + if (media.isDownloaded()) { File mediaFile = new File(media.getLocalMediaUrl()); if(mediaFile.exists()) { size = mediaFile.length(); } - } else { + } else if (false == media.checkedOnSize()) { + // only query the network if we haven't already checked HttpURLConnection conn = null; try { URL url = new URL(media.getDownload_url()); @@ -50,7 +52,6 @@ public class FeedMediaSizeService extends IntentService { conn.setRequestProperty("Accept-Encoding", ""); conn.setRequestMethod("HEAD"); size = conn.getContentLength(); - conn.disconnect(); } catch (IOException e) { Log.d(TAG, media.getDownload_url()); e.printStackTrace(); @@ -60,7 +61,12 @@ public class FeedMediaSizeService extends IntentService { } } } + if (size <= 0) { + // they didn't tell us the size, but we don't want to keep querying on it + media.setCheckedOnSize(); + } media.setSize(size); + Log.d(TAG, "Size now: " + media.getSize()); DBWriter.setFeedMedia(this, media); EventBus.getDefault().post(FeedMediaEvent.update(media)); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 15f35d644..0153cbc8c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -1113,7 +1113,7 @@ public class PodDBAdapter { public final Cursor getFeedMediaUnknownSizeCursor() { final String query = "SELECT * " + " FROM " + TABLE_NAME_FEED_MEDIA - + " WHERE " + KEY_SIZE + ">" + Integer.MIN_VALUE; + + " WHERE " + KEY_SIZE + "<= 0"; return db.rawQuery(query, null); } -- cgit v1.2.3 From 36626bbdb9be7b700e64cebced8d3986c06cdfd6 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 19 Jul 2015 22:35:28 -0400 Subject: fix setting of size so it doesn't override everything we just did --- .../java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index 9a98093ba..2882039c0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -64,8 +64,9 @@ public class FeedMediaSizeService extends IntentService { if (size <= 0) { // they didn't tell us the size, but we don't want to keep querying on it media.setCheckedOnSize(); + } else { + media.setSize(size); } - media.setSize(size); Log.d(TAG, "Size now: " + media.getSize()); DBWriter.setFeedMedia(this, media); EventBus.getDefault().post(FeedMediaEvent.update(media)); -- cgit v1.2.3 From 0dbdbdd1ed9201b55ce0f654889944a76723e6de Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Mon, 20 Jul 2015 19:55:17 -0400 Subject: renamed checkedonSize --- .../main/java/de/danoeh/antennapod/core/feed/FeedMedia.java | 10 +++++----- .../danoeh/antennapod/core/service/FeedMediaSizeService.java | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index 55ab46335..9dbf6cc61 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -35,7 +35,7 @@ public class FeedMedia extends FeedFile implements Playable { * 2) By default all FeedMedia have a size of 0 if we don't know it, * so this won't conflict with existing practice. */ - private static final int CHECKED_ON_SIZE = Integer.MIN_VALUE; + private static final int CHECKED_ON_SIZE_BUT_UNKNOWN = Integer.MIN_VALUE; private int duration; private int position; // Current position in file @@ -212,12 +212,12 @@ public class FeedMedia extends FeedFile implements Playable { * Indicates we asked the service what the size was, but didn't * get a valid answer and we shoudln't check using the network again. */ - public void setCheckedOnSize() { - this.size = CHECKED_ON_SIZE; + public void setCheckedOnSizeButUnknown() { + this.size = CHECKED_ON_SIZE_BUT_UNKNOWN; } - public boolean checkedOnSize() { - return (CHECKED_ON_SIZE == this.size); + public boolean checkedOnSizeButUnknown() { + return (CHECKED_ON_SIZE_BUT_UNKNOWN == this.size); } public String getMime_type() { diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index 2882039c0..44fb14f0c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -43,7 +43,7 @@ public class FeedMediaSizeService extends IntentService { if(mediaFile.exists()) { size = mediaFile.length(); } - } else if (false == media.checkedOnSize()) { + } else if (false == media.checkedOnSizeButUnknown()) { // only query the network if we haven't already checked HttpURLConnection conn = null; try { @@ -63,7 +63,7 @@ public class FeedMediaSizeService extends IntentService { } if (size <= 0) { // they didn't tell us the size, but we don't want to keep querying on it - media.setCheckedOnSize(); + media.setCheckedOnSizeButUnknown(); } else { media.setSize(size); } -- cgit v1.2.3 From 36eb938aa34be4c88fb07788aec4537099107d7a Mon Sep 17 00:00:00 2001 From: Katrin Leinweber Date: Wed, 22 Jul 2015 09:25:08 +0200 Subject: remove 8h auto-update interval --- core/src/main/res/values/arrays.xml | 1 - 1 file changed, 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 724f667c3..2bb5a5e1b 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -30,7 +30,6 @@ 1 2 4 - 8 12 24 72 -- cgit v1.2.3 From 71a7f09d410e95951ed4d7eec5df8864cfdf13d1 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 26 Jul 2015 15:36:25 -0400 Subject: prevent multiple refreshes due to time of day alarm --- .../java/de/danoeh/antennapod/core/preferences/UserPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index c1b913c27..9f6b144ef 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -588,7 +588,7 @@ public class UserPreferences { Calendar alarm = (Calendar)now.clone(); alarm.set(Calendar.HOUR_OF_DAY, hoursOfDay); alarm.set(Calendar.MINUTE, minute); - if(alarm.before(now)) { + if (alarm.before(now) || alarm.equals(now)) { alarm.add(Calendar.DATE, 1); } Log.d(TAG, "Alarm set for: " + alarm.toString() + " : " + alarm.getTimeInMillis()); -- cgit v1.2.3 From c4e909e2916605a615c35f7f745f01335065c6b2 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 26 Jul 2015 16:25:56 -0400 Subject: expired feeds weren't implemented properly and were probably a bad idea. now refreshing all feeds on the schedule. --- .../core/receiver/FeedUpdateReceiver.java | 2 +- .../core/service/download/DownloadService.java | 1 + .../danoeh/antennapod/core/storage/DBReader.java | 29 ---------------- .../de/danoeh/antennapod/core/storage/DBTasks.java | 40 ++-------------------- .../antennapod/core/storage/PodDBAdapter.java | 7 ---- 5 files changed, 4 insertions(+), 75 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java index d98086003..0045f1eb0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java +++ b/core/src/main/java/de/danoeh/antennapod/core/receiver/FeedUpdateReceiver.java @@ -20,7 +20,7 @@ public class FeedUpdateReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { Log.d(TAG, "Received intent"); if (NetworkUtils.isDownloadAllowed(context)) { - DBTasks.refreshExpiredFeeds(context); + DBTasks.refreshAllFeeds(context, null); } else { Log.d(TAG, "Blocking automatic update: no wifi available / no mobile updates allowed"); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 578bce854..3df305027 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -326,6 +326,7 @@ public class DownloadService extends Service { unregisterReceiver(cancelDownloadReceiver); if (!newMediaFiles.isEmpty()) { + Log.d(TAG, "newMediaFiles exist, autodownload them"); DBTasks.autodownloadUndownloadedItems(getApplicationContext(), ArrayUtils.toPrimitive(newMediaFiles.toArray(new Long[newMediaFiles.size()]))); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 53fd8c24b..cfbfd152b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -114,35 +114,6 @@ public final class DBReader { return result; } - /** - * Returns a list of 'expired Feeds', i.e. Feeds that have not been updated for a certain amount of time. - * - * @param context A context that is used for opening a database connection. - * @param expirationTime Time that is used for determining whether a feed is outdated or not. - * A Feed is considered expired if 'lastUpdate < (currentTime - expirationTime)' evaluates to true. - * @return A list of Feeds, sorted alphabetically by their title. A Feed-object - * of the returned list does NOT have its list of FeedItems yet. The FeedItem-list - * can be loaded separately with {@link #getFeedItemList(android.content.Context, de.danoeh.antennapod.core.feed.Feed)}. - */ - public static List getExpiredFeedsList(final Context context, final long expirationTime) { - Log.d(TAG, String.format("getExpiredFeedsList(%d)", expirationTime)); - - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - - Cursor feedlistCursor = adapter.getExpiredFeedsCursor(expirationTime); - List feeds = new ArrayList(feedlistCursor.getCount()); - - if (feedlistCursor.moveToFirst()) { - do { - Feed feed = extractFeedFromCursorRow(adapter, feedlistCursor); - feeds.add(feed); - } while (feedlistCursor.moveToNext()); - } - feedlistCursor.close(); - return feeds; - } - /** * Takes a list of FeedItems and loads their corresponding Feed-objects from the database. * The feedID-attribute of a FeedItem must be set to the ID of its feed or the method will diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index a90df433e..b08013c65 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -184,6 +184,7 @@ public final class DBTasks { if (ClientConfig.gpodnetCallbacks.gpodnetEnabled()) { GpodnetSyncService.sendSyncIntent(context); } + Log.d(TAG, "refreshAllFeeds autodownload"); autodownloadUndownloadedItems(context); } }.start(); @@ -192,44 +193,6 @@ public final class DBTasks { } } - /** - * Used by refreshExpiredFeeds to determine which feeds should be refreshed. - * This method will use the value specified in the UserPreferences as the - * expiration time. - * - * @param context Used for DB access. - * @return A list of expired feeds. An empty list will be returned if there - * are no expired feeds. - */ - public static List getExpiredFeeds(final Context context) { - long millis = UserPreferences.getUpdateInterval(); - if (millis > 0) { - List feedList = DBReader.getExpiredFeedsList(context, millis); - if (feedList.size() > 0) { - refreshFeeds(context, feedList); - } - return feedList; - } else { - return new ArrayList(); - } - } - - /** - * Refreshes expired Feeds in the list returned by the getExpiredFeedsList(Context, long) method in DBReader. - * The expiration date parameter is determined by the update interval specified in {@link UserPreferences}. - * - * @param context Used for DB access. - */ - public static void refreshExpiredFeeds(final Context context) { - Log.d(TAG, "Refreshing expired feeds"); - - new Thread() { - public void run() { - refreshFeeds(context, getExpiredFeeds(context)); - } - }.start(); - } - private static void refreshFeeds(final Context context, final List feedList) { @@ -440,6 +403,7 @@ public final class DBTasks { * @return A Future that can be used for waiting for the methods completion. */ public static Future autodownloadUndownloadedItems(final Context context, final long... mediaIds) { + Log.d(TAG, "autodownloadUndownloadedItems"); return autodownloadExec.submit(ClientConfig.dbTasksCallbacks.getAutomaticDownloadAlgorithm() .autoDownloadUndownloadedItems(context, mediaIds)); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 0153cbc8c..d0402710c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -981,13 +981,6 @@ public class PodDBAdapter { return db.query(TABLE_NAME_FEEDS, new String[]{KEY_ID, KEY_DOWNLOAD_URL}, null, null, null, null, null); } - public final Cursor getExpiredFeedsCursor(long expirationTime) { - Cursor c = db.query(TABLE_NAME_FEEDS, FEED_SEL_STD, KEY_LASTUPDATE + " < " + String.valueOf(System.currentTimeMillis() - expirationTime), - null, null, null, - null); - return c; - } - /** * Returns a cursor with all FeedItems of a Feed. Uses FEEDITEM_SEL_FI_SMALL * -- cgit v1.2.3 From b0c464d6ba2f0ed57a8255d7ae1999ef0f2e2acc Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Mon, 27 Jul 2015 19:46:29 -0400 Subject: share titles with the URL. fixes AntennaPod/AntennaPod#905 --- .../de/danoeh/antennapod/core/util/ShareUtils.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java index c065a62c3..35916a604 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/ShareUtils.java @@ -21,11 +21,11 @@ public class ShareUtils { } public static void shareFeedlink(Context context, Feed feed) { - shareLink(context, feed.getLink()); + shareLink(context, feed.getTitle() + ": " + feed.getLink()); } public static void shareFeedDownloadLink(Context context, Feed feed) { - shareLink(context, feed.getDownload_url()); + shareLink(context, feed.getTitle() + ": " + feed.getDownload_url()); } public static void shareFeedItemLink(Context context, FeedItem item) { @@ -36,24 +36,24 @@ public class ShareUtils { shareFeedItemDownloadLink(context, item, false); } + private static String getItemShareText(FeedItem item) { + return item.getFeed().getTitle() + ": " + item.getTitle(); + } + public static void shareFeedItemLink(Context context, FeedItem item, boolean withPosition) { - String text; + String text = getItemShareText(item) + " " + item.getLink(); if(withPosition) { int pos = item.getMedia().getPosition(); text = item.getLink() + " [" + Converter.getDurationStringLong(pos) + "]"; - } else { - text = item.getLink(); } shareLink(context, text); } public static void shareFeedItemDownloadLink(Context context, FeedItem item, boolean withPosition) { - String text; + String text = getItemShareText(item) + " " + item.getMedia().getDownload_url(); if(withPosition) { int pos = item.getMedia().getPosition(); - text = item.getMedia().getDownload_url() + " [" + Converter.getDurationStringLong(pos) + "]"; - } else { - text = item.getMedia().getDownload_url(); + text += " [" + Converter.getDurationStringLong(pos) + "]"; } shareLink(context, text); } -- cgit v1.2.3 From d45b7c7b6d66b448366538ad67de31a644f49d16 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 28 Jul 2015 17:26:02 -0400 Subject: * fix ConcurrentModificationException in Gpodder * removed 'About' tests (they take too long) --- .../core/preferences/GpodnetPreferences.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java index c3c6ce8c5..1401d5f39 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/GpodnetPreferences.java @@ -8,7 +8,6 @@ import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -217,26 +216,36 @@ public class GpodnetPreferences { public static void removeRemovedFeeds(Collection removed) { ensurePreferencesLoaded(); + feedListLock.lock(); removedFeeds.removeAll(removed); writePreference(PREF_SYNC_REMOVED, removedFeeds); + feedListLock.unlock(); } - public static synchronized void enqueueEpisodeAction(GpodnetEpisodeAction action) { + public static void enqueueEpisodeAction(GpodnetEpisodeAction action) { ensurePreferencesLoaded(); + feedListLock.lock(); queuedEpisodeActions.add(action); writePreference(PREF_SYNC_EPISODE_ACTIONS, writeEpisodeActionsToString(queuedEpisodeActions)); + feedListLock.unlock(); GpodnetSyncService.sendSyncActionsIntent(ClientConfig.applicationCallbacks.getApplicationInstance()); } public static List getQueuedEpisodeActions() { ensurePreferencesLoaded(); - return Collections.unmodifiableList(queuedEpisodeActions); + List copy = new ArrayList(); + feedListLock.lock(); + copy.addAll(queuedEpisodeActions); + feedListLock.unlock(); + return copy; } - public static synchronized void removeQueuedEpisodeActions(Collection queued) { + public static void removeQueuedEpisodeActions(Collection queued) { ensurePreferencesLoaded(); + feedListLock.lock(); queuedEpisodeActions.removeAll(queued); writePreference(PREF_SYNC_EPISODE_ACTIONS, writeEpisodeActionsToString(queuedEpisodeActions)); + feedListLock.unlock(); } /** @@ -252,12 +261,14 @@ public class GpodnetPreferences { setUsername(null); setPassword(null); setDeviceID(null); + feedListLock.lock(); addedFeeds.clear(); writePreference(PREF_SYNC_ADDED, addedFeeds); removedFeeds.clear(); writePreference(PREF_SYNC_REMOVED, removedFeeds); queuedEpisodeActions.clear(); writePreference(PREF_SYNC_EPISODE_ACTIONS, writeEpisodeActionsToString(queuedEpisodeActions)); + feedListLock.unlock(); setLastSubscriptionSyncTimestamp(0); } -- cgit v1.2.3 From d13885944a550922ce80f93119d2e6f9ca899291 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 28 Jul 2015 17:52:38 -0400 Subject: Added Norweign Also updated some other strings. fixes AntennaPod/AntennaPod#1038 --- core/src/main/res/values-it-rIT/strings.xml | 1 + core/src/main/res/values-no/strings.xml | 30 ++++++++++++++++++ core/src/main/res/values-tr/strings.xml | 48 +++++++++++++++++++++++------ 3 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 core/src/main/res/values-no/strings.xml (limited to 'core/src/main') diff --git a/core/src/main/res/values-it-rIT/strings.xml b/core/src/main/res/values-it-rIT/strings.xml index b81e3f2ce..82c7395ff 100644 --- a/core/src/main/res/values-it-rIT/strings.xml +++ b/core/src/main/res/values-it-rIT/strings.xml @@ -126,6 +126,7 @@ Errore di autenticazione Annulla tutti i download Download annullato + Download completato con un errore (o errori) Rapporto del downoad URL malformato Errore IO diff --git a/core/src/main/res/values-no/strings.xml b/core/src/main/res/values-no/strings.xml new file mode 100644 index 000000000..16639048b --- /dev/null +++ b/core/src/main/res/values-no/strings.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/core/src/main/res/values-tr/strings.xml b/core/src/main/res/values-tr/strings.xml index e83c9b48e..9f80f8532 100644 --- a/core/src/main/res/values-tr/strings.xml +++ b/core/src/main/res/values-tr/strings.xml @@ -26,6 +26,7 @@ Münüyü aç Menüyü kapat + Çekmece Seçenekleri Tarayıcıda aç URL\'yi kopyala @@ -39,6 +40,7 @@ İptal Yayıncı Dil + URL Ayarlar Resim Hata @@ -67,10 +69,10 @@ gdpodder.net dizininde yeni cep yayınlarını isme, kategoriye veya popülerliğe göre arayabilirsiniz veya iTunes mağazasında arama yapabilirsiniz. gpodder.net\'e gözat - Hepsini okundu olarak işaretle - Tüm bölümler okundu olarak işaretlendi - Lütfen tüm bölümleri okundu olarak işaretlemek istediğinizi onaylayın. - Lütfen bu besleme içindeki tüm bölümleri okundu olarak işaretlemek istediğinizi onaylayın. + Hepsini oynatıldı olarak işaretle + Tüm bölümleri oynatıldı olarak işaretle + Lütfen tüm bölümleri oynatıldı olarak işaretlemek istediğinizi onaylayın. + Lütfen bu besleme içindeki tüm bölümleri oynatıldı olarak işaretlemek istediğinizi onaylayın. Bilgiyi göster Cep yayını kaldır Web sayfası bağlantısı paylaş @@ -78,6 +80,16 @@ Lütfen bu beslemeyi ve bu beslemeye ait indirilmiş BÜTÜN bölümleri silme isteğinizi onaylayın. Besleme kaldırılıyor Tüm beslemeyi yenile + Bölümleri gizle + Oynatılmadı + Duraklatıldı + Oynatıldı + Kuyrukta + Kuyrukta değil + İndirildi + İndirilmedi + Filtrelendi + {fa-exclamation-circle} Son yenileme başarısız oldu İndir Oynat @@ -86,16 +98,20 @@ Akış Kaldır Bölümü kaldır - Okundu olarak işaretle - Okunmadı olarak işaretle - Okundu olarak işaretlendi + Oynatıldı olarak işaretle + Oynatılmadı olarak işaretle + Oynatıldı olarak işaretlendi Kuyruğa Ekle + Kuyruğa Eklendi Kuyruktan Kaldır Siteyi Ziyaret Et Flattr ile destekle Hepsini kuyruğa ekle Hepsini indir Bölümü atla + Otomatik indirmeyi etkinleştir + Otomatik indirmeyi devre dışı bırak + Çalme konumunu sıfırla başarılı başarısız @@ -113,7 +129,9 @@ Yetkilendirme hatası Bütün indirmeleri iptal et İndirme iptal edildi - İndirme tamamlandı + İndirme iptal edildi\nBu öğe için Otomatik İndirme devre dışı + İndirme hata(lar) ile tamamlandı + İndirme raporu Bozuk URL G/Ç Hatası İstek hatası @@ -129,6 +147,11 @@ Dosyayı indirmeye çalışırken bir hata oluştu:\u0020 Yetkilendirme gerekiyor İstediğiniz kaynak kullanıcı adı ve şifre istiyor + Mobil İndirmeyi Onaylayın + Mobil veri ile indirme ayarlarda devre dışıdır.\n\nGeçici olarak açılsın mı yoksa sadece kuyruğa mı eklensin?\n\nBu tercihiniz 10 dakika boyunca hatırlanacak. + Mobil veri ile indirme ayarlarda devre dışıdır.\n\nGeçici olarak açılsın mı?\n\nBu tercihiniz 10 dakika boyunca hatırlanacak. + Sadece Kuyruğa ekle + Geçici olarak aç Hata! Çalınan medya yok @@ -143,6 +166,8 @@ Cep yayını çalınıyor AntennaPod - Bilinmeyen medya anahtarı: %1$d + Kuyruğu kilitle + Kuyruğun kilidini aç Kuyruğu temizle Geri al Öge kaldırıldı @@ -246,8 +271,8 @@ gpodder.net hesabınız için giriş bilgisini değiştirin. Çalma hızları Değişken hızlı ses yürütmesi için kullanılabilir hızları özelleştirin - Arama zamanı - Geri veya ileri sararken bu kadar saniye atla + İleri sarma süresi + Geri sarma süresi Sunucu ismini ayarla Varsayılan sunucuyu kullan Bildirimi Genişlet @@ -257,6 +282,7 @@ Android 4.1 öncesi sürümler genişletilmiş bildirimleri desteklememektedir. Yeni bölümleri kuyruğun önüne ekle. Kuyruğun önüne ekle. + Devre dışı Otomatik Flattr\'lamayı etkinleştir Bölümün yüzde %d kısmı oynatıldığında Flattr\'la @@ -341,6 +367,8 @@ Vaysayılan dizini seç Başka bir uygulama ses çalmak istediğinde sesi kısmak yerine yürütmeyi duraklat Kesintiler için duraklat + Bir telefon konuşması tamamlandıktan sonra çalmaya kaldığı yerden devam et + Konuşmadan sonra devam et Üye ol Üye olundu -- cgit v1.2.3 From af2ded8fe01a0589dc0030c4f981f6924765ef49 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Tue, 21 Jul 2015 20:04:39 +0200 Subject: Replace Picasso with Glide --- .../antennapod/core/asynctask/ImageResource.java | 37 ++ .../core/asynctask/PicassoImageResource.java | 37 -- .../antennapod/core/asynctask/PicassoProvider.java | 533 --------------------- .../java/de/danoeh/antennapod/core/feed/Feed.java | 4 +- .../de/danoeh/antennapod/core/feed/FeedImage.java | 4 +- .../de/danoeh/antennapod/core/feed/FeedItem.java | 6 +- .../antennapod/core/glide/ApGlideModule.java | 33 ++ .../core/glide/ApOkHttpStreamFetcher.java | 80 ++++ .../antennapod/core/glide/ApOkHttpUrlLoader.java | 124 +++++ .../core/glide/FastBlurTransformation.java | 277 +++++++++++ .../core/preferences/UserPreferences.java | 8 +- .../core/service/download/DownloadService.java | 34 -- .../core/service/playback/PlaybackService.java | 27 +- .../danoeh/antennapod/core/storage/DBReader.java | 6 +- .../de/danoeh/antennapod/core/storage/DBTasks.java | 18 - .../antennapod/core/storage/DownloadRequester.java | 24 - .../antennapod/core/util/playback/Playable.java | 4 +- core/src/main/res/values/arrays.xml | 16 + core/src/main/res/values/colors.xml | 1 + core/src/main/res/values/strings.xml | 6 +- core/src/main/res/values/styles.xml | 4 +- 21 files changed, 612 insertions(+), 671 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/asynctask/ImageResource.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoImageResource.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpStreamFetcher.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/ImageResource.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/ImageResource.java new file mode 100644 index 000000000..edd69f15b --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/ImageResource.java @@ -0,0 +1,37 @@ +package de.danoeh.antennapod.core.asynctask; + +import android.net.Uri; + +/** + * Classes that implement this interface provide access to an image resource that can + * be loaded by the Picasso library. + */ +public interface ImageResource { + + /** + * This scheme should be used by PicassoImageResources to + * indicate that the image Uri points to a file that is not an image + * (e.g. a media file). This workaround is needed so that the Picasso library + * loads these Uri with a Downloader instead of trying to load it directly. + *

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

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

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

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

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

- * The Uri can also have an optional fallback-URL if loading the default URL - * failed (see PARAM_FALLBACK). - */ - public Uri getImageUri(); -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java deleted file mode 100644 index 8e47a5b71..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/PicassoProvider.java +++ /dev/null @@ -1,533 +0,0 @@ -package de.danoeh.antennapod.core.asynctask; - -import android.content.ContentResolver; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.media.MediaMetadataRetriever; -import android.net.Uri; -import android.text.TextUtils; -import android.util.Log; - -import com.squareup.okhttp.Interceptor; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Response; -import com.squareup.picasso.Cache; -import com.squareup.picasso.LruCache; -import com.squareup.picasso.OkHttpDownloader; -import com.squareup.picasso.Picasso; -import com.squareup.picasso.Request; -import com.squareup.picasso.RequestHandler; -import com.squareup.picasso.Transformation; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import de.danoeh.antennapod.core.service.download.HttpDownloader; -import de.danoeh.antennapod.core.storage.DBReader; - -/** - * Provides access to Picasso instances. - */ -public class PicassoProvider { - - private static final String TAG = "PicassoProvider"; - - private static final boolean DEBUG = false; - - private static ExecutorService executorService; - private static Cache memoryCache; - - private static synchronized ExecutorService getExecutorService() { - if (executorService == null) { - executorService = Executors.newFixedThreadPool(3); - } - return executorService; - } - - private static synchronized Cache getMemoryCache(Context context) { - if (memoryCache == null) { - memoryCache = new LruCache(context); - } - return memoryCache; - } - - private static volatile boolean picassoSetup = false; - - public static synchronized void setupPicassoInstance(Context appContext) { - if (picassoSetup) { - return; - } - OkHttpClient client = new OkHttpClient(); - client.interceptors().add(new BasicAuthenticationInterceptor(appContext)); - Picasso picasso = new Picasso.Builder(appContext) - .indicatorsEnabled(DEBUG) - .loggingEnabled(DEBUG) - .downloader(new OkHttpDownloader(client)) - .addRequestHandler(new MediaRequestHandler(appContext)) - .executor(getExecutorService()) - .memoryCache(getMemoryCache(appContext)) - .listener(new Picasso.Listener() { - @Override - public void onImageLoadFailed(Picasso picasso, Uri uri, Exception e) { - Log.e(TAG, "Failed to load Uri:" + uri.toString()); - e.printStackTrace(); - } - }) - .build(); - Picasso.setSingletonInstance(picasso); - picassoSetup = true; - } - - private static class BasicAuthenticationInterceptor implements Interceptor { - - private final Context context; - - public BasicAuthenticationInterceptor(Context context) { - this.context = context; - } - - @Override - public Response intercept(Chain chain) throws IOException { - com.squareup.okhttp.Request request = chain.request(); - String url = request.urlString(); - String authentication = DBReader.getImageAuthentication(context, url); - - if(TextUtils.isEmpty(authentication)) { - Log.d(TAG, "no credentials for '" + url + "'"); - return chain.proceed(request); - } - - // add authentication - String[] auth = authentication.split(":"); - String credentials = HttpDownloader.encodeCredentials(auth[0], auth[1], "ISO-8859-1"); - com.squareup.okhttp.Request newRequest = request - .newBuilder() - .addHeader("Authorization", credentials) - .build(); - Log.d(TAG, "Basic authentication with ISO-8859-1 encoding"); - Response response = chain.proceed(newRequest); - if (!response.isSuccessful() && response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) { - credentials = HttpDownloader.encodeCredentials(auth[0], auth[1], "UTF-8"); - newRequest = request - .newBuilder() - .addHeader("Authorization", credentials) - .build(); - Log.d(TAG, "Basic authentication with UTF-8 encoding"); - return chain.proceed(newRequest); - } else { - return response; - } - } - } - - private static class MediaRequestHandler extends RequestHandler { - - final Context context; - - public MediaRequestHandler(Context context) { - super(); - this.context = context; - } - - @Override - public boolean canHandleRequest(Request data) { - return StringUtils.equals(data.uri.getScheme(), PicassoImageResource.SCHEME_MEDIA); - } - - @Override - public Result load(Request data, int networkPolicy) throws IOException { - Bitmap bitmap = null; - MediaMetadataRetriever mmr = null; - try { - mmr = new MediaMetadataRetriever(); - mmr.setDataSource(data.uri.getPath()); - byte[] image = mmr.getEmbeddedPicture(); - if (image != null) { - bitmap = decodeStreamFromByteArray(data, image); - } - } catch (RuntimeException e) { - Log.e(TAG, "Failed to decode image in media file", e); - } finally { - if (mmr != null) { - mmr.release(); - } - } - - if (bitmap == null) { - // this should never, happen, but sometimes it does, so fallback - // check for fallback Uri - String fallbackParam = data.uri.getQueryParameter(PicassoImageResource.PARAM_FALLBACK); - if (fallbackParam != null) { - Uri fallback = Uri.parse(fallbackParam); - bitmap = decodeStreamFromFile(data, fallback); - } - } - - if (bitmap == null) { - Log.e(TAG, "Could not load media"); - return null; - } - - return new Result(bitmap, Picasso.LoadedFrom.DISK); - - } - - /* Copied/Adapted from Picasso RequestHandler classes */ - - private Bitmap decodeStreamFromByteArray(Request data, byte[] bytes) throws IOException { - - final BitmapFactory.Options options = createBitmapOptions(data); - final ByteArrayInputStream in = new ByteArrayInputStream(bytes); - in.mark(0); - if (requiresInSampleSize(options)) { - try { - BitmapFactory.decodeStream(in, null, options); - } finally { - in.reset(); - } - calculateInSampleSize(data.targetWidth, data.targetHeight, options, data); - } - try { - return BitmapFactory.decodeStream(in, null, options); - } finally { - IOUtils.closeQuietly(in); - } - } - - private Bitmap decodeStreamFromFile(Request data, Uri uri) throws IOException { - ContentResolver contentResolver = context.getContentResolver(); - final BitmapFactory.Options options = createBitmapOptions(data); - if (requiresInSampleSize(options)) { - InputStream is = null; - try { - is = contentResolver.openInputStream(uri); - BitmapFactory.decodeStream(is, null, options); - } finally { - IOUtils.closeQuietly(is); - } - calculateInSampleSize(data.targetWidth, data.targetHeight, options, data); - } - InputStream is = contentResolver.openInputStream(uri); - try { - return BitmapFactory.decodeStream(is, null, options); - } finally { - IOUtils.closeQuietly(is); - } - } - - private BitmapFactory.Options createBitmapOptions(Request data) { - final boolean justBounds = data.hasSize(); - final boolean hasConfig = data.config != null; - BitmapFactory.Options options = null; - if (justBounds || hasConfig) { - options = new BitmapFactory.Options(); - options.inJustDecodeBounds = justBounds; - if (hasConfig) { - options.inPreferredConfig = data.config; - } - } - return options; - } - - private static boolean requiresInSampleSize(BitmapFactory.Options options) { - return options != null && options.inJustDecodeBounds; - } - - private static void calculateInSampleSize(int reqWidth, int reqHeight, BitmapFactory.Options options, - Request request) { - calculateInSampleSize(reqWidth, reqHeight, options.outWidth, options.outHeight, options, - request); - } - - private static void calculateInSampleSize(int reqWidth, int reqHeight, int width, int height, - BitmapFactory.Options options, Request request) { - int sampleSize = 1; - if (height > reqHeight || width > reqWidth) { - final int heightRatio; - final int widthRatio; - if (reqHeight == 0) { - sampleSize = (int) Math.floor((float) width / (float) reqWidth); - } else if (reqWidth == 0) { - sampleSize = (int) Math.floor((float) height / (float) reqHeight); - } else { - heightRatio = (int) Math.floor((float) height / (float) reqHeight); - widthRatio = (int) Math.floor((float) width / (float) reqWidth); - sampleSize = request.centerInside - ? Math.max(heightRatio, widthRatio) - : Math.min(heightRatio, widthRatio); - } - } - options.inSampleSize = sampleSize; - options.inJustDecodeBounds = false; - } - } - - public static final int BLUR_RADIUS = 1; - public static final int BLUR_IMAGE_SIZE = 100; - public static final String BLUR_KEY = "blur"; - - public static final Transformation blurTransformation = new Transformation() { - @Override - public Bitmap transform(Bitmap source) { - Bitmap result = fastblur(source, BLUR_RADIUS); - if (result == null) { - // just return the original - // for some reason we couldn't transform it. - return source; - } - source.recycle(); - return result; - } - - @Override - public String key() { - return BLUR_KEY; - } - }; - - public static Bitmap fastblur(Bitmap sentBitmap, int radius) { - - // Stack Blur v1.0 from - // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html - // - // Java Author: Mario Klingemann - // http://incubator.quasimondo.com - // created Feburary 29, 2004 - // Android port : Yahel Bouaziz - // http://www.kayenko.com - // ported april 5th, 2012 - - // This is a compromise between Gaussian Blur and Box blur - // It creates much better looking blurs than Box Blur, but is - // 7x faster than my Gaussian Blur implementation. - // - // I called it Stack Blur because this describes best how this - // filter works internally: it creates a kind of moving stack - // of colors whilst scanning through the image. Thereby it - // just has to add one new block of color to the right side - // of the stack and remove the leftmost color. The remaining - // colors on the topmost layer of the stack are either added on - // or reduced by one, depending on if they are on the right or - // on the left side of the stack. - // - // If you are using this algorithm in your code please add - // the following line: - // - // Stack Blur Algorithm by Mario Klingemann - Bitmap.Config config = sentBitmap.getConfig(); - if (config == null) { - // Sometimes the config can be null, in those cases - // we don't do a transform. - return null; - } - - Bitmap bitmap = sentBitmap.copy(config, true); - - if (radius < 1) { - return (null); - } - - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - - int[] pix = new int[w * h]; - Log.e("pix", w + " " + h + " " + pix.length); - bitmap.getPixels(pix, 0, w, 0, 0, w, h); - - int wm = w - 1; - int hm = h - 1; - int wh = w * h; - int div = radius + radius + 1; - - int r[] = new int[wh]; - int g[] = new int[wh]; - int b[] = new int[wh]; - int rsum, gsum, bsum, x, y, i, p, yp, yi, yw; - int vmin[] = new int[Math.max(w, h)]; - - int divsum = (div + 1) >> 1; - divsum *= divsum; - int dv[] = new int[256 * divsum]; - for (i = 0; i < 256 * divsum; i++) { - dv[i] = (i / divsum); - } - - yw = yi = 0; - - int[][] stack = new int[div][3]; - int stackpointer; - int stackstart; - int[] sir; - int rbs; - int r1 = radius + 1; - int routsum, goutsum, boutsum; - int rinsum, ginsum, binsum; - - for (y = 0; y < h; y++) { - rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; - for (i = -radius; i <= radius; i++) { - p = pix[yi + Math.min(wm, Math.max(i, 0))]; - sir = stack[i + radius]; - sir[0] = (p & 0xff0000) >> 16; - sir[1] = (p & 0x00ff00) >> 8; - sir[2] = (p & 0x0000ff); - rbs = r1 - Math.abs(i); - rsum += sir[0] * rbs; - gsum += sir[1] * rbs; - bsum += sir[2] * rbs; - if (i > 0) { - rinsum += sir[0]; - ginsum += sir[1]; - binsum += sir[2]; - } else { - routsum += sir[0]; - goutsum += sir[1]; - boutsum += sir[2]; - } - } - stackpointer = radius; - - for (x = 0; x < w; x++) { - - r[yi] = dv[rsum]; - g[yi] = dv[gsum]; - b[yi] = dv[bsum]; - - rsum -= routsum; - gsum -= goutsum; - bsum -= boutsum; - - stackstart = stackpointer - radius + div; - sir = stack[stackstart % div]; - - routsum -= sir[0]; - goutsum -= sir[1]; - boutsum -= sir[2]; - - if (y == 0) { - vmin[x] = Math.min(x + radius + 1, wm); - } - p = pix[yw + vmin[x]]; - - sir[0] = (p & 0xff0000) >> 16; - sir[1] = (p & 0x00ff00) >> 8; - sir[2] = (p & 0x0000ff); - - rinsum += sir[0]; - ginsum += sir[1]; - binsum += sir[2]; - - rsum += rinsum; - gsum += ginsum; - bsum += binsum; - - stackpointer = (stackpointer + 1) % div; - sir = stack[(stackpointer) % div]; - - routsum += sir[0]; - goutsum += sir[1]; - boutsum += sir[2]; - - rinsum -= sir[0]; - ginsum -= sir[1]; - binsum -= sir[2]; - - yi++; - } - yw += w; - } - for (x = 0; x < w; x++) { - rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; - yp = -radius * w; - for (i = -radius; i <= radius; i++) { - yi = Math.max(0, yp) + x; - - sir = stack[i + radius]; - - sir[0] = r[yi]; - sir[1] = g[yi]; - sir[2] = b[yi]; - - rbs = r1 - Math.abs(i); - - rsum += r[yi] * rbs; - gsum += g[yi] * rbs; - bsum += b[yi] * rbs; - - if (i > 0) { - rinsum += sir[0]; - ginsum += sir[1]; - binsum += sir[2]; - } else { - routsum += sir[0]; - goutsum += sir[1]; - boutsum += sir[2]; - } - - if (i < hm) { - yp += w; - } - } - yi = x; - stackpointer = radius; - for (y = 0; y < h; y++) { - // Preserve alpha channel: ( 0xff000000 & pix[yi] ) - pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum]; - - rsum -= routsum; - gsum -= goutsum; - bsum -= boutsum; - - stackstart = stackpointer - radius + div; - sir = stack[stackstart % div]; - - routsum -= sir[0]; - goutsum -= sir[1]; - boutsum -= sir[2]; - - if (x == 0) { - vmin[y] = Math.min(y + r1, hm) * w; - } - p = x + vmin[y]; - - sir[0] = r[p]; - sir[1] = g[p]; - sir[2] = b[p]; - - rinsum += sir[0]; - ginsum += sir[1]; - binsum += sir[2]; - - rsum += rinsum; - gsum += ginsum; - bsum += binsum; - - stackpointer = (stackpointer + 1) % div; - sir = stack[stackpointer]; - - routsum += sir[0]; - goutsum += sir[1]; - boutsum += sir[2]; - - rinsum -= sir[0]; - ginsum -= sir[1]; - binsum -= sir[2]; - - yi += w; - } - } - - Log.e("pix", w + " " + h + " " + pix.length); - bitmap.setPixels(pix, 0, w, 0, 0, w, h); - - return (bitmap); - } -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java index f6322d6f4..2a483ca9b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java @@ -10,7 +10,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; -import de.danoeh.antennapod.core.asynctask.PicassoImageResource; +import de.danoeh.antennapod.core.asynctask.ImageResource; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.flattr.FlattrStatus; import de.danoeh.antennapod.core.util.flattr.FlattrThing; @@ -20,7 +20,7 @@ import de.danoeh.antennapod.core.util.flattr.FlattrThing; * * @author daniel */ -public class Feed extends FeedFile implements FlattrThing, PicassoImageResource { +public class Feed extends FeedFile implements FlattrThing, ImageResource { public static final int FEEDFILETYPE_FEED = 0; public static final String TYPE_RSS2 = "rss"; public static final String TYPE_RSS091 = "rss"; diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java index c6f24367e..f77a78721 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java @@ -4,10 +4,10 @@ import android.net.Uri; import java.io.File; -import de.danoeh.antennapod.core.asynctask.PicassoImageResource; +import de.danoeh.antennapod.core.asynctask.ImageResource; -public class FeedImage extends FeedFile implements PicassoImageResource { +public class FeedImage extends FeedFile implements ImageResource { public static final int FEEDFILETYPE_FEEDIMAGE = 1; protected String title; diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java index 96a6c2ba1..c0af126f7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java @@ -10,7 +10,7 @@ import java.util.List; import java.util.concurrent.Callable; import de.danoeh.antennapod.core.ClientConfig; -import de.danoeh.antennapod.core.asynctask.PicassoImageResource; +import de.danoeh.antennapod.core.asynctask.ImageResource; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.util.ShownotesProvider; import de.danoeh.antennapod.core.util.flattr.FlattrStatus; @@ -21,7 +21,7 @@ import de.danoeh.antennapod.core.util.flattr.FlattrThing; * * @author daniel */ -public class FeedItem extends FeedComponent implements ShownotesProvider, FlattrThing, PicassoImageResource { +public class FeedItem extends FeedComponent implements ShownotesProvider, FlattrThing, ImageResource { /** * The id/guid that can be found in the rss/atom feed. Might not be set. @@ -337,7 +337,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr public Uri getImageUri() { if(media != null && media.hasEmbeddedPicture()) { return media.getImageUri(); - } else if (hasItemImageDownloaded()) { + } else if (image != null) { return image.getImageUri(); } else if (feed != null) { return feed.getImageUri(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java new file mode 100644 index 000000000..0baff9723 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideModule.java @@ -0,0 +1,33 @@ +package de.danoeh.antennapod.core.glide; + +import android.content.Context; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.GlideBuilder; +import com.bumptech.glide.load.DecodeFormat; +import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory; +import com.bumptech.glide.load.model.GlideUrl; +import com.bumptech.glide.module.GlideModule; + +import java.io.InputStream; + +import de.danoeh.antennapod.core.preferences.UserPreferences; + +/** + * {@see com.bumptech.glide.integration.okhttp.OkHttpGlideModule} + */ +public class ApGlideModule implements GlideModule { + + @Override + public void applyOptions(Context context, GlideBuilder builder) { + builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888); + builder.setDiskCache(new InternalCacheDiskCacheFactory(context, + UserPreferences.getImageCacheSize())); + } + + @Override + public void registerComponents(Context context, Glide glide) { + glide.register(GlideUrl.class, InputStream.class, new ApOkHttpUrlLoader.Factory()); + } + +} \ No newline at end of file diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpStreamFetcher.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpStreamFetcher.java new file mode 100644 index 000000000..13a148d1e --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpStreamFetcher.java @@ -0,0 +1,80 @@ +package de.danoeh.antennapod.core.glide; + +import com.bumptech.glide.Priority; +import com.bumptech.glide.load.data.DataFetcher; +import com.bumptech.glide.load.model.GlideUrl; +import com.bumptech.glide.util.ContentLengthInputStream; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; +import com.squareup.okhttp.ResponseBody; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +/** + * @see com.bumptech.glide.integration.okhttp.OkHttpStreamFetcher + */ +public class ApOkHttpStreamFetcher implements DataFetcher { + private final OkHttpClient client; + private final GlideUrl url; + private InputStream stream; + private ResponseBody responseBody; + + public ApOkHttpStreamFetcher(OkHttpClient client, GlideUrl url) { + this.client = client; + this.url = url; + } + + @Override + public InputStream loadData(Priority priority) throws Exception { + Request.Builder requestBuilder = new Request.Builder() + .url(url.toStringUrl()); + + for (Map.Entry headerEntry : url.getHeaders().entrySet()) { + String key = headerEntry.getKey(); + requestBuilder.addHeader(key, headerEntry.getValue()); + } + + Request request = requestBuilder.build(); + + Response response = client.newCall(request).execute(); + responseBody = response.body(); + if (!response.isSuccessful()) { + throw new IOException("Request failed with code: " + response.code()); + } + + long contentLength = responseBody.contentLength(); + stream = ContentLengthInputStream.obtain(responseBody.byteStream(), contentLength); + return stream; + } + + @Override + public void cleanup() { + if (stream != null) { + try { + stream.close(); + } catch (IOException e) { + // Ignored + } + } + if (responseBody != null) { + try { + responseBody.close(); + } catch (IOException e) { + // Ignored. + } + } + } + + @Override + public String getId() { + return url.getCacheKey(); + } + + @Override + public void cancel() { + // TODO: call cancel on the client when this method is called on a background thread. See #257 + } +} \ No newline at end of file diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java new file mode 100644 index 000000000..33290723b --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java @@ -0,0 +1,124 @@ +package de.danoeh.antennapod.core.glide; + +import android.content.Context; +import android.text.TextUtils; +import android.util.Log; + +import com.bumptech.glide.integration.okhttp.OkHttpStreamFetcher; +import com.bumptech.glide.load.data.DataFetcher; +import com.bumptech.glide.load.model.GenericLoaderFactory; +import com.bumptech.glide.load.model.GlideUrl; +import com.bumptech.glide.load.model.ModelLoader; +import com.bumptech.glide.load.model.ModelLoaderFactory; +import com.squareup.okhttp.Interceptor; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Response; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; + +import de.danoeh.antennapod.core.ClientConfig; +import de.danoeh.antennapod.core.service.download.HttpDownloader; +import de.danoeh.antennapod.core.storage.DBReader; + +/** + * @see com.bumptech.glide.integration.okhttp.OkHttpUrlLoader + */ +public class ApOkHttpUrlLoader implements ModelLoader { + + private static final String TAG = "ApOkHttpUrlLoader"; + + /** + * The default factory for {@link ApOkHttpUrlLoader}s. + */ + public static class Factory implements ModelLoaderFactory { + private static volatile OkHttpClient internalClient; + private OkHttpClient client; + + private static OkHttpClient getInternalClient() { + if (internalClient == null) { + synchronized (Factory.class) { + if (internalClient == null) { + internalClient = new OkHttpClient(); + internalClient.interceptors().add(new BasicAuthenticationInterceptor()); + } + } + } + return internalClient; + } + + /** + * Constructor for a new Factory that runs requests using a static singleton client. + */ + public Factory() { + this(getInternalClient()); + } + + /** + * Constructor for a new Factory that runs requests using given client. + */ + public Factory(OkHttpClient client) { + this.client = client; + } + + @Override + public ModelLoader build(Context context, GenericLoaderFactory factories) { + return new ApOkHttpUrlLoader(client); + } + + @Override + public void teardown() { + // Do nothing, this instance doesn't own the client. + } + } + + private final OkHttpClient client; + + public ApOkHttpUrlLoader(OkHttpClient client) { + this.client = client; + } + + @Override + public DataFetcher getResourceFetcher(GlideUrl model, int width, int height) { + return new OkHttpStreamFetcher(client, model); + } + + private static class BasicAuthenticationInterceptor implements Interceptor { + + @Override + public Response intercept(Chain chain) throws IOException { + com.squareup.okhttp.Request request = chain.request(); + String url = request.urlString(); + Context context = ClientConfig.applicationCallbacks.getApplicationInstance(); + String authentication = DBReader.getImageAuthentication(context, url); + + if(TextUtils.isEmpty(authentication)) { + Log.d(TAG, "no credentials for '" + url + "'"); + return chain.proceed(request); + } + + // add authentication + String[] auth = authentication.split(":"); + String credentials = HttpDownloader.encodeCredentials(auth[0], auth[1], "ISO-8859-1"); + com.squareup.okhttp.Request newRequest = request + .newBuilder() + .addHeader("Authorization", credentials) + .build(); + Log.d(TAG, "Basic authentication with ISO-8859-1 encoding"); + Response response = chain.proceed(newRequest); + if (!response.isSuccessful() && response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) { + credentials = HttpDownloader.encodeCredentials(auth[0], auth[1], "UTF-8"); + newRequest = request + .newBuilder() + .addHeader("Authorization", credentials) + .build(); + Log.d(TAG, "Basic authentication with UTF-8 encoding"); + return chain.proceed(newRequest); + } else { + return response; + } + } + } + +} \ No newline at end of file diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java new file mode 100644 index 000000000..f5e645535 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java @@ -0,0 +1,277 @@ +package de.danoeh.antennapod.core.glide; + +import android.content.Context; +import android.graphics.Bitmap; +import android.util.Log; + +import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; +import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; + +public class FastBlurTransformation extends BitmapTransformation { + + private static final String TAG = "BlurTransformation"; + + private static final int RADIUS = 1; + private static final int IMAGE_SIZE = 192; + + public FastBlurTransformation(Context context) { + super(context); + } + + @Override + protected Bitmap transform(BitmapPool pool, Bitmap toTransform, + int outWidth, int outHeight) { + Bitmap resizedBitmap = Bitmap.createScaledBitmap(toTransform, IMAGE_SIZE, IMAGE_SIZE, true); + Bitmap transformed = fastBlur(resizedBitmap, RADIUS); + if (transformed == null) { + Log.w(TAG, "transformed was null"); + return toTransform; + } + return transformed; + } + + @Override + public String getId() { + return "FastBlurTransformation-" + IMAGE_SIZE + "x" + IMAGE_SIZE + "-" + RADIUS; + } + + private static Bitmap fastBlur(Bitmap original, int radius) { + + // Stack Blur v1.0 from + // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html + // + // Java Author: Mario Klingemann + // http://incubator.quasimondo.com + // created Feburary 29, 2004 + // Android port : Yahel Bouaziz + // http://www.kayenko.com + // ported april 5th, 2012 + + // This is a compromise between Gaussian Blur and Box blur + // It creates much better looking blurs than Box Blur, but is + // 7x faster than my Gaussian Blur implementation. + // + // I called it Stack Blur because this describes best how this + // filter works internally: it creates a kind of moving stack + // of colors whilst scanning through the image. Thereby it + // just has to add one new block of color to the right side + // of the stack and remove the leftmost color. The remaining + // colors on the topmost layer of the stack are either added on + // or reduced by one, depending on if they are on the right or + // on the left side of the stack. + // + // If you are using this algorithm in your code please add + // the following line: + // + // Stack Blur Algorithm by Mario Klingemann + + Bitmap.Config config = original.getConfig(); + if (config == null) { + // Sometimes the config can be null, in those cases + // we don't do a transform. + return null; + } + + Bitmap bitmap = original.copy(config, true); + + if (radius < 1) { + return null; + } + + int w = bitmap.getWidth(); + int h = bitmap.getHeight(); + + int[] pix = new int[w * h]; + Log.e("pix", w + " " + h + " " + pix.length); + bitmap.getPixels(pix, 0, w, 0, 0, w, h); + + int wm = w - 1; + int hm = h - 1; + int wh = w * h; + int div = radius + radius + 1; + + int r[] = new int[wh]; + int g[] = new int[wh]; + int b[] = new int[wh]; + int rsum, gsum, bsum, x, y, i, p, yp, yi, yw; + int vmin[] = new int[Math.max(w, h)]; + + int divsum = (div + 1) >> 1; + divsum *= divsum; + int dv[] = new int[256 * divsum]; + for (i = 0; i < 256 * divsum; i++) { + dv[i] = (i / divsum); + } + + yw = yi = 0; + + int[][] stack = new int[div][3]; + int stackpointer; + int stackstart; + int[] sir; + int rbs; + int r1 = radius + 1; + int routsum, goutsum, boutsum; + int rinsum, ginsum, binsum; + + for (y = 0; y < h; y++) { + rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; + for (i = -radius; i <= radius; i++) { + p = pix[yi + Math.min(wm, Math.max(i, 0))]; + sir = stack[i + radius]; + sir[0] = (p & 0xff0000) >> 16; + sir[1] = (p & 0x00ff00) >> 8; + sir[2] = (p & 0x0000ff); + rbs = r1 - Math.abs(i); + rsum += sir[0] * rbs; + gsum += sir[1] * rbs; + bsum += sir[2] * rbs; + if (i > 0) { + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + } else { + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + } + } + stackpointer = radius; + + for (x = 0; x < w; x++) { + + r[yi] = dv[rsum]; + g[yi] = dv[gsum]; + b[yi] = dv[bsum]; + + rsum -= routsum; + gsum -= goutsum; + bsum -= boutsum; + + stackstart = stackpointer - radius + div; + sir = stack[stackstart % div]; + + routsum -= sir[0]; + goutsum -= sir[1]; + boutsum -= sir[2]; + + if (y == 0) { + vmin[x] = Math.min(x + radius + 1, wm); + } + p = pix[yw + vmin[x]]; + + sir[0] = (p & 0xff0000) >> 16; + sir[1] = (p & 0x00ff00) >> 8; + sir[2] = (p & 0x0000ff); + + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + + rsum += rinsum; + gsum += ginsum; + bsum += binsum; + + stackpointer = (stackpointer + 1) % div; + sir = stack[(stackpointer) % div]; + + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + + rinsum -= sir[0]; + ginsum -= sir[1]; + binsum -= sir[2]; + + yi++; + } + yw += w; + } + for (x = 0; x < w; x++) { + rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0; + yp = -radius * w; + for (i = -radius; i <= radius; i++) { + yi = Math.max(0, yp) + x; + + sir = stack[i + radius]; + + sir[0] = r[yi]; + sir[1] = g[yi]; + sir[2] = b[yi]; + + rbs = r1 - Math.abs(i); + + rsum += r[yi] * rbs; + gsum += g[yi] * rbs; + bsum += b[yi] * rbs; + + if (i > 0) { + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + } else { + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + } + + if (i < hm) { + yp += w; + } + } + yi = x; + stackpointer = radius; + for (y = 0; y < h; y++) { + // Preserve alpha channel: ( 0xff000000 & pix[yi] ) + pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum]; + + rsum -= routsum; + gsum -= goutsum; + bsum -= boutsum; + + stackstart = stackpointer - radius + div; + sir = stack[stackstart % div]; + + routsum -= sir[0]; + goutsum -= sir[1]; + boutsum -= sir[2]; + + if (x == 0) { + vmin[y] = Math.min(y + r1, hm) * w; + } + p = x + vmin[y]; + + sir[0] = r[p]; + sir[1] = g[p]; + sir[2] = b[p]; + + rinsum += sir[0]; + ginsum += sir[1]; + binsum += sir[2]; + + rsum += rinsum; + gsum += ginsum; + bsum += binsum; + + stackpointer = (stackpointer + 1) % div; + sir = stack[stackpointer]; + + routsum += sir[0]; + goutsum += sir[1]; + boutsum += sir[2]; + + rinsum -= sir[0]; + ginsum -= sir[1]; + binsum -= sir[2]; + + yi += w; + } + } + + Log.e("pix", w + " " + h + " " + pix.length); + bitmap.setPixels(pix, 0, w, 0, 0, w, h); + + return bitmap; + } + +} \ No newline at end of file diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index 9f6b144ef..789a2366e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -78,6 +78,7 @@ public class UserPreferences { // Other public static final String PREF_DATA_FOLDER = "prefDataFolder"; + public static final String PREF_IMAGE_CACHE_SIZE = "prefImageCacheSize"; // Mediaplayer public static final String PREF_PLAYBACK_SPEED = "prefPlaybackSpeed"; @@ -213,7 +214,6 @@ public class UserPreferences { public static String getPlaybackSpeed() { return prefs.getString(PREF_PLAYBACK_SPEED, "1.0"); - } public static String[] getPlaybackSpeedArray() { @@ -278,6 +278,12 @@ public class UserPreferences { return prefs.getBoolean(PREF_ENABLE_AUTODL_WIFI_FILTER, false); } + public static int getImageCacheSize() { + String cacheSizeString = prefs.getString(PREF_IMAGE_CACHE_SIZE, "100"); + int cacheSize = Integer.valueOf(cacheSizeString) * 1024 * 1024; + return cacheSize; + } + public static int getFastFowardSecs() { return prefs.getInt(PREF_FAST_FORWARD_SECS, 30); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 3df305027..19a710d24 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -777,52 +777,18 @@ public class DownloadService extends Service { for (int i = 0; i < savedFeeds.length; i++) { Feed savedFeed = savedFeeds[i]; - // Download Feed Image if provided and not downloaded - if (savedFeed.getImage() != null - && savedFeed.getImage().isDownloaded() == false) { - Log.d(TAG, "Feed has image; Downloading...."); - savedFeed.getImage().setOwner(savedFeed); - final Feed savedFeedRef = savedFeed; - try { - requester.downloadImage(DownloadService.this, - savedFeedRef.getImage()); - } catch (DownloadRequestException e) { - e.printStackTrace(); - DBWriter.addDownloadStatus( - DownloadService.this, - new DownloadStatus( - savedFeedRef.getImage(), - savedFeedRef - .getImage() - .getHumanReadableIdentifier(), - DownloadError.ERROR_REQUEST_ERROR, - false, e.getMessage() - ) - ); - } - } // queue new media files for automatic download for (FeedItem item : savedFeed.getItems()) { if(item.getPubDate() == null) { Log.d(TAG, item.toString()); } - if(item.getImage() != null && item.getImage().isDownloaded() == false) { - item.getImage().setOwner(item); - try { - requester.downloadImage(DownloadService.this, - item.getImage()); - } catch (DownloadRequestException e) { - e.printStackTrace(); - } - } if (!item.isPlayed() && item.hasMedia() && !item.getMedia().isDownloaded()) { newMediaFiles.add(item.getMedia().getId()); } } // If loadAllPages=true, check if another page is available and queue it for download - final boolean loadAllPages = results.get(i).first.getArguments().getBoolean(DownloadRequester.REQUEST_ARG_LOAD_ALL_PAGES); final Feed feed = results.get(i).second.feed; if (loadAllPages && feed.getNextPageLink() != null) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index 737f0aefd..fd8608d88 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -29,7 +29,10 @@ import android.view.KeyEvent; import android.view.SurfaceHolder; import android.widget.Toast; -import com.squareup.picasso.Picasso; +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.request.animation.GlideAnimation; +import com.bumptech.glide.request.target.SimpleTarget; import org.apache.commons.lang3.StringUtils; @@ -791,16 +794,18 @@ public class PlaybackService extends Service { Log.d(TAG, "Starting background work"); if (android.os.Build.VERSION.SDK_INT >= 11) { if (info.playable != null) { - try { - int iconSize = getResources().getDimensionPixelSize( - android.R.dimen.notification_large_icon_width); - icon = Picasso.with(PlaybackService.this) - .load(info.playable.getImageUri()) - .resize(iconSize, iconSize) - .get(); - } catch (IOException e) { - e.printStackTrace(); - } + int iconSize = getResources().getDimensionPixelSize( + android.R.dimen.notification_large_icon_width); + Glide.with(PlaybackService.this) + .load(info.playable.getImageUri()) + .asBitmap() + .diskCacheStrategy(DiskCacheStrategy.SOURCE) + .into(new SimpleTarget(iconSize, iconSize) { + @Override + public void onResourceReady(Bitmap bitmap, GlideAnimation anim) { + icon = bitmap; + } + }); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index cfbfd152b..5ed0a6ee3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -871,7 +871,11 @@ public final class DBReader { if (cursor.moveToFirst()) { String username = cursor.getString(0); String password = cursor.getString(1); - return username + ":" + password; + if(username != null && password != null) { + return username + ":" + password; + } else { + return ""; + } } return ""; } finally { diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index b08013c65..770c4f7d7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -283,24 +283,6 @@ public final class DBTasks { DownloadRequester.getInstance().downloadFeed(context, f, loadAllPages); } - /** - * Notifies the database about a missing FeedImage file. This method will attempt to re-download the file. - * - * @param context Used for requesting the download. - * @param image The FeedImage object. - */ - public static void notifyInvalidImageFile(final Context context, - final FeedImage image) { - Log.i(TAG, - "The DB was notified about an invalid image download. It will now try to re-download the image file"); - try { - DownloadRequester.getInstance().downloadImage(context, image); - } catch (DownloadRequestException e) { - e.printStackTrace(); - Log.w(TAG, "Failed to download invalid feed image"); - } - } - /** * Notifies the database about a missing FeedMedia file. This method will correct the FeedMedia object's values in the * DB and send a FeedUpdateBroadcast. diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java index ca6aa0178..74dce17f4 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java @@ -18,7 +18,6 @@ import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedFile; -import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.DownloadRequest; @@ -186,15 +185,6 @@ public class DownloadRequester { downloadFeed(context, feed, false); } - public synchronized void downloadImage(Context context, FeedImage image) - throws DownloadRequestException { - if (feedFileValid(image)) { - FeedFile container = (image.getOwner() instanceof FeedFile) ? (FeedFile) image.getOwner() : null; - download(context, image, container, new File(getImagefilePath(context), - getImagefileName(image)), false, null, null, 0, false, null); - } - } - public synchronized void downloadMedia(Context context, FeedMedia feedmedia) throws DownloadRequestException { if (feedFileValid(feedmedia)) { @@ -332,20 +322,6 @@ public class DownloadRequester { return "feed-" + FileNameGenerator.generateFileName(filename); } - public synchronized String getImagefilePath(Context context) - throws DownloadRequestException { - return getExternalFilesDirOrThrowException(context, IMAGE_DOWNLOADPATH) - .toString() + "/"; - } - - public synchronized String getImagefileName(FeedImage image) { - String filename = image.getDownload_url(); - if (image.getOwner() != null && image.getOwner().getHumanReadableIdentifier() != null) { - filename = image.getOwner().getHumanReadableIdentifier(); - } - return "image-" + FileNameGenerator.generateFileName(filename); - } - public synchronized String getMediafilePath(Context context, FeedMedia media) throws DownloadRequestException { File externalStorage = getExternalFilesDirOrThrowException( diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java index 7ebd580f7..752e95985 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java @@ -7,7 +7,7 @@ import android.util.Log; import java.util.List; -import de.danoeh.antennapod.core.asynctask.PicassoImageResource; +import de.danoeh.antennapod.core.asynctask.ImageResource; import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; @@ -18,7 +18,7 @@ import de.danoeh.antennapod.core.util.ShownotesProvider; * Interface for objects that can be played by the PlaybackService. */ public interface Playable extends Parcelable, - ShownotesProvider, PicassoImageResource { + ShownotesProvider, ImageResource { /** * Save information about the playable in a preference so that it can be diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 3c852360c..f2a80cd38 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -174,4 +174,20 @@ not_downloaded + + 20 MiB + 50 MiB + 100 MiB + 250 MiB + 500 MiB + + + + 20 + 50 + 100 + 250 + 500 + + diff --git a/core/src/main/res/values/colors.xml b/core/src/main/res/values/colors.xml index e558a5c4e..bc0521dcd 100644 --- a/core/src/main/res/values/colors.xml +++ b/core/src/main/res/values/colors.xml @@ -3,6 +3,7 @@ #FFFFFF #808080 + #bfbfbf #000000 #33B5E5 #858585 diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 5079950fa..e91030e93 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -331,12 +331,12 @@ Keep notification and lockscreen controls when playback is paused. Show Download Report If downloads fail, generate a report that shows the details of the failure. - Android versions before 4.1 do not support expanded notifications. Add new episodes to the front of the queue. Enqueue at Front Disabled - + Image Cache Size + Size of the disk cache for images. Enable automatic flattring @@ -431,6 +431,7 @@ Pause for Interruptions Resume playback after a phone call completes Resume after Call + AnntennaPod has to be restarted for this change to take effect. Subscribe @@ -464,6 +465,7 @@ Upgrading the database + Clearing old image cache diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index 8619869c8..85c908f64 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -263,7 +263,9 @@ -- cgit v1.2.3 From 66e5c4fdf1325758e03a6146703ae2fd2c68f3db Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Wed, 29 Jul 2015 18:30:29 +0200 Subject: Improve datetime parser --- .../de/danoeh/antennapod/core/util/DateUtils.java | 28 ++++++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java index 7b06128f9..c0233f684 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java @@ -8,6 +8,7 @@ import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; +import java.util.TimeZone; /** * Parses several date formats. @@ -17,50 +18,66 @@ public class DateUtils { private static final String TAG = "DateUtils"; private static final SimpleDateFormat parser = new SimpleDateFormat("", Locale.US); + private static final TimeZone defaultTimezone = TimeZone.getTimeZone("GMT"); + static { parser.setLenient(false); + parser.setTimeZone(defaultTimezone); } public static Date parse(final String input) { if(input == null) { - throw new IllegalArgumentException("Date most not be null"); + throw new IllegalArgumentException("Date must not be null"); } - String date = input.replace('/', '-'); + String date = input.trim().replace('/', '-').replaceAll("( ){2,}+", " "); + + // if datetime is more precise than seconds, make sure the value is in ms if(date.contains(".")) { int start = date.indexOf('.'); int current = start+1; while(current < date.length() && Character.isDigit(date.charAt(current))) { current++; } + // even more precise than microseconds: discard further decimal places if(current - start > 4) { if(current < date.length()-1) { date = date.substring(0, start + 4) + date.substring(current); } else { date = date.substring(0, start + 4); } + // less than 4 decimal places: pad to have a consistent format for the parser } else if(current - start < 4) { if(current < date.length()-1) { date = date.substring(0, current) + StringUtils.repeat("0", 4-(current-start)) + date.substring(current); } else { date = date.substring(0, current) + StringUtils.repeat("0", 4-(current-start)); } - } } String[] patterns = { "dd MMM yy HH:mm:ss Z", "dd MMM yy HH:mm Z", "EEE, dd MMM yyyy HH:mm:ss Z", + "EEE, dd MMM yyyy HH:mm:ss", "EEE, dd MMMM yyyy HH:mm:ss Z", + "EEE, dd MMMM yyyy HH:mm:ss", + "EEEE, dd MMM yyyy HH:mm:ss Z", "EEEE, dd MMM yy HH:mm:ss Z", + "EEEE, dd MMM yyyy HH:mm:ss", + "EEEE, dd MMM yy HH:mm:ss", "EEE MMM d HH:mm:ss yyyy", "EEE, dd MMM yyyy HH:mm Z", + "EEE, dd MMM yyyy HH:mm", "EEE, dd MMMM yyyy HH:mm Z", + "EEE, dd MMMM yyyy HH:mm", + "EEEE, dd MMM yyyy HH:mm Z", "EEEE, dd MMM yy HH:mm Z", + "EEEE, dd MMM yyyy HH:mm", + "EEEE, dd MMM yy HH:mm", "EEE MMM d HH:mm yyyy", "yyyy-MM-dd'T'HH:mm:ss", - "yyyy-MM-dd'T'HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ss.SSS Z", + "yyyy-MM-dd'T'HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ssZ", "yyyy-MM-dd'T'HH:mm:ss'Z'", "yyyy-MM-ddZ", @@ -77,7 +94,7 @@ public class DateUtils { } } - Log.d(TAG, "Could not parse date string \"" + input + "\""); + Log.d(TAG, "Could not parse date string \"" + input + "\" [" + date + "]"); return null; } @@ -117,6 +134,7 @@ public class DateUtils { public static String formatRFC3339UTC(Date date) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); + format.setTimeZone(defaultTimezone); return format.format(date); } } -- cgit v1.2.3 From 5f41d422aa4b68ebf853101d4c3488f5c711540e Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Wed, 29 Jul 2015 20:36:27 +0200 Subject: Retro-actively disable auto download for episodes that were downloaded, were partially or completely played and are not queued currently --- .../main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index d0402710c..c7eadcbb6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -1477,7 +1477,7 @@ public class PodDBAdapter { */ private static class PodDBHelper extends SQLiteOpenHelper { - private final static int VERSION = 18; + private final static int VERSION = 1030002; private Context context; @@ -1702,6 +1702,11 @@ public class PodDBAdapter { db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0"); } + if(oldVersion < 1030002) { + db.execSQL("UPDATE FeedItems SET auto_download=0 WHERE " + + "(read=1 OR id IN (SELECT id FROM FeedMedia WHERE position>0 OR downloaded=1)) " + + "AND id NOT IN (SELECT feeditem FROM Queue)"); + } EventBus.getDefault().post(ProgressEvent.end()); } } -- cgit v1.2.3 From 4f7566ddfca14754ebe28cd49e63a1db0c992d78 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 31 Jul 2015 10:50:38 +0200 Subject: Improved blurring --- .../core/glide/FastBlurTransformation.java | 40 ++++++++-------------- core/src/main/res/values/strings.xml | 1 - 2 files changed, 15 insertions(+), 26 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java index f5e645535..ee58c2f39 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/FastBlurTransformation.java @@ -2,6 +2,7 @@ package de.danoeh.antennapod.core.glide; import android.content.Context; import android.graphics.Bitmap; +import android.media.ThumbnailUtils; import android.util.Log; import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; @@ -9,33 +10,35 @@ import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; public class FastBlurTransformation extends BitmapTransformation { - private static final String TAG = "BlurTransformation"; + private static final String TAG = FastBlurTransformation.class.getSimpleName(); - private static final int RADIUS = 1; - private static final int IMAGE_SIZE = 192; + private static final int STACK_BLUR_RADIUS = 1; + private static final int BLUR_IMAGE_WIDTH = 150; public FastBlurTransformation(Context context) { super(context); } @Override - protected Bitmap transform(BitmapPool pool, Bitmap toTransform, + protected Bitmap transform(BitmapPool pool, Bitmap source, int outWidth, int outHeight) { - Bitmap resizedBitmap = Bitmap.createScaledBitmap(toTransform, IMAGE_SIZE, IMAGE_SIZE, true); - Bitmap transformed = fastBlur(resizedBitmap, RADIUS); - if (transformed == null) { - Log.w(TAG, "transformed was null"); - return toTransform; + int targetWidth = BLUR_IMAGE_WIDTH; + int targetHeight = (int) (1.0 * outHeight * targetWidth / outWidth); + Bitmap resized = ThumbnailUtils.extractThumbnail(source, targetWidth, targetHeight); + Bitmap result = fastBlur(resized, STACK_BLUR_RADIUS); + if (result == null) { + Log.w(TAG, "result was null"); + return source; } - return transformed; + return result; } @Override public String getId() { - return "FastBlurTransformation-" + IMAGE_SIZE + "x" + IMAGE_SIZE + "-" + RADIUS; + return "FastBlurTransformation[width=" + BLUR_IMAGE_WIDTH + "px,radius=" + STACK_BLUR_RADIUS +"]"; } - private static Bitmap fastBlur(Bitmap original, int radius) { + private static Bitmap fastBlur(Bitmap bitmap, int radius) { // Stack Blur v1.0 from // http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html @@ -65,15 +68,6 @@ public class FastBlurTransformation extends BitmapTransformation { // // Stack Blur Algorithm by Mario Klingemann - Bitmap.Config config = original.getConfig(); - if (config == null) { - // Sometimes the config can be null, in those cases - // we don't do a transform. - return null; - } - - Bitmap bitmap = original.copy(config, true); - if (radius < 1) { return null; } @@ -82,7 +76,6 @@ public class FastBlurTransformation extends BitmapTransformation { int h = bitmap.getHeight(); int[] pix = new int[w * h]; - Log.e("pix", w + " " + h + " " + pix.length); bitmap.getPixels(pix, 0, w, 0, 0, w, h); int wm = w - 1; @@ -267,10 +260,7 @@ public class FastBlurTransformation extends BitmapTransformation { yi += w; } } - - Log.e("pix", w + " " + h + " " + pix.length); bitmap.setPixels(pix, 0, w, 0, 0, w, h); - return bitmap; } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index e91030e93..21a35cdb7 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -465,7 +465,6 @@ Upgrading the database - Clearing old image cache -- cgit v1.2.3 From cf519ca0aa1637c716a780b9a2f855a83fb1d6af Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 1 Aug 2015 12:17:50 +0200 Subject: Dialog when podcast's auto download preference is changed When the user changes a podcast's auto download setting, ask if this new setting should be applied to the podcast's episodes --- .../antennapod/core/dialog/ConfirmationDialog.java | 10 ++++----- .../danoeh/antennapod/core/storage/DBWriter.java | 25 ++++++++++++++++++++++ .../antennapod/core/storage/PodDBAdapter.java | 7 ++++++ core/src/main/res/values/strings.xml | 2 ++ 4 files changed, 39 insertions(+), 5 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java b/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java index ba1add895..ffaed084a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java +++ b/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java @@ -4,7 +4,7 @@ import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.util.Log; -import de.danoeh.antennapod.core.BuildConfig; + import de.danoeh.antennapod.core.R; /** @@ -12,9 +12,10 @@ import de.danoeh.antennapod.core.R; * classes can handle events like confirmation or cancellation. */ public abstract class ConfirmationDialog { - private static final String TAG = "ConfirmationDialog"; - Context context; + private static final String TAG = ConfirmationDialog.class.getSimpleName(); + + protected Context context; int titleId; int messageId; @@ -25,8 +26,7 @@ public abstract class ConfirmationDialog { } public void onCancelButtonPressed(DialogInterface dialog) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Dialog was cancelled"); + Log.d(TAG, "Dialog was cancelled"); dialog.dismiss(); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index acdcf5f85..12bc208a6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java @@ -1110,9 +1110,34 @@ public class DBWriter { EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); } }); + } + + /** + * Sets the 'auto_download'-attribute of specific FeedItem. + * + * @param context A context that is used for opening a database connection. + * @param feed This feed's episodes will be processed. + * @param autoDownload If true, auto download will be enabled for the feed's episodes. Else, + * it will be disabled. + */ + public static Future setFeedsItemsAutoDownload(final Context context, final Feed feed, + final boolean autoDownload) { + Log.d(TAG, (autoDownload ? "Enabling" : "Disabling") + " auto download for items of feed " + feed.getId()); + return dbExec.submit(new Runnable() { + @Override + public void run() { + final PodDBAdapter adapter = new PodDBAdapter(context); + adapter.open(); + adapter.setFeedsItemsAutoDownload(feed, autoDownload); + adapter.close(); + + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + } + }); } + /** * Set filter of the feed * diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index d0402710c..a1f11a1b6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -861,6 +861,13 @@ public class PodDBAdapter { new String[]{String.valueOf(feedItem.getId())}); } + public void setFeedsItemsAutoDownload(Feed feed, boolean autoDownload) { + final String sql = "UPDATE " + TABLE_NAME_FEED_ITEMS + + " SET " + KEY_AUTO_DOWNLOAD + "="+ (autoDownload ? "1" : "0") + + " WHERE " + KEY_FEED + "=" + feed.getId(); + db.execSQL(sql); + } + public long getDownloadLogSize() { final String query = String.format("SELECT COUNT(%s) FROM %s", KEY_ID, TABLE_NAME_DOWNLOAD_LOG); Cursor result = db.rawQuery(query, null); diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 5079950fa..3a9e30ea6 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -75,6 +75,8 @@ Close Retry Include in auto downloads + Apply Setting to Episodes + Do you want to apply the podcast\'s new Auto Download setting to all of its episodes? Auto Delete Episode\n(override global default) \u0020parallel downloads Global -- cgit v1.2.3 From d9f8dc53a6bd5b812f27656faea00de5d2f71b5f Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 28 Jun 2015 21:55:38 -0400 Subject: removed flattr this app button --- .../main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java | 2 -- 1 file changed, 2 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java index 50792ae26..502b23a89 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java @@ -42,8 +42,6 @@ public class FlattrUtils { private static final String PREF_ACCESS_TOKEN = "de.danoeh.antennapod.preference.flattrAccessToken"; - // Flattr URL for this app. - public static final String APP_URL = "http://antennapod.com"; // Human-readable flattr-page. public static final String APP_LINK = "https://flattr.com/thing/745609/"; public static final String APP_THING_ID = "745609"; -- cgit v1.2.3 From 8cb5f68dd7f0b050e8d51f4b5f3320c6bad8c9f4 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 1 Aug 2015 10:49:18 -0400 Subject: removed unused code. fixes AntennaPod/AntennaPod#935 --- .../antennapod/core/util/flattr/FlattrUtils.java | 47 ---------------------- 1 file changed, 47 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java index 502b23a89..3b9e6120c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java @@ -42,10 +42,6 @@ public class FlattrUtils { private static final String PREF_ACCESS_TOKEN = "de.danoeh.antennapod.preference.flattrAccessToken"; - // Human-readable flattr-page. - public static final String APP_LINK = "https://flattr.com/thing/745609/"; - public static final String APP_THING_ID = "745609"; - private static volatile AccessToken cachedToken; private static AndroidAuthenticator createAuthenticator() { @@ -108,18 +104,6 @@ public class FlattrUtils { storeToken(null); } - public static Thing getAppThing(Context context) { - FlattrService fs = FlattrServiceCreator.getService(retrieveToken()); - try { - Thing thing = fs.getThing(Thing.withId(APP_THING_ID)); - return thing; - } catch (FlattrException e) { - e.printStackTrace(); - showErrorDialog(context, e.getMessage()); - return null; - } - } - public static void clickUrl(Context context, String url) throws FlattrException { if (hasToken()) { @@ -243,37 +227,6 @@ public class FlattrUtils { } } - public static void showForbiddenDialog(final Context context, - final String url) { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(R.string.action_forbidden_title); - builder.setMessage(R.string.action_forbidden_msg); - builder.setPositiveButton(R.string.authenticate_now_label, - new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - context.startActivity( - ClientConfig.flattrCallbacks.getFlattrAuthenticationActivityIntent(context)); - } - - } - ); - builder.setNegativeButton(R.string.visit_website_label, - new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - Uri uri = Uri.parse(url); - context.startActivity(new Intent(Intent.ACTION_VIEW, - uri)); - } - - } - ); - builder.create().show(); - } - public static void showErrorDialog(final Context context, final String msg) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.error_label); -- cgit v1.2.3 From a9d353ea2bd35c582f52b8ec37a4c10a9c35e98e Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 1 Aug 2015 11:07:46 -0400 Subject: removed unused method --- core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java index 96a6c2ba1..12b9a7db5 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java @@ -274,11 +274,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr public void setContentEncoded(String contentEncoded) { this.contentEncoded = contentEncoded; } - - public void setFlattrStatus(FlattrStatus status) { - this.flattrStatus = status; - } - + public FlattrStatus getFlattrStatus() { return flattrStatus; } -- cgit v1.2.3 From a3ea16b90c7a9183e1fc856e44f9e5970ab4d196 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 1 Aug 2015 17:53:06 +0200 Subject: Made dialog better, not to say awesome --- .../antennapod/core/dialog/ConfirmationDialog.java | 16 ++++++++++++++-- core/src/main/res/values/strings.xml | 6 ++++-- 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java b/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java index ffaed084a..fea2bbb2b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java +++ b/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java @@ -19,6 +19,9 @@ public abstract class ConfirmationDialog { int titleId; int messageId; + int positiveText; + int negativeText; + public ConfirmationDialog(Context context, int titleId, int messageId) { this.context = context; this.titleId = titleId; @@ -30,13 +33,22 @@ public abstract class ConfirmationDialog { dialog.dismiss(); } + public void setPositiveText(int id) { + this.positiveText = id; + } + + public void setNegativeText(int id) { + this.negativeText = id; + } + + public abstract void onConfirmButtonPressed(DialogInterface dialog); public final AlertDialog createNewDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(titleId); builder.setMessage(messageId); - builder.setPositiveButton(R.string.confirm_label, + builder.setPositiveButton(positiveText != 0 ? positiveText : R.string.confirm_label, new DialogInterface.OnClickListener() { @Override @@ -44,7 +56,7 @@ public abstract class ConfirmationDialog { onConfirmButtonPressed(dialog); } }); - builder.setNegativeButton(R.string.cancel_label, + builder.setNegativeButton(negativeText != 0 ? negativeText : R.string.cancel_label, new DialogInterface.OnClickListener() { @Override diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 3a9e30ea6..a692dbc73 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -53,6 +53,8 @@ Confirm Cancel + Yes + No Author Language URL @@ -75,8 +77,8 @@ Close Retry Include in auto downloads - Apply Setting to Episodes - Do you want to apply the podcast\'s new Auto Download setting to all of its episodes? + Apply to Previous Episodes + The new Auto Download setting will automatically be applied to new episodes.\nDo you also want to apply it to previous episodes? Auto Delete Episode\n(override global default) \u0020parallel downloads Global -- cgit v1.2.3 From fcd6284135f63d19c025444f24a527eea8ed234b Mon Sep 17 00:00:00 2001 From: Katrin Leinweber Date: Sat, 1 Aug 2015 20:48:12 +0200 Subject: add only 72h, due to 168h criticism --- core/src/main/res/values/arrays.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 2bb5a5e1b..4c810edfe 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -30,10 +30,10 @@ 1 2 4 + 8 12 24 72 - 168 @string/pref_episode_cache_unlimited -- cgit v1.2.3 From 65d470043baf7f3f7d7009d16255e33b68af3650 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 2 Aug 2015 17:43:41 +0200 Subject: Fix duration overflow and time unit plurals --- .../java/de/danoeh/antennapod/core/util/Converter.java | 16 ++++++++-------- core/src/main/res/values/strings.xml | 15 ++++++++++++--- 2 files changed, 20 insertions(+), 11 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java b/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java index 917f99564..2bf88b3f3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java @@ -26,7 +26,7 @@ public final class Converter { /** Determines the length of the number for best readability.*/ private static final int NUM_LENGTH = 1024; - + private static final int DAYS_MIL = 86400000; private static final int HOURS_MIL = 3600000; private static final int MINUTES_MIL = 60000; private static final int SECONDS_MIL = 1000; @@ -104,18 +104,18 @@ public final class Converter { } /** Converts milliseconds to a localized string containing hours and minutes */ - public static String getDurationStringLocalized(Context context, int duration) { - int h = duration / HOURS_MIL; - int rest = duration - h * HOURS_MIL; + public static String getDurationStringLocalized(Context context, long duration) { + int h = (int)(duration / HOURS_MIL); + int rest = (int)(duration - h * HOURS_MIL); int m = rest / MINUTES_MIL; String result = ""; if(h > 0) { - String hours = context.getString(R.string.time_unit_hours); - result += h + " " + hours + " "; + String hours = context.getResources().getQuantityString(R.plurals.time_unit_hours, h, h); + result += hours + " "; } - String minutes = context.getString(R.string.time_unit_minutes); - result += m + " " + minutes; + String minutes = context.getResources().getQuantityString(R.plurals.time_unit_minutes, m, m); + result += minutes; return result; } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 21a35cdb7..eca366a2d 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -380,9 +380,18 @@ Sleep timer Time left:\u0020 Invalid input, time has to be an integer - seconds - minutes - hours + + 1 second + %d seconds + + + 1 minute + %d minutes + + + 1 hour + %d hours + CATEGORIES -- cgit v1.2.3 From ab116ee6be1c268787cc3496ae257990ec42a560 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 2 Aug 2015 17:48:08 +0200 Subject: Initialize NetworkUtils, set context once Had some issues with the new NetworkAllowanceInterceptor. When I gave it a constructor that would hold the context (to use it with NetworkUtils), the whole Glide image loading process would not work. --- .../core/asynctask/FlattrClickWorker.java | 2 +- .../core/receiver/FeedUpdateReceiver.java | 2 +- .../core/service/FeedMediaSizeService.java | 4 +-- .../core/service/GpodnetSyncService.java | 2 +- .../core/storage/APDownloadAlgorithm.java | 2 +- .../danoeh/antennapod/core/util/NetworkUtils.java | 31 ++++++++++------------ 6 files changed, 20 insertions(+), 23 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java index 5d2d5d441..f91d4557e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java @@ -90,7 +90,7 @@ public class FlattrClickWorker extends AsyncTask list = DBReader.getFeedMediaUnknownSize(this); for (FeedMedia media : list) { Log.d(TAG, "Getting size currently " + media.getSize() + " for " + media.getDownload_url()); - if(false == NetworkUtils.isDownloadAllowed(this)) { + if(false == NetworkUtils.isDownloadAllowed()) { return; } long size = Integer.MIN_VALUE; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java index 3f2222f42..b80b4303f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java @@ -108,7 +108,7 @@ public class GpodnetSyncService extends Service { private synchronized void sync() { - if (GpodnetPreferences.loggedIn() == false || NetworkUtils.networkAvailable(this) == false) { + if (GpodnetPreferences.loggedIn() == false || NetworkUtils.networkAvailable() == false) { stopSelf(); return; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java index 92de1eee7..0e6b23696 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java @@ -40,7 +40,7 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm { public void run() { // true if we should auto download based on network status - boolean networkShouldAutoDl = NetworkUtils.autodownloadNetworkAvailable(context) + boolean networkShouldAutoDl = NetworkUtils.autodownloadNetworkAvailable() && UserPreferences.isEnableAutodownload(); // true if we should auto download based on power status diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java index 3a349e221..9296039f0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/NetworkUtils.java @@ -10,14 +10,16 @@ import android.util.Log; import java.util.Arrays; import java.util.List; -import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.preferences.UserPreferences; public class NetworkUtils { - private static final String TAG = "NetworkUtils"; - private NetworkUtils() { + private static final String TAG = NetworkUtils.class.getSimpleName(); + private static Context context; + + public static void init(Context context) { + NetworkUtils.context = context; } /** @@ -26,18 +28,16 @@ public class NetworkUtils { * network that is on the 'selected networks' list of the Wi-Fi filter for * automatic downloads and false otherwise. * */ - public static boolean autodownloadNetworkAvailable(Context context) { + public static boolean autodownloadNetworkAvailable() { ConnectivityManager cm = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = cm.getActiveNetworkInfo(); if (networkInfo != null) { if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Device is connected to Wi-Fi"); + Log.d(TAG, "Device is connected to Wi-Fi"); if (networkInfo.isConnected()) { if (!UserPreferences.isEnableAutodownloadWifiFilter()) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Auto-dl filter is disabled"); + Log.d(TAG, "Auto-dl filter is disabled"); return true; } else { WifiManager wm = (WifiManager) context @@ -48,31 +48,28 @@ public class NetworkUtils { .getAutodownloadSelectedNetworks()); if (selectedNetworks.contains(Integer.toString(wifiInfo .getNetworkId()))) { - if (BuildConfig.DEBUG) - Log.d(TAG, - "Current network is on the selected networks list"); + Log.d(TAG, "Current network is on the selected networks list"); return true; } } } } } - if (BuildConfig.DEBUG) - Log.d(TAG, "Network for auto-dl is not available"); + Log.d(TAG, "Network for auto-dl is not available"); return false; } - public static boolean networkAvailable(Context context) { + public static boolean networkAvailable() { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo info = cm.getActiveNetworkInfo(); return info != null && info.isConnected(); } - public static boolean isDownloadAllowed(Context context) { - return UserPreferences.isAllowMobileUpdate() || NetworkUtils.connectedToWifi(context); + public static boolean isDownloadAllowed() { + return UserPreferences.isAllowMobileUpdate() || NetworkUtils.connectedToWifi(); } - public static boolean connectedToWifi(Context context) { + public static boolean connectedToWifi() { ConnectivityManager connManager = (ConnectivityManager) context .getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo mWifi = connManager -- cgit v1.2.3 From 0824af6325e18d9b3c10d43807b94ba3f6ad88da Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 2 Aug 2015 17:49:52 +0200 Subject: Fix loading the notification image --- .../core/service/playback/PlaybackService.java | 56 +++++++++------------- 1 file changed, 23 insertions(+), 33 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index fd8608d88..aa1816e1c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -38,6 +38,7 @@ import org.apache.commons.lang3.StringUtils; import java.io.IOException; import java.util.List; +import java.util.concurrent.ExecutionException; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.R; @@ -772,7 +773,7 @@ public class PlaybackService extends Service { /** * Used by setupNotification to load notification data in another thread. */ - private AsyncTask notificationSetupTask; + private Thread notificationSetupThread; /** * Prepares notification and starts the service in the foreground. @@ -783,52 +784,47 @@ public class PlaybackService extends Service { PlaybackService.getPlayerActivityIntent(this), PendingIntent.FLAG_UPDATE_CURRENT); - if (notificationSetupTask != null) { - notificationSetupTask.cancel(true); + if (notificationSetupThread != null) { + notificationSetupThread.interrupt(); } - notificationSetupTask = new AsyncTask() { + Runnable notificationSetupTask = new Runnable() { Bitmap icon = null; @Override - protected Void doInBackground(Void... params) { + public void run() { Log.d(TAG, "Starting background work"); if (android.os.Build.VERSION.SDK_INT >= 11) { if (info.playable != null) { int iconSize = getResources().getDimensionPixelSize( android.R.dimen.notification_large_icon_width); - Glide.with(PlaybackService.this) - .load(info.playable.getImageUri()) - .asBitmap() - .diskCacheStrategy(DiskCacheStrategy.SOURCE) - .into(new SimpleTarget(iconSize, iconSize) { - @Override - public void onResourceReady(Bitmap bitmap, GlideAnimation anim) { - icon = bitmap; - } - }); + try { + icon = Glide.with(PlaybackService.this) + .load(info.playable.getImageUri()) + .asBitmap() + .diskCacheStrategy(DiskCacheStrategy.SOURCE) + .into(-1, -1) // this resizing would not be exact, so we have + // scale the bitmap ourselves + .get(); + icon = Bitmap.createScaledBitmap(icon, iconSize, iconSize, true); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } } - } if (icon == null) { icon = BitmapFactory.decodeResource(getApplicationContext().getResources(), ClientConfig.playbackServiceCallbacks.getNotificationIconResource(getApplicationContext())); } - return null; - } - - @Override - protected void onPostExecute(Void result) { - super.onPostExecute(result); if (mediaPlayer == null) { return; } PlayerStatus playerStatus = mediaPlayer.getPlayerStatus(); final int smallIcon = ClientConfig.playbackServiceCallbacks.getNotificationIconResource(getApplicationContext()); - if (!isCancelled() && - started && - info.playable != null) { + if (!Thread.currentThread().isInterrupted() && started && info.playable != null) { String contentText = info.playable.getFeedTitle(); String contentTitle = info.playable.getEpisodeTitle(); Notification notification = null; @@ -906,15 +902,9 @@ public class PlaybackService extends Service { Log.d(TAG, "Notification set up"); } } - }; - if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) { - notificationSetupTask - .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - } else { - notificationSetupTask.execute(); - } - + notificationSetupThread = new Thread(notificationSetupTask); + notificationSetupThread.start(); } /** -- cgit v1.2.3 From 4165d848d8d8956c4fa14002920ec17729551b34 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 2 Aug 2015 17:51:33 +0200 Subject: Respect the mobile download settings --- .../antennapod/core/glide/ApOkHttpUrlLoader.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java index 33290723b..433ba8db4 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java @@ -21,18 +21,20 @@ import java.net.HttpURLConnection; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.service.download.HttpDownloader; import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.core.util.NetworkUtils; /** * @see com.bumptech.glide.integration.okhttp.OkHttpUrlLoader */ public class ApOkHttpUrlLoader implements ModelLoader { - private static final String TAG = "ApOkHttpUrlLoader"; + private static final String TAG = ApOkHttpUrlLoader.class.getSimpleName(); /** * The default factory for {@link ApOkHttpUrlLoader}s. */ public static class Factory implements ModelLoaderFactory { + private static volatile OkHttpClient internalClient; private OkHttpClient client; @@ -41,6 +43,7 @@ public class ApOkHttpUrlLoader implements ModelLoader { synchronized (Factory.class) { if (internalClient == null) { internalClient = new OkHttpClient(); + internalClient.interceptors().add(new NetworkAllowanceInterceptor()); internalClient.interceptors().add(new BasicAuthenticationInterceptor()); } } @@ -84,6 +87,19 @@ public class ApOkHttpUrlLoader implements ModelLoader { return new OkHttpStreamFetcher(client, model); } + private static class NetworkAllowanceInterceptor implements Interceptor { + + @Override + public Response intercept(Chain chain) throws IOException { + if (NetworkUtils.isDownloadAllowed()) { + return chain.proceed(chain.request()); + } else { + return null; + } + } + + } + private static class BasicAuthenticationInterceptor implements Interceptor { @Override -- cgit v1.2.3 From 6c82db167588579c78c9bc273cd4b78ae2786ca2 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 2 Aug 2015 17:51:44 +0200 Subject: Remove unused class --- .../core/glide/ApOkHttpStreamFetcher.java | 80 ---------------------- 1 file changed, 80 deletions(-) delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpStreamFetcher.java (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpStreamFetcher.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpStreamFetcher.java deleted file mode 100644 index 13a148d1e..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpStreamFetcher.java +++ /dev/null @@ -1,80 +0,0 @@ -package de.danoeh.antennapod.core.glide; - -import com.bumptech.glide.Priority; -import com.bumptech.glide.load.data.DataFetcher; -import com.bumptech.glide.load.model.GlideUrl; -import com.bumptech.glide.util.ContentLengthInputStream; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; -import com.squareup.okhttp.ResponseBody; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Map; - -/** - * @see com.bumptech.glide.integration.okhttp.OkHttpStreamFetcher - */ -public class ApOkHttpStreamFetcher implements DataFetcher { - private final OkHttpClient client; - private final GlideUrl url; - private InputStream stream; - private ResponseBody responseBody; - - public ApOkHttpStreamFetcher(OkHttpClient client, GlideUrl url) { - this.client = client; - this.url = url; - } - - @Override - public InputStream loadData(Priority priority) throws Exception { - Request.Builder requestBuilder = new Request.Builder() - .url(url.toStringUrl()); - - for (Map.Entry headerEntry : url.getHeaders().entrySet()) { - String key = headerEntry.getKey(); - requestBuilder.addHeader(key, headerEntry.getValue()); - } - - Request request = requestBuilder.build(); - - Response response = client.newCall(request).execute(); - responseBody = response.body(); - if (!response.isSuccessful()) { - throw new IOException("Request failed with code: " + response.code()); - } - - long contentLength = responseBody.contentLength(); - stream = ContentLengthInputStream.obtain(responseBody.byteStream(), contentLength); - return stream; - } - - @Override - public void cleanup() { - if (stream != null) { - try { - stream.close(); - } catch (IOException e) { - // Ignored - } - } - if (responseBody != null) { - try { - responseBody.close(); - } catch (IOException e) { - // Ignored. - } - } - } - - @Override - public String getId() { - return url.getCacheKey(); - } - - @Override - public void cancel() { - // TODO: call cancel on the client when this method is called on a background thread. See #257 - } -} \ No newline at end of file -- cgit v1.2.3 From dfc97dcd62f30ebbb56dc87afc55bfc21c13148e Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 2 Aug 2015 14:14:44 -0400 Subject: merged 1.2.2 changes to develop --- .../main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java index 74dce17f4..bc34523cc 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java @@ -170,7 +170,7 @@ public class DownloadRequester { if (feedFileValid(feed)) { String username = (feed.getPreferences() != null) ? feed.getPreferences().getUsername() : null; String password = (feed.getPreferences() != null) ? feed.getPreferences().getPassword() : null; - long ifModifiedSince = feed.getLastUpdate().getTime(); + long ifModifiedSince = feed.isPaged() ? 0 : feed.getLastUpdate().getTime(); Bundle args = new Bundle(); args.putInt(REQUEST_ARG_PAGE_NR, feed.getPageNr()); -- cgit v1.2.3 From 744f3d6442d04428f9b74206c8aaae972d99727a Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 2 Aug 2015 14:45:22 -0400 Subject: fixed typo --- core/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 23c58d16f..7ec9bd508 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -444,7 +444,7 @@ Pause for Interruptions Resume playback after a phone call completes Resume after Call - AnntennaPod has to be restarted for this change to take effect. + AntennaPod has to be restarted for this change to take effect. Subscribe -- cgit v1.2.3 From 6c4afc4711e1c4e7eac9528fa9582b0106456656 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 2 Aug 2015 16:39:04 -0400 Subject: we can have both strings and plurals with the same name. fixes AntennaPod/AntennaPod#1050 --- core/src/main/res/values/strings.xml | 3 +++ 1 file changed, 3 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 23c58d16f..c36cde6f7 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -384,6 +384,9 @@ Sleep timer Time left:\u0020 Invalid input, time has to be an integer + seconds + minutes + hours 1 second %d seconds -- cgit v1.2.3 From dbaae4aa69b20ab6a650be73aeb944157ad8b43f Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 2 Aug 2015 18:19:38 -0400 Subject: Fixes pictures disappearing in some cases * Default value for the image cache size should be > 0 * If the image cache size is too small we force it back to default * We should only have once instance of the HTTP client fixes AntennaPod/AntennaPod/#1053 --- .../danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java | 3 ++- .../antennapod/core/preferences/UserPreferences.java | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java index 433ba8db4..c7ac146b5 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java @@ -19,6 +19,7 @@ import java.io.InputStream; import java.net.HttpURLConnection; import de.danoeh.antennapod.core.ClientConfig; +import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.service.download.HttpDownloader; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.util.NetworkUtils; @@ -42,7 +43,7 @@ public class ApOkHttpUrlLoader implements ModelLoader { if (internalClient == null) { synchronized (Factory.class) { if (internalClient == null) { - internalClient = new OkHttpClient(); + internalClient = AntennapodHttpClient.getHttpClient(); internalClient.interceptors().add(new NetworkAllowanceInterceptor()); internalClient.interceptors().add(new BasicAuthenticationInterceptor()); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index 789a2366e..0eae8b837 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -85,6 +85,8 @@ public class UserPreferences { private static final String PREF_FAST_FORWARD_SECS = "prefFastForwardSecs"; private static final String PREF_REWIND_SECS = "prefRewindSecs"; public static final String PREF_QUEUE_LOCKED = "prefQueueLocked"; + public static final String IMAGE_CACHE_DEFAULT_VALUE = "100"; + public static final int IMAGE_CACHE_SIZE_MINIMUM = 20; // Constants private static int EPISODE_CACHE_SIZE_UNLIMITED = -1; @@ -279,9 +281,16 @@ public class UserPreferences { } public static int getImageCacheSize() { - String cacheSizeString = prefs.getString(PREF_IMAGE_CACHE_SIZE, "100"); - int cacheSize = Integer.valueOf(cacheSizeString) * 1024 * 1024; - return cacheSize; + String cacheSizeString = prefs.getString(PREF_IMAGE_CACHE_SIZE, IMAGE_CACHE_DEFAULT_VALUE); + int cacheSizeInt = Integer.valueOf(cacheSizeString); + // if the cache size is too small the user won't get any images at all + // that's bad, force it back to the default. + if (cacheSizeInt < IMAGE_CACHE_SIZE_MINIMUM) { + prefs.edit().putString(PREF_IMAGE_CACHE_SIZE, IMAGE_CACHE_DEFAULT_VALUE).commit(); + cacheSizeInt = Integer.valueOf(IMAGE_CACHE_DEFAULT_VALUE); + } + int cacheSizeMB = cacheSizeInt * 1024 * 1024; + return cacheSizeMB; } public static int getFastFowardSecs() { -- cgit v1.2.3 From f799ad5ed58391ff841b1c19366c6558e99411b4 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 2 Aug 2015 18:27:36 -0400 Subject: Changed string names relating to time units. Android can handle plurals and strings having the same names, but Transifex can't. Renamed the time_unit*'s to just time_ to make sure we got the correct translations. --- .../main/java/de/danoeh/antennapod/core/util/Converter.java | 4 ++-- core/src/main/res/values/strings.xml | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java b/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java index 2bf88b3f3..1b929b214 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/Converter.java @@ -111,10 +111,10 @@ public final class Converter { String result = ""; if(h > 0) { - String hours = context.getResources().getQuantityString(R.plurals.time_unit_hours, h, h); + String hours = context.getResources().getQuantityString(R.plurals.time_hours_quantified, h, h); result += hours + " "; } - String minutes = context.getResources().getQuantityString(R.plurals.time_unit_minutes, m, m); + String minutes = context.getResources().getQuantityString(R.plurals.time_minutes_quantified, m, m); result += minutes; return result; } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 8db8f8d78..b0ebef3da 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -384,18 +384,18 @@ Sleep timer Time left:\u0020 Invalid input, time has to be an integer - seconds - minutes - hours - + seconds + minutes + hours + 1 second %d seconds - + 1 minute %d minutes - + 1 hour %d hours -- cgit v1.2.3 From 3174c338bdc38ddfbdfaf9b7c23ed16e85a7d3de Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 2 Aug 2015 21:09:52 -0400 Subject: Should call apply instead of commit since it is asynchronous. --- .../java/de/danoeh/antennapod/core/preferences/UserPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index 0eae8b837..d56829c70 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -286,7 +286,7 @@ public class UserPreferences { // if the cache size is too small the user won't get any images at all // that's bad, force it back to the default. if (cacheSizeInt < IMAGE_CACHE_SIZE_MINIMUM) { - prefs.edit().putString(PREF_IMAGE_CACHE_SIZE, IMAGE_CACHE_DEFAULT_VALUE).commit(); + prefs.edit().putString(PREF_IMAGE_CACHE_SIZE, IMAGE_CACHE_DEFAULT_VALUE).apply(); cacheSizeInt = Integer.valueOf(IMAGE_CACHE_DEFAULT_VALUE); } int cacheSizeMB = cacheSizeInt * 1024 * 1024; -- cgit v1.2.3 From 008347313f0481e2096b70e2d494055d9e9ebb66 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 4 Aug 2015 21:09:55 -0400 Subject: 'feeditem' is the id of the FeedItem SQL statement previously used 'id' which was actually the id of the FeedMedia item and not the FeedItem --- core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index f9ac39349..904a416df 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -1711,7 +1711,7 @@ public class PodDBAdapter { } if(oldVersion < 1030002) { db.execSQL("UPDATE FeedItems SET auto_download=0 WHERE " + - "(read=1 OR id IN (SELECT id FROM FeedMedia WHERE position>0 OR downloaded=1)) " + + "(read=1 OR id IN (SELECT feeditem FROM FeedMedia WHERE position>0 OR downloaded=1)) " + "AND id NOT IN (SELECT feeditem FROM Queue)"); } EventBus.getDefault().post(ProgressEvent.end()); -- cgit v1.2.3 From fe6796f102bb8c126cfad80d957bffe0cb04fa34 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 4 Aug 2015 21:25:25 -0400 Subject: Updated version code for RC5 Also updated the oldVersion used by the UPDATE FeedItems sql statement. We don't want to run the 1030002 version ever, and the 1030005 version should fix any users that used the 1030002 version (with the possibility that some items that shouldn't have had auto_download set to 0 did have it set to 0, but accepting that that's not a terrible problem). --- core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 904a416df..edb7598ab 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java @@ -1709,7 +1709,7 @@ public class PodDBAdapter { db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS + " ADD COLUMN " + PodDBAdapter.KEY_AUTO_DELETE_ACTION + " INTEGER DEFAULT 0"); } - if(oldVersion < 1030002) { + if(oldVersion < 1030005) { db.execSQL("UPDATE FeedItems SET auto_download=0 WHERE " + "(read=1 OR id IN (SELECT feeditem FROM FeedMedia WHERE position>0 OR downloaded=1)) " + "AND id NOT IN (SELECT feeditem FROM Queue)"); -- cgit v1.2.3 From 224832300f4a8d0b42e257a23f0ae69957518a01 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 4 Aug 2015 22:09:53 -0400 Subject: only autodownload new items --- .../antennapod/core/service/download/DownloadService.java | 7 ++++++- .../danoeh/antennapod/core/storage/APDownloadAlgorithm.java | 12 ++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java index 19a710d24..4fdaf6843 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -325,6 +325,11 @@ public class DownloadService extends Service { cancelNotificationUpdater(); unregisterReceiver(cancelDownloadReceiver); + // TODO: I'm not sure this is actually needed. + // We could just invoke the autodownloadUndownloadeditems method + // and it would get everything it's supposed to. By sending it the + // items in newMediaFiles we're overriding the download algorithm, + // which is not something we should probably do. if (!newMediaFiles.isEmpty()) { Log.d(TAG, "newMediaFiles exist, autodownload them"); DBTasks.autodownloadUndownloadedItems(getApplicationContext(), @@ -783,7 +788,7 @@ public class DownloadService extends Service { if(item.getPubDate() == null) { Log.d(TAG, item.toString()); } - if (!item.isPlayed() && item.hasMedia() && !item.getMedia().isDownloaded()) { + if (item.isNew() && item.hasMedia() && !item.getMedia().isDownloaded()) { newMediaFiles.add(item.getMedia().getId()); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java index 0e6b23696..c2e971dce 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java @@ -22,7 +22,7 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm { private final APCleanupAlgorithm cleanupAlgorithm = new APCleanupAlgorithm(); /** - * Looks for undownloaded episodes in the queue or list of unread items and request a download if + * Looks for undownloaded episodes in the queue or list of new items and request a download if * 1. Network is available * 2. The device is charging or the user allows auto download on battery * 3. There is free space in the episode cache @@ -57,12 +57,12 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm { candidates = DBReader.getFeedItems(context, mediaIds); } else { final List queue = DBReader.getQueue(context); - final List unreadItems = DBReader.getUnreadItemsList(context); - candidates = new ArrayList(queue.size() + unreadItems.size()); + final List newItems = DBReader.getNewItemsList(context); + candidates = new ArrayList(queue.size() + newItems.size()); candidates.addAll(queue); - for(FeedItem unreadItem : unreadItems) { - if(candidates.contains(unreadItem) == false) { - candidates.add(unreadItem); + for(FeedItem newItem : newItems) { + if(candidates.contains(newItem) == false) { + candidates.add(newItem); } } } -- cgit v1.2.3 From c019f2cd3bf6791e6c9b1783816e369cb88e4363 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 4 Aug 2015 22:41:03 -0400 Subject: removed extra quote --- core/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index b0ebef3da..00bc077e8 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -271,7 +271,7 @@ Network Update Interval or Time of Day Specify an interval or a specific time of day to refresh the feeds automatically - You can set an interval like \"every 2 hours\", set a specific time of day like \"7:00 AM\" or disable automatic updates altogether.\n\nPlease note: Update times are inexact. You may encounter a short delay." + You can set an interval like \"every 2 hours\", set a specific time of day like \"7:00 AM\" or disable automatic updates altogether.\n\nPlease note: Update times are inexact. You may encounter a short delay. Disable Set Interval Set Time of Day -- cgit v1.2.3 From dbaa5a87e5445ced73fd001400451a21a4ca6c0b Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 8 Aug 2015 08:42:31 -0400 Subject: updated strings from transifex --- core/src/main/res/values-az/strings.xml | 4 +- core/src/main/res/values-ca/strings.xml | 9 +- core/src/main/res/values-cs-rCZ/strings.xml | 88 ++++++++++++- core/src/main/res/values-de/strings.xml | 68 +++++++++- core/src/main/res/values-es/strings.xml | 84 +++++++++++- core/src/main/res/values-fr/strings.xml | 9 +- core/src/main/res/values-it-rIT/strings.xml | 9 +- core/src/main/res/values-ja/strings.xml | 81 +++++++++++- core/src/main/res/values-ko/strings.xml | 9 +- core/src/main/res/values-nl/strings.xml | 4 +- core/src/main/res/values-no/strings.xml | 1 + core/src/main/res/values-pt-rBR/strings.xml | 4 +- core/src/main/res/values-pt/strings.xml | 172 +++++++++++++++++-------- core/src/main/res/values-ro-rRO/strings.xml | 4 +- core/src/main/res/values-ru/strings.xml | 9 +- core/src/main/res/values-sv-rSE/strings.xml | 190 +++++++++++++++++++--------- core/src/main/res/values-uk-rUA/strings.xml | 9 +- 17 files changed, 560 insertions(+), 194 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values-az/strings.xml b/core/src/main/res/values-az/strings.xml index b52ecf4a4..3610f837e 100644 --- a/core/src/main/res/values-az/strings.xml +++ b/core/src/main/res/values-az/strings.xml @@ -46,7 +46,6 @@ Hamısını oxunmuş kimi işarələ Məlumatı göstər Web-səhifəyi paylaş - Kanalı paylaş Bütün kanallar və epizodlar silinəçək. Yüklə @@ -134,8 +133,6 @@ Oynatma başa çatanda növbədə irəlidəki epizodu oynat Oynatma Şəbəkə - Təzələmə intervalı - Kanalın avtomatik təzələməsinin intervalını seç ya da keçir onu Təkçə Wi-Fi vasitəsiilə yüklə Fasiləsiz oynatma Wi-Fi vasitəsiilə yükləmə @@ -210,5 +207,6 @@ Yükləmə... + diff --git a/core/src/main/res/values-ca/strings.xml b/core/src/main/res/values-ca/strings.xml index be7a73e6d..c4887e512 100644 --- a/core/src/main/res/values-ca/strings.xml +++ b/core/src/main/res/values-ca/strings.xml @@ -71,7 +71,6 @@ Mostra informació Esborra podcast Comparteix l\'enllaç de la plana - Comparteix l\'enllaç del canal Confirmeu que, efectivament, voleu suprimir aquest canal i tots els episodis que us n\'heu baixat. S\'està esborrant el canal S\'ha actualitzat el canal @@ -197,8 +196,6 @@ Esborrat automàtic Reproducció Xarxa - Interval d\'actualització - Especifiqueu l\'interval en què els canals s\'actualitzen de forma automàtica, o deshabiliteu la funcionalitat. Només baixa fitxers a través d\'una xarxa sense fils Reproducció continuada Baixa a través de xarxes sense fils @@ -240,8 +237,6 @@ Canvia les dades d\'inici de sessió del vostre compte de gpodder.net Velocitats de reproducció Personalitzeu les velocitats disponibles per a una velocitat de reproducció d\'àudio variable - Salta a l\'instant - Salta aquesta quantitat de segons en rebobinar o en avançar ràpidament Definex nom del servidor Utilitza el servidor per defecte Amplia la notificació @@ -283,9 +278,6 @@ Temporitzador Temps restant:\u0020 L\'entrada no és vàlida, ja que el temps ha de ser un nombre i no ho és - segons - minuts - hores CATEGORIES TOP PODCASTS @@ -354,6 +346,7 @@ Autenticació Canvieu el nom d\'usuari i contrasenya per a aquest podcast i els seus episodis. + S\'estan important les subscripcions des de les apps de propòsit únic... diff --git a/core/src/main/res/values-cs-rCZ/strings.xml b/core/src/main/res/values-cs-rCZ/strings.xml index 90304a404..4a89a7d8c 100644 --- a/core/src/main/res/values-cs-rCZ/strings.xml +++ b/core/src/main/res/values-cs-rCZ/strings.xml @@ -27,6 +27,12 @@ Otevřít menu Zavřít menu Nastavení panelu + Řadit dle počtu + Řadit abecedně + Počet nových a nepřehraných epizod + Počet nových epizod + Počet nepřehraných epizod + Žádné Otevřít v prohlížeči Kopírovat URL @@ -38,6 +44,9 @@ Potvrdit Zrušit + Ano + Ne + Autor Jazyk URL @@ -60,7 +69,13 @@ Zavřít Zkusit znovu Zahrnout do automaticky stahovaných + Použít na předchozí epizody + Nová funkce auto stahování bude automaticky použita na nové epizody.\nChcete ji také použít na předchozí epizody? + Automaticky smazat epizodu\n(přeskočit globální nastavení) \u0020paralelních stahování + Globální + Vždy + Nikdy URL kanálu URL nebo webová stránka kanálu @@ -73,14 +88,20 @@ Všechny epizody označeny jako poslechnuté Prosím potvrďte, že chcete označit všechny vybrané epizody jako poslechnuté. Prosím potvrďte, že chcete označit všechny epizody z tohoto zdroje jako poslechnuté. + Označit vše jako zobrazené Informace o zdroji Odstranit podcast + Sdílet... Sdílet odkaz - Sdílet adresu kanálu + Sdílet odkaz s pozicí + Sdílet URL kanálu + Sdílet URL epizody + Sdílet URL epizody s pozicí Prosím potvrďte, že chcete smazat tento kanál včetně všech stažených epizod. Odstranit kanál Obnovit kompletní kanál Skrýt epizody + Provést akce Neposlechnuté Pozastavené Poslechnuté @@ -99,8 +120,8 @@ Odstranit Odstranit epizodu Označit jako poslechnuté - Označit jako neposlechnuté Označeno jako poslechnuté + Označit jako neposlechnuté Přidat do fronty Přidáno do fronty Odebrat z fronty @@ -229,8 +250,12 @@ Chytré označování jako poslechnuté Přehrávání Síť - Interval aktualizace zdrojů - Udává interval, ve kterém se kanály automaticky aktualizují nebo tuto funkci deaktivuje + Aktualizovat interval nebo čas v průběhu dne + Udat interval nebo přesný čas v průběhu dne pro automatickou aktualizaci kanálů + Můžete nastavit interval jako třeba \"každé 2 hodiny\", nastavit specifický čas v průběhu dne jako \"7:00\" nebo úplně vypnout automatické aktualizace.\n\nMějte na paměti: Časy aktualizací nejsou přesné. Možná zaznamenáte krátká zpoždění. + Vypnout + Nastavit interval + Nastavit čas v průběhu dne Stahovat soubory pouze pomocí WiFi Kontinuální přehrávání WiFi stahování @@ -250,8 +275,14 @@ Nastavit automatické flattrování Uživatelské rozhraní Vybrat motiv + Upravit navigační panel + Upravit vzhled navigačního panelu. Změnit navigační panel Upravit zobrazení položek v navigačním panelu. + Nastavit pořadí sbírek + Upravit pořadí vašich sbírek + Nastavit počítadlo sbírek + Upravit informaci zobrazovanou počítadlem sbírek Změnit vzhled AntennaPod. Automatické stahování Nastavení automatického stahování epizod. @@ -283,10 +314,14 @@ Vždy zobrazovat tlačítka pro přehrávání v upozornění. Pevné ovládání přehrávání Zachovat upozornění a ovládání na obrazovce uzamčení i při pozastaveném přehrávání. + Zobrazit report stahování + Pokud selže stahování, vygenerovat report zobrazující detaily o chybě. Verze Androidu nižší než 4.1 nepodporují rozšířená upozornění. Přidávat nové epizody na začátek fronty. Přidat na začátek. Vypnuto + Velikost odkládací paměti obrázků + Velikost diskové paměti pro obrázky. Povolit automatické flattrování Flattrovat díl jakmile bude odehráno %d procent @@ -312,6 +347,7 @@ Adresář importu je prázdný. Označit vše Zrušit výběr + Vybrat ... Z místního souborového systému Použít externí aplikaci OPML export @@ -326,9 +362,24 @@ Časovač vypnutí Zbývající čas:\u0020 Neplatný vstup, musí být zadáno celé číslo - sekund - minut - hodin + sekund + minut + hodin + + 1 sekunda + %d sekundy + %d sekund + + + 1 minuta + %d minuty + %d minut + + + 1 hodina + %d hodiny + %d hodin + KATEGORIE TOP PODCASTY @@ -373,6 +424,7 @@ Automatické pozastavení přehrávání Pokračovat v přehrávání po ukončení telefonního hovoru Pokračovat po telefonátu + Pro aktivování změn nastavení bylo třeba restartovat aplikaci AntennaPod. Odebírat Odebíráno @@ -399,7 +451,29 @@ Ověření Změnit uživatelské jméno a heslo pro tento podcast a jeho epizody. + + Probíhá aktualizace databáze Importuji odběry z jednoúčelových aplikací... Prohledat iTunes + Vybrat ... + Vše + Vybrány všechny epizody + Žádné + Odebrány všechny epizody + Přehrány + Vybrány přehrané epizody + Nepřehrány + Odebrány nepřehrané epizody + Stažené + Vybrány stažené epizody + Nestažené + Vybrány nestažené epizody + Řadit podle ... + Názvu (A \u2192 Z) + Názvu (Z \u2192 A) + Data (Nové \u2192 Staré) + Data (Staré \u2192 Nové) + Délka (Krátké \u2192 Dlouhé) + Délka (Dlouhé \u2192 Krátké) diff --git a/core/src/main/res/values-de/strings.xml b/core/src/main/res/values-de/strings.xml index 93e52acb6..c6e7acbcc 100644 --- a/core/src/main/res/values-de/strings.xml +++ b/core/src/main/res/values-de/strings.xml @@ -27,6 +27,12 @@ Menü öffnen Menü schließen Seitenleisten-Einstellungen + Sortieren nach Zähler + Alphabetisch sortieren + Anzahl neuer und ungespielter Episoden + Anzahl neuer Episoden + Anzahl ungespielter Episoden + Keine Im Browser öffnen URL kopieren @@ -38,6 +44,8 @@ Bestätigen Abbrechen + Ja + Nein Autor Sprache URL @@ -60,7 +68,13 @@ Schließen Erneut versuchen Automatisch herunterladen + Auf bisherige Episoden anwenden + Die neue Einstellung zum Automatischen Download wird automatisch auf neue Episoden angewandt.\nMöchtest du sie auch auf die bisherige Episoden anwenden? + Episoden automatisch löschen\n(überschreibt globale Vorgabe) \u0020gleichzeitige Downloads + Global + Immer + Nie Feed URL URL des Feeds oder der Webseite @@ -73,14 +87,20 @@ Alle Episoden als gespielt markieren Bitte bestätige, dass alle Episoden als gespielt markiert werden sollen. Bitte bestätige, dass alle Episoden in diesem Feed als gespielt markiert werden sollen. + Alle als gesehen markieren Informationen anzeigen Podcast entfernen + Teile... Webseiten-Link teilen - Feed-Link teilen + Teile Link mit Zeitmarke + Teile URL des Podcasts + Teile URL der Episode + Teile URL der Episode mit Zeitmarke Bitte bestätige, dass du diesen Feed und ALLE heruntergeladenen Episoden dieses Feeds entfernen möchtest. Entferne Feed Kompletten Feed aktualisieren Episoden verbergen + Aktionen anwenden Ungespielt Pausiert Gespielt @@ -99,8 +119,8 @@ Entfernen Episode entfernen Als gespielt markieren - Als ungespielt markieren Als gespielt markiert + Als ungespielt markieren Zur Abspielliste hinzufügen Zur Abspielliste hinzugefügt Aus der Abspielliste entfernen @@ -229,8 +249,11 @@ Schlaues als gespielt markieren Wiedergabe Netzwerk - Aktualisierungsintervall - Lege ein Intervall fest, in dem Feeds automatisch aktualisiert werden oder deaktiviere es + Aktualisierungsintervall oder -tageszeit + Lege ein Intervall oder eine Tageszeit zur automatischen Aktualisierung der Podcasts fest + Deaktivieren + Intervall einstellen + Tageszeit festlegen Lade Mediendateien nur über WiFi Durchgehendes Abspielen WiFi Medien-Download @@ -250,8 +273,14 @@ Automatisches Flattrn konfigurieren Benutzeroberfläche Theme auswählen + Seitenleiste anpassen + Passe das Aussehen der Seitenleiste an. Seitenleiste ändern Ändere, welche Listen in der Seitenleiste erscheinen + Reihenfolge der Abonnements einstellen + Ändere die Reihenfolge deiner Abonnements + Abonnement-Zähler einstellen + Ändere, welche Information der Abonnement-Zähler anzeigt Ändere das Aussehen von AntennaPod. Automatisches Herunterladen Konfiguriere das automatische Herunterladen von Episoden. @@ -283,10 +312,14 @@ Erweiterte Wiedergabebenachrichtigung mit Abspiel-, Pause- und Stop-Knöpfen anzeigen. Persistente Wiedergabesteurung Zeige Wiedergabebedienelemente in der Benachrichtigung und im Lockscreen an, während die Wiedergabe pausiert ist. + Zeige Download-Bericht + Wenn Downloads fehlschlagen, erstelle einen Bericht, der die Details des Fehlschlages beschreibt. Android-Versionen vor 4.1 unterstützen keine erweiterten Benachrichtigungen. Fügen Sie neue Folgen auf den Anfang der Warteschlange. Vorne in Abspielliste einreihen Deaktiviert + Größe des Bilder-Zwischenspeichers + Größe des Zwischenspeichers für Bilder Automatisches Flattrn aktivieren Flattr eine Episode, sobald %d Prozent gespielt worden sind @@ -312,6 +345,7 @@ Der Import-Ordner ist leer. Alle auswählen Auswahl zurücksetzen + Wähle aus ... Vom lokalen Dateisystem Verwende externe Anwendung OPML Export @@ -326,9 +360,6 @@ Schlummerfunktion Zeit übrig:\u0020 Ungültige Eingabe, Zeit muss eine Ganzzahl sein - Sekunden - Minuten - Stunden KATEGORIEN BESTE PODCASTS @@ -373,6 +404,7 @@ Bei Unterbrechungen pausieren Wiedergabe fortsetzen, wenn Anruf beendet ist Nach Anruf fortsetzen + AntennaPod muss neu gestartet werden, damit die Änderungen wirksam werden. Abonnieren Abonniert @@ -399,7 +431,29 @@ Authentifizierung Ändere den Benutzernamen und das Passwort für diesen Podcast und dessen Episoden. + + Datenbank wird aktualisiert Importiere Abonnements aus Single-Purpose Apps iTunes durchsuchen + Wähle aus ... + Alle + Alle Episoden ausgewählt + Keine + Alle Episoden abgewählt + Gespielt + Gespielte Episoden ausgewählt + Ungespielt + Ungespielte Episoden ausgewählt + Heruntergeladen + Heruntergeladene Episoden ausgewählt + Nicht heruntergeladen + Nicht heruntergeladene Episoden ausgewählt + Sortieren nach ... + Titel (A \u2192 Z) + Titel (Z \u2192 A) + Datum (neu \u2192 alt) + Datum (alt \u2192 neu) + Dauer (kurz \u2192 lang) + Dauer (lang \u2192 kurz) diff --git a/core/src/main/res/values-es/strings.xml b/core/src/main/res/values-es/strings.xml index d5255a589..6670836db 100644 --- a/core/src/main/res/values-es/strings.xml +++ b/core/src/main/res/values-es/strings.xml @@ -27,6 +27,12 @@ Abrir menú Cerrar menú Preferencias del cajón + Ordenar por cuenta + Ordenar alfabéticamente + Cantidad de episodios nuevos y no escuchados + Cantidad de episodios nuevos + Cantidad de episodios no escuchados + Ninguno Abrir en el navegador Copiar URL @@ -38,6 +44,8 @@ Confirmar Cancelar + + No Autor Idioma URL @@ -60,7 +68,13 @@ Cerrar Reintentar Incluir en descargas automáticas + Aplicar a episodios anteriores + La nueva opción Auto Descarga se aplicará automáticamente a episodios nuevos.\n¿También desea aplicarlo a episodios anteriores? + Auto borrar episodio\n(Ignorando los ajustes globales) \u0020descargas paralelas + Global + Siempre + Nunca URL del canal URL del canal o del sitio web @@ -73,14 +87,20 @@ Se marcaron todos los episodios como escuchados Por favor, confirme que desea marcar todos los episodios como escuchados. Por favor, confirme que desea marcar todos los episodios de este feed como escuchados. + Marcar todos como vistos Información del programa Eliminar podcast + Compartir... Compartir el enlace de la web - Compartir el enlace del canal + Compartir enlace con posición + Compartir URL del canal + Compartir URL del episodio + Compartir URL del episodio con posición Confirme que quiere eliminar este canal y TODOS los episodios descargados del mismo. Quitando el canal Actualizar el canal completo Ocultar episodios + Aplicar acciones No escuchados Pausados Escuchados @@ -99,8 +119,8 @@ Quitar Quitar episodio Marcar como escuchado - Marcar como no escuchado Marcado como escuchado + Marcar como no escuchado Añadir a la cola Añadido a la cola Quitar de la cola @@ -229,8 +249,12 @@ Marcar como escuchado inteligente Reproducción Red - Intervalo de actualización - Especificar el intervalo en que se actualizarán automáticamente los canales, o desactivarlo + Intervalo de actualización u hora del día + Especificar el intervalo o la hora del día en que se actualizarán automáticamente los canales + Se puede ajustar un intervalo como \"cada 2 horas\", especificar una hora del día como \"7:00 AM\" o deshabilitar las actualizaciones automáticas.\n\nNota: Las horas de actualización no son exactas. Puede haber un ligero retraso. + Deshabilitar + Ajustar intervalo + Ajustar hora del día Solo descargar los contenidos por WiFi Reproducción continua Descarga de contenidos por WiFi @@ -250,8 +274,14 @@ Configurar flattr automático Interfaz de usuario Elegir un tema + Personalizar el cajón de navegación + Personalizar la apariencia del cajón de navegación Cambiar el cajón de navegación Cambiar los ítems que aparecen en el cajón de navegación + Ajustar orden de suscripción + Cambiar el orden de las suscripciones + Ajustar contador de suscripción + Cambiar la información mostrada en el contador de suscripción Cambiar la apariencia de AntennaPod. Descarga automática Configurar la descarga automática de episodios. @@ -283,10 +313,14 @@ Expandir siempre la notificación para mostrar los botones de reproducción Controles de reproducción persistentes Mantener la notificación y controles en pantalla de bloqueo cuando se pausa. + Mostrar informe de descarga + Si la descarga falla, generar un informe con los detalles del fallo Las versiones de Android anteriores a la 4.1 no soportan notificaciones expandidas Agregar nuevos episodios al principio de la cola. Poner al principio de la cola. Deshabilitado + Tamaño de la caché de imágenes + Tamaño de la caché en disco para imágenes. Habilitar Flattr automático Hacer Flattr del episodio en cuanto se haya reproducido el %d por ciento @@ -312,6 +346,7 @@ El directorio de importación está vacío. Seleccionar todo Deseleccionar todo + Seleccionar... Desde el sistema de ficheros local Usar aplicación externa Exportar a OPML @@ -326,9 +361,21 @@ Temporizador Tiempo restante:\u0020 Entrada no válida, el tiempo debe ser un entero - segundos - minutos - horas + segundos + minutos + horas + + 1 segundo + %d segundos + + + 1 minuto + %d minutos + + + 1 hora + %d horas + CATEGORÍAS MEJORES PODCASTS @@ -373,6 +420,7 @@ Pausar durante las interrupciones Reanudar reproducción tras una llamada Reanudar tras una llamada + Es necesario reiniciar AntennaPod para aplicar los cambios. Suscribirse Suscrito @@ -399,7 +447,29 @@ Autenticación Cambiar nombre y contraseña de este podcast y sus episodios + + Actualizando la base de datos Importando subscripciones de aplicaciones de uso específico... Buscar en iTunes + Seleccionar... + Todo + Seleccionados todos los episodios + Ninguno + Deseleccionados todos los episodios + Reproducido + Seleccionados episodios reproducidos + No reproducidos + Seleccionados episodios no reproducidos + Descargado + Seleccionados episodios descargados + No descargado + Seleccionados episodios no descargados + Ordenar por... + Título (A \u2192 Z) + Título (Z \u2192 A) + Fecha (Nuevo \u2192 Antiguo) + Fecha (Antiguo \u2192 Nuevo) + Duración (Corto \u2192 Largo) + Duración (Largo \u2192 Corto) diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml index 2f59e139d..3b952e56b 100644 --- a/core/src/main/res/values-fr/strings.xml +++ b/core/src/main/res/values-fr/strings.xml @@ -74,7 +74,6 @@ Voir les détails Supprimer le podcast Partager un lien vers le site - Partager le flux Veuillez confirmer que vous voulez bien supprimer ce flux et TOUS ses épisodes que vous avez téléchargés. Flux en cours de suppression Mettre à jour tout le flux @@ -87,8 +86,8 @@ Supprimer Supprimer cet épisode Marquer comme lu - Marquer comme non lu Les épisodes ont été marqués comme lus + Marquer comme non lu Ajouter à la liste Supprimer de la liste Visiter le site @@ -202,8 +201,6 @@ Supression automatique Lecture Réseau - Intervalle de mise à jour - Indiquer un intervalle de mise à jour automatique des flux, ou le désactiver Ne télécharger les épisodes que par Wi-Fi Lecture continue Téléchargement en Wi-Fi @@ -294,9 +291,6 @@ Arrêt automatique Durée restante :\u0020 Entrée invalide, la durée doit être un nombre entier - secondes - minutes - heures CATEGORIES PODCASTS POPULAIRES @@ -365,6 +359,7 @@ Authentification Modifier votre identifiant et mot de passe pour ce podcast et tous ses épisodes + Importation des abonnements à partir d\'applications à usage unique... Chercher sur iTunes diff --git a/core/src/main/res/values-it-rIT/strings.xml b/core/src/main/res/values-it-rIT/strings.xml index 82c7395ff..c12fedbaa 100644 --- a/core/src/main/res/values-it-rIT/strings.xml +++ b/core/src/main/res/values-it-rIT/strings.xml @@ -73,7 +73,6 @@ Informazioni Rimuovi un podcast Condividi il link al sito - Condividi il link al feed Per favore conferma la cancellazione di questo feed e di TUTTI gli episodi collegati che sono stati precedentemente scaricati. Rimozione feed Ricarica il feed completo @@ -96,8 +95,8 @@ Rimuovi Rimuovi l\'episodio Segna come riprodotto - Segna come non riprodotto Segnato come riprodotto + Segna come non riprodotto Aggiungi alla coda Aggiunto alla coda Rimuovi dalla coda @@ -220,8 +219,6 @@ Elimina automaticamente Riproduzione Rete - Intervallo di update - Specifica un intervallo per l\'aggiornamento automatico dei feed o disabilitalo Abilita il download dei media solo tramite WiFi Playback continuo Download dei media su WiFi @@ -308,9 +305,6 @@ Timer di spegnimento Tempo residuo:\u0020 Input non valido, il campo deve essere un numero intero. - secondi - minuti - ore CATEGORIE TOP PODCAST @@ -380,6 +374,7 @@ Autenticazione Cambia il tuo nome utente e la tua password per questo podcast e i suoi episodi. + Importazione di sottoscrizioni da applicazioni monouso in corso... Cerca su iTunes diff --git a/core/src/main/res/values-ja/strings.xml b/core/src/main/res/values-ja/strings.xml index 79411ffc1..3a9e58d9a 100644 --- a/core/src/main/res/values-ja/strings.xml +++ b/core/src/main/res/values-ja/strings.xml @@ -27,6 +27,12 @@ メニューを開く メニューを閉じる ドロワー設定 + カウンターで並び替え + アルファベット順に並び替え + 新しい未再生のエピソードの数 + 新しいエピソードの数 + 未再生のエピソードの数 + なし ブラウザーで開く URLをコピー @@ -38,6 +44,8 @@ 確認 キャンセル + はい + いいえ 作者 言語 URL @@ -60,7 +68,13 @@ 閉じる 再試行 自動ダウンロードに含む + 前のエピソードに適用 + 新しい 自動ダウンロード の設定は、新しいエピソードに自動的に適用されます。\n前のエピソードにも適用しますか? + エピソードの自動削除\n(全般のデフォルトを上書きします) \u0020パラレル ダウンロード + 全般 + 常に + しない フィードURL フィードまたはWebサイトのURL @@ -73,14 +87,20 @@ すべてのエピソードを再生済にしました 再生済としてマークするすべてのエピソードを確認してください。 再生済としてマークするこのフィードのすべてのエピソードを確認してください。 + 参照済としてマーク 情報を表示 ポッドキャストを削除 + 共有... Webサイトのリンクを共有 - フィードのリンクを共有 + 場所とリンクを共有 + フィード URLを共有 + エピソード URLを共有 + 場所とエピソード URL を共有 このフィードと、このフィードのダウンロードしたすべてのエピソードを削除することを確認してください。 フィードの削除中 フィードをすべて更新 エピソードを非表示にする + 操作を適用 未再生 一時停止しました 再生しました @@ -99,8 +119,8 @@ 削除 エピソードを削除 再生済としてマーク - 未再生としてマーク 再生済としてマークしました + 未再生としてマーク キューに追加 キューに追加しました キューから削除 @@ -229,8 +249,12 @@ 再生済としてスマートマーク 再生 ネットワーク - 更新間隔 - フィードが自動的に更新される間隔を指定するか、または無効にしてください + 間隔または時間を更新 + 自動的にフィードを更新する間隔または時間を指定してください + \"2 時間ごと\" のような 間隔 、\"7:00 AM\" のような特定の 時間 、または自動更新を完全に 無効 にセットすることができます。\n\nご注意ください: 更新時間は正確ではありません。少し遅延が発生する可能性があります。 + 無効 + 間隔をセット + 時間をセット WiFi接続時のみメディアファイルをダウンロードします 連続再生 WiFiメディアダウンロード @@ -250,8 +274,14 @@ 自動Flattrを構成 インターフェース テーマを選択 + ナビゲーションドロワーをカスタマイズ + ナビゲーションドロワーの外観をカスタマイズします。 ナビゲーションドロワーを変更 ナビゲーションドロワーに表示するアイテムを変更します。 + 購読注文をセット + 購読の注文を変更します + 購読カウンターをセット + 購読カウンターで表示される情報を変更します AntennaPodの外観を変更します。 自動ダウンロード エピソードの自動ダウンロードを構成します。 @@ -283,10 +313,14 @@ 常に再生ボタンを表示するように通知を展開します。 永続再生コントロール 再生が一時停止された時に、通知およびロック画面のコントロールを保持します。 + ダウンロード レポートを表示 + ダウンロードが失敗した場合、失敗の詳細を表示するレポートを生成します。 Androidバージョン4.1以前では、拡張通知をサポートしていません。 新しいエピソードをキューの先頭に追加します。 キューの先頭に入れる 無効 + 画像キャッシュサイズ + 画像のディスクキャッシュのサイズ。 自動Flattrを有効にする %d %再生したらエピソードをFlattr @@ -312,6 +346,7 @@ インポートディレクトリが空です。 すべてを選択 選択解除 + 選択 ... ローカル ファイルシステムから 外部アプリケーションを使用する OPMLエクスポート @@ -326,9 +361,18 @@ スリープタイマー 残り時間:\u0020 入力が正しくありません、時間は数字で入力してください - - - + + + 時間 + + %d 秒 + + + %d 分 + + + %d 時間 + カテゴリー トップ ボッドキャスト @@ -373,6 +417,7 @@ 割り込み時に一時停止 着信が完了した後に再生を再開します 着信後に再開 + この変更を有効にするには AntennaPod を再起動する必要があります。 購読 購読しました @@ -399,7 +444,29 @@ 認証 このポッドキャストとそのエピソード用のあなたのユーザー名とパスワードを変更します。 + + データベースをアップグレードしています 単一目的のアプリから購読をインポート中… iTunes を検索 + 選択 ... + すべて + すべてのエピソードを選択しました + なし + すべてのエピソードの選択を解除しました + 再生しました + 再生済のエピソードを選択しました + 未再生 + 未再生のエピソードを選択しました + ダウンロードしました + ダウンロード済のエピソードを選択しました + ダウンロードしていません + ダウンロードしていないエピソードを選択しました + 並び替え順 ... + タイトル (A \u2192 Z) + タイトル (Z \u2192 A) + 日付 (新 \u2192 旧) + 日付 (旧 \u2192 新) + 期間 (短 \u2192 長) + 期間 (長 \u2192 短) diff --git a/core/src/main/res/values-ko/strings.xml b/core/src/main/res/values-ko/strings.xml index 148010050..fcfa89e88 100644 --- a/core/src/main/res/values-ko/strings.xml +++ b/core/src/main/res/values-ko/strings.xml @@ -76,7 +76,6 @@ 정보 표시 팟캐스트 제거 홈페이지 링크 공유 - 피드 링크 공유 이 피드와 이 피드에서 다운로드한 모든 에피소드를 삭제하시려면 확인을 누르십시오. 피드 삭제하는 중 전체 피드 새로고침 @@ -99,8 +98,8 @@ 제거 에피소드 제거 재생했다고 표시 - 재생하지 않음으로 표시 재생했다고 표시함 + 재생하지 않음으로 표시 대기열에 추가 대기열에 추가함 대기열에서 제거 @@ -229,8 +228,6 @@ 똑똑하게 재생한 것으로 표시 재생 네트워크 - 업데이트 주기 - 피드를 새로 고칠 주기를 지정하거나 새로 고침을 하지 않음 Wi-Fi를 통해서만 미디어 파일 다운로드 연속 재생 Wi-Fi 미디어 다운로드 @@ -326,9 +323,6 @@ 취침 타이머 남은 시간:\u0020 입력이 잘못되었습니다. 시간으로 숫자를 입력해야 합니다. - - - 시간 분류 상위 팟캐스트 @@ -399,6 +393,7 @@ 인증 이 팟캐스트와 에피소드에 대한 사용자 이름과 비밀번호를 바꿉니다. + 단일 용도 앱에서 구독 정보를 가져옵니다... iTunes 검색 diff --git a/core/src/main/res/values-nl/strings.xml b/core/src/main/res/values-nl/strings.xml index 0f447d54a..4ef43ecaf 100644 --- a/core/src/main/res/values-nl/strings.xml +++ b/core/src/main/res/values-nl/strings.xml @@ -54,7 +54,6 @@ Alles als gelezen markeren Toon informatie Website link delen - Feed link delen Bevestig dat u deze feed en ALLE afleveringen van deze feed die u hebt gedownload wilt verwijderen. Feed verwijderen @@ -162,8 +161,6 @@ Volgende wachtrij item afspelen als de episode voltooid is Afspelen Netwerk - Update interval - Voer een tijdsinterval in waarin de feeds automatisch worden vernieuwd, of schakel het uit Download mediabestanden alleen via WiFi Continu afspelen WiFi download van media @@ -295,6 +292,7 @@ Aantal nieuwe afleveringen Aantal afleveringen dat begonnen te luisteren zijn + Abonnementen aan het importeren vanuit single-purpose apps... diff --git a/core/src/main/res/values-no/strings.xml b/core/src/main/res/values-no/strings.xml index 16639048b..645d576a4 100644 --- a/core/src/main/res/values-no/strings.xml +++ b/core/src/main/res/values-no/strings.xml @@ -26,5 +26,6 @@ + diff --git a/core/src/main/res/values-pt-rBR/strings.xml b/core/src/main/res/values-pt-rBR/strings.xml index c3523acfb..3d421fdb2 100644 --- a/core/src/main/res/values-pt-rBR/strings.xml +++ b/core/src/main/res/values-pt-rBR/strings.xml @@ -54,7 +54,6 @@ Marcar todos como lido Mostrar informação Compartilhar link do site - Compartilhar link do feed Por favor confirme que você deseja apagar este feed e TODOS os episódios que você fez download deste feed. Removendo feed @@ -148,8 +147,6 @@ Pular para próximo item da fila quando a reprodução terminar Reprodução Rede - Intervalo de atualização - Especifica o intervalo com que os feeds serão atualizados automaticamente ou desabilita esta funcionalidade Fazer download dos arquivos apenas via rede WiFi Reprodução contínua Download de mídia via WiFi @@ -271,5 +268,6 @@ Episódio está na fila Numero de novos episódios + diff --git a/core/src/main/res/values-pt/strings.xml b/core/src/main/res/values-pt/strings.xml index abbf97de6..902fe5575 100644 --- a/core/src/main/res/values-pt/strings.xml +++ b/core/src/main/res/values-pt/strings.xml @@ -12,11 +12,11 @@ Lista de espera Definições Adicionar podcast - Transferências + Descargas Em curso Terminadas Registo - Cancelar transferência + Cancelar\ndescarga Histórico de reprodução gpodder.net Dados gpodder.net @@ -27,6 +27,12 @@ Abrir menu Fechar menu Preferências do menu + Ordenar por contador + Ordenar alfabeticamente + Número de episódios novos ou por reproduzir + Número de novos episódios + Número de episódios por reproduzir + Nenhum Abrir no navegador Copiar URL @@ -38,6 +44,8 @@ Confirmar Cancelar + Sim + Não Autor Idioma URL @@ -59,8 +67,14 @@ Guardar utilizador e palavra-passe Fechar Tentar novamente - Incluir nas transferências automáticas - \u0020transferências simultâneas + Incluir nas descargas automáticas + Aplicar aos episódios anteriores + A definição Descarga automática será aplicada a todos os novos episódios.\nGostaria de também a aplicar aos episódios anteriores? + Apagar episódio automáticamente\n(altera a definição global) + \u0020descargas simultâneas + Global + Sempre + Nunca URL da fonte URL da fonte ou sítio web @@ -73,25 +87,31 @@ Marcar todos os episódios como reproduzidos Por favor confirme que deseja marcar todos os episódios como reproduzidos Por favor confirme que deseja marcar todos os episódios desta fonte como reproduzidos + Marcar tudo como visto Mostrar informações Remover podcast - Partilhar ligação do sítio web - Partilhar ligação da fonte - Confirme a eliminação desta fonte e de todos os episódios a ela pertencentes + Partilhar... + Partilhar ligação + Partilhar ligação com posição + Partilhar URL da fonte + Partilhar URL do episódio + Partilhar URL do episódio com posição + Por favor confirme que deseja apagar esta fonte e todos os episódios descarregados Remover fonte Atualizar todas as páginas da fonte Ocultar episódios + Aplicar ações Não reproduzidos Em pausa Reproduzidos Na fila Não na fila - Transferidos - Não transferidos + Descarregados + Não descarregados Filtrados {fa-exclamation-circle} Última atualização falhada - Transferir + Descarregar Reproduzir Pausa Parar @@ -99,24 +119,24 @@ Remover Remover episódio Marcar como reproduzido - Marcar como não reproduzido Marcado como reproduzido + Marcar como não reproduzido Adicionar à fila Adicionado à fila Remover da fila Aceder ao sítio web Flattr Colocar tudo na fila - Transferir tudo + Descarregar tudo Ignorar episódio - Ativar transferência automática - Desativar transferência automática + Ativar descarga automática + Desativar descarga automática Repor posição de reprodução sucesso falha - Transferência pendente - Transferência atual + Descarga pendente + Descarga atual Cartão SD não encontrado Espaço insuficiente Erro no ficheiro @@ -127,29 +147,29 @@ Erro de ligação Servidor desconhecido Erro de autenticação - Cancelar transferências - Transferência cancelada - Transferência cancelada\nTransferência automática desativada para este item - Transferências terminadas com erros - Relatório de transferências + Cancelar descargas + Descarga cancelada + Descarga cancelada\nDescarga automática desativada para este item + Descargas terminadas com erros + Relatório de descargas URL inválido Erro I/O Erro de pedido Erro de acesso à base de dados - \u0020Transferências em falta - Processamento de transferências - A transferir dados... - %1$d transferências efetuadas, %2$d falhadas + \u0020Descargas em falta + Processamento de descargas + A descarregar dados do podcast + %1$d descargas efetuadas, %2$d falhadas Título desconhecido Fonte Ficheiro multimédia Imagem - Ocorreu um erro ao transferir o ficheiro:\u0020 + Ocorreu um erro ao descarregar o ficheiro:\u0020 Requer autenticação O recurso solicitado requer um utilizador e uma palavra-passe - Confirmação de transferência - A transferência através de dados móveis está desativada nas definições.\n\nAtivar temporariamente ou apenas adicionar à fila?\n\nA sua decisão será memorizada durante 10 minutos. - A transferência através de dados móveis está desativada nas definições.\n\nAtivar temporariamente?\n\nA sua decisão será memorizada durante 10 minutos. + Confirmação de descarga + A descarga através de dados móveis está desativada nas definições.\n\nAtivar temporariamente ou apenas adicionar à fila?\n\nA sua decisão será memorizada durante 10 minutos. + A descarga através de dados móveis está desativada nas definições.\n\nAtivar temporariamente?\n\nA sua decisão será memorizada durante 10 minutos. Apenas adicionados à fila Ativar temporariamente @@ -207,9 +227,9 @@ O AntennaPod não fez o flattr A obter itens com flattr - Transferir extra + Descarregar extra Extra não instalado - Para que a velocidade de reprodução variável funcione, tem que instalar um biblioteca de terceiros.\n\nClique em Transferir extra para a transferir no Google Play.\n\nQuaisquer problemas que ocorram na utilização do extra devem ser reportados diretamente ao seu programador. + Para que a velocidade variável de reprodução funcione, tem que instalar um biblioteca de terceiros.\n\nClique em Descarregar extra para a transferir no Google Play.\n\nQuaisquer erros que ocorram na utilização do extra devem ser reportados diretamente ao seu programador. Velocidades de reprodução Não existem itens nesta lista @@ -223,19 +243,23 @@ Pausa na reprodução ao remover os auscultadores Continuar reprodução ao ligar os auscultadores Ir para a faixa seguinte ao terminar a reprodução - Eliminar episódio ao terminar a reprodução + Apagar episódio ao terminar a reprodução Eliminação automática Marcar episódios como reproduzidos mesmo que restem alguns segundos de reprodução Marcar como reproduzido (inteligente) Reprodução Rede - Intervalo entre atualizações - Indique o intervalo de tempo entre as atualizações de fontes ou desative a opção - Apenas transferir pelas redes sem fios + Intervalo de atualização ou hora do dia + Define um intervalo de atualização ou hora para atualizar automaticamente a fonte + Pode definir um intervalo, ex.: \"a cada 2 horas\", definir uma hora do dia, ex.: \"7:00 AM\" ou desativar as atualizações automáticas.\n\nTenha em conta que a hora de atualização não é precisa. Pode existir um pouco de atraso. + Desativar + Definir intervalo + Definir hora do dia + Apenas descarregar através de redes sem fios Reprodução contínua - Transferência Wi-Fi + Descarga por Wi-Fi Auscultadores removidos - Auscultadores ligados + Auscultadores inseridos Atualizações móveis Permitir atualizações através da rede de dados móveis A atualizar @@ -250,16 +274,22 @@ Configurar flattr automático Interface Tema - Alterar itens do menu + Personalizar menu de navegação + Personaliza a aparência do menu de navegação + Alterar elementos do menu Alterar os itens que aparecem no menu de navegação + Definir ordem de subscrição + Alterar a ordem das suas subscrições + Definir contador de subsrições + Mudar informação mostrada no contador de subscrições Mudar o aspeto do AntennaPod - Transferência automática - Configure a transferência automática dos episódios + Descarga automática + Configure a descarga automática dos episódios Ativar filtro Wi-Fi - Apenas permitir transferências automáticas através de redes sem fios - Transferência se não estiver a carregar - Permitir transferência automática se a bateria não estiver a ser carregada - Transferências simultâneas + Apenas permitir descargas automáticas através de redes sem fios + Descarregar se não estiver a carregar + Permitir descarga automática se a bateria não estiver a ser carregada + Descargas simultâneas Cache de episódios Claro Escuro @@ -283,10 +313,14 @@ Expandir sempre a notificação para mostrar os botões de reprodução Controlos de reprodução persistentes Manter controlos de notificação e ecrã de bloqueio ao colocar a reprodução em pausa + Mostrar relatório de erros + Se a descarga falhar, gera um relatório que mostra os detalhes do erro As versões Android anteriores à 4.1 não possuem suporte à expansão de notificações Colocar novos episódios no inicio da fila Novos episódios no inicio Desativada + Cache de imagens + O tamanho da cache de imagens Ativar flattr automático Flattr de episódios ao atingir %d porcento de reprodução @@ -312,6 +346,7 @@ O diretório de importação está vazio Marcar tudo Desmarcar tudo + Selecionar... Do sistema local de ficheiros Utilizar aplicação externa Exportação OPML @@ -326,9 +361,21 @@ Temporizador Tempo restante:\u0020 Tem que introduzir um número inteiro - segundos - minutos - horas + segundos + minutos + horas + + 1 segundo + %d segundos + + + 1 minuto + %d minutos + + + 1 hora + %d horas + Categorias Melhores @@ -367,16 +414,17 @@ A pasta já existe Não é possível criar a pasta A pasta não está vazia - A pasta escolhida não está vazia. As transferências multimédia e os ficheiros serão colocados nesta pasta. Continuar? + A pasta escolhida não está vazia. As descargas multimédia e os ficheiros serão colocados nesta pasta. Continuar? Escolha a pasta pré-definida Pausa na reprodução em vez de baixar o volume se outra aplicação quiser reproduzir sons Pausa nas interrupções Continuar reprodução ao terminar a chamada Continuar após a chamada + Tem que reiniciar o AntennaPod para aplicar as alterações Subscrever Subscrito - A transferir... + A descarregar... Mostrar capítulos Mostrar notas @@ -388,8 +436,8 @@ Navegar para cima Mais ações Episódio em reprodução - Episódio a ser transferido - Episódio transferido + Episódio a ser descarregado + Episódio descarregado Novo item Episódio está na fila Número de novos episódios @@ -399,7 +447,29 @@ Autenticação Altere o seu nome de utilizador e senha para este podcast e seus episódios + + Atualizando base de dados Importar subscrições de aplicações single-purpose... Procurar no iTunes + Selecionar... + Todos + Marcar todos os episódios + Nenhum + Desmarcar todos os episódios + Reproduzidos + Selecionar episódios reproduzidos + Não reproduzidos + Selecionar episódios não reproduzidos + Descarregados + Selecionar episódios descarregados + Não descarregados + Selecionar episódios não descarregados + Ordenar por... + Título (A \u2192 Z) + Título (Z \u2192 A) + Data (Recente \u2192 Antiga) + Data (Antiga \u2192 Recente) + Duração (Curta \u2192 Longa) + Duração (Longa \u2192 Curta) diff --git a/core/src/main/res/values-ro-rRO/strings.xml b/core/src/main/res/values-ro-rRO/strings.xml index 390f50767..ce82dec1e 100644 --- a/core/src/main/res/values-ro-rRO/strings.xml +++ b/core/src/main/res/values-ro-rRO/strings.xml @@ -50,7 +50,6 @@ Marchează toate ca citite Arată informații Împarte adresă website - Împarte adresă feed Confirmați ștergerea feedului și a TUTUROR episoadelor pe care le-ați descărcat. Descarcă @@ -140,8 +139,6 @@ Sari la următorul element din coadă cand se termină ascultarea Ascultare Rețea - Interval actualizare - Specifică un interval în care feedurile sunt actualizate automat sau oprește funcția Descarcă fișiere media doar pe WiFi Ascultare continuă Descărcare media pe WiFi @@ -237,5 +234,6 @@ Se descarcă... + diff --git a/core/src/main/res/values-ru/strings.xml b/core/src/main/res/values-ru/strings.xml index ae10b314f..b8206d906 100644 --- a/core/src/main/res/values-ru/strings.xml +++ b/core/src/main/res/values-ru/strings.xml @@ -74,7 +74,6 @@ Показать информацию Удалить подкаст Поделиться ссылкой на сайт - Ссылка на канал Подтвердите удаление канала и всех выпусков, загруженных с этого канала. Удаление канала Обновить весь канал @@ -87,8 +86,8 @@ Удалить Удалить Отметить как прочитанное - Отметить как непрочитанное Помечено как прослушанное + Отметить как непрочитанное Добавить в очередь Удалить из очереди Посетить сайт @@ -202,8 +201,6 @@ Автоматическое удаление Воспроизведение Сеть - Интервал обновлений - Укажите интервал через который каналы обновляются автоматически, или отключите его Загружать файлы только через Wi-Fi Непрерывное воспроизведение Загрузка по Wi-Fi @@ -294,9 +291,6 @@ Таймер сна Осталось времени:\u0020 Неправильный ввод, время должно быть в виде числа - с - м - ч Категории Лучшее @@ -365,6 +359,7 @@ Авторизация Изменить имя пользователя и пароль для этого подкаста и его выпусков. + Импорт подписок из одноцелевых приложений… Поиск в iTunes diff --git a/core/src/main/res/values-sv-rSE/strings.xml b/core/src/main/res/values-sv-rSE/strings.xml index c0c49ca7d..ad970e521 100644 --- a/core/src/main/res/values-sv-rSE/strings.xml +++ b/core/src/main/res/values-sv-rSE/strings.xml @@ -3,41 +3,49 @@ AntennaPod Flöden - Lägg till podcast + Lägg till Podcast PODCASTS EPISODER - Nya episoder - Alla episoder + Nya Episoder + Alla Episoder Ny Väntelista Inställningar - Lägg till podcast + Lägg till Podcast Nedladdningar Körs Färdiga Logg - Avbryt nedladdning + Avbryt\nNedladdning Uppspelningshistorik gpodder.net - gpodder.net login + Inloggning till gpodder.net Nyligen publicerade - Visa bara nya episoder + Visa bara nya Episoder Öppna meny Stäng meny Lådinställningar + Sortera efter räknare + Sortera alfabetiskt + Antal nya och ospelade episoder + Antal nya episoder + Antal ospelade episoder + Inga - Öppna i webbläsare + Öppna i Webbläsare Kopiera URL Dela URL - Kopierade URL till clipboard. - Gå hit + Kopierade URL:en till Urklipp + Gå till denna Position - Rensa historik + Rensa Historiken Bekräfta Avbryt + Ja + Nej Skapare Språk URL @@ -60,27 +68,39 @@ Stäng Försök igen Inkludera i automatiska nedladdningar + Applicera på Föregående Episoder + Den nya inställningen Automatisk Nedladdning kommer automatiskt att appliceras på nya episoder.\nVill du också applicera det på tidigare episoder? + Ta automatiskt bort episod\n(åsidosätter global standardinställning) \u0020parallella nedladdningar + Global + Alltid + Aldrig Flödets URL URL till flöde eller webbsida Lägg till podcast via URL - Hitta podcast i mapp + Hitta Podcast i Biblioteket Du kan söka efter podcasts baserat på namn, kategori eller populäritet med tjänsten gpodder.net eller på iTunes Store. Bläddra på gpodder.net Markera alla som spelade - Markera alla episoder som spelade + Markera alla Episoder som spelade Bekräfta att du verkligen vill markera alla episoder som spelade. Bekräfta att du verkligen vill markera alla episoder i detta flöde som spelade. + Markera alla som sedda Visa information - Ta bort podcast - Dela hemsidans länk - Dela flödeslänk + Ta bort Podcast + Dela... + Dela Länk + Dela Länk med Position + Dela Flödets URL + Dela Episodens URL + Dela Episodens URL med Position Bekräfta att du vill ta bort denna feed och ALLA avsnitt av denna feed som du har hämtat. - Tar bort flöde - Uppdatera hela flödet - Dölj episoder + Tar bort Flöde + Uppdatera hela Flödet + Dölj Episoder + Applicera åtgärder Ospelade Pausad Spelad @@ -97,10 +117,10 @@ Stopp Strömma Ta bort - Ta bort episod + Ta bort Episod Markera som spelad - Markera som ospelad Markera som spelad + Markera som ospelad Lägg till i kön Lägg till i Kö Ta bort från Kön @@ -109,24 +129,24 @@ Lägg till alla i kön Ladda ner alla Hoppa över episod - Aktivera automatisk nedladdning - Avaktivera automatisk nedladdning - Nollställ uppspelningsposition + Aktivera Automatisk Nedladdning + Avaktivera Automatisk Nedladdning + Nollställ Uppspelningspositionen lyckades misslyckades Avvaktar nedladdning Nedladdning pågår - Lagringsenhet hittades inte - Otillräckligt utrymme + Hittade ingen lagringsenhet + Otillräckligt Utrymme Filfel HTTP data fel Okänt fel Tolkningsfel - Flödestyp utan stöd + Flödestypen stöds inte Anslutningsfel - Okänd värd - Autentiseringsproblem + Okänd Värd + Autentiseringsfel Avbryt alla nedladdningar Nedladdning avbruten Nedladdning avbruten\nStängde av Automatisk nedladdning för denna sak @@ -134,13 +154,13 @@ Nedladdningsrapport Felaktig webbadress IO fel - Request fel - Ingen tillgång till databasen + Förfrågningsfel + Åtkomstfel till databasen \u0020Nedladdningar kvar Bearbetar nedladdningar Laddar ner podcastdata %1$d nedladdningar lyckades, %2$d misslyckades - Okänd titel + Okänd Titel Flöde Mediafil Bild @@ -148,10 +168,10 @@ Autentisering krävs Resursen du begärde kräver ett användarnamn och ett lösenord Bekräfta mobil nedladdning - Nedladdning över mobil dataanslutning är avaktiverat i inställningarna.\n\nAktivera tillfälligt eller bara lägg till i kön?\n\nDitt val gäller i 10 minuter. - Nedladdning över mobil dataanslutning är avstängt i inställningarna.\n\nAktivera tillfälligt?\n\nDitt val gäller i 10 minuter. - Lägg bara till i kön - Aktivera tillfälligt + Nedladdning över mobil dataanslutning är avaktiverat i inställningarna.\n\nDu kan välja att antingen bara lägga till episoden i kön eller att tillfälligt tillåta nedladdning.\n\nDitt val gäller i 10 minuter. + Nedladdning över mobil dataanslutning är avaktiverat i inställningarna.\n\nVill du tillfälligt tillåta nedladdning?\n\nDitt val gäller i 10 minuter. + Köa + Tillåt tillfälligt Fel! Inget media spelar @@ -166,9 +186,9 @@ Spelar podcast AntannaPod - Okänd mediaknapp: %1$d - Lås kön - Lås upp kön - Rensa kön + Lås Kön + Lås upp Kön + Rensa Kön Ångra Föremålet avlägsnades Flytta längst upp @@ -229,37 +249,47 @@ Smart markering av uppspelat innehåll Uppspelning Nätverk - Uppdateringsintervall - Ange ett intervall för att automatiskt uppdatera flödet eller avaktivera det + Uppdateringsintervall eller Tid på Dagen + Ange ett intervall eller specifik tid på dagen för att uppdatera flödena automatisk. + Du kan välja ett intervall som \"var 2 timmar\", en specifik tid på dagen som \"07:00\" eller avaktivera automatiska uppdateringar helt.\n\nNotera: Uppdateringstiderna är inte exakta. Korta fördröjningar kan uppstå. + Avaktivera + Sätt intervall + Sätt Tid på Dagen Hämta mediefiler endast över WiFi - Kontinuerlig uppspelning + Kontinuerlig Uppspelning WiFi nedladdning - Hörlurar bortkopplade - Hörlurar återanslutna - Mobila uppdateringar + Hörlurar Bortkopplade + Hörlurar Återanslutna + Mobila Uppdateringar Tillåt uppdateringar via mobil dataanslutning Uppdaterar Flattr inställningar Flattr inloggning För att Flattra saker direkt från appen, logga in på ditt Flattr-konto. - Flattra den här appen + Flattra denna App Stöd utvecklingen av AntennaPod genom att flattra den. Tack! Återkalla åtkomst Återkalla behörigheten till ditt Flattr-konto för denna app. Automatisk Flattring Konfigurerar automatisk Flattring Användargränssnitt - Välj tema - Ändra navigationslådan + Välj Tema + Anpassa Navigeringsrutan + Anpassa utseendet på navigeringsrutan. + Välj saker i Navigeringsrutan Ändra vilka saker som visas i navigationslådan. + Välj Prenumerationsordning + Ändra ordningen på dina prenumerationer + Välj Prenumerationsräknaren + Ändra informationen som visas av prenumerationsräknaren Ändra utseendet på AntennaPod. - Automatisk nedladdning + Automatisk Nedladdning Konfigurera automatisk nedladdning av episoder. Aktivera WiFi filtrering Tillåt automatisk nedladdning endast för utvalda WiFi-nätverk. Nedladdning vid batteridrift Tillåt automatisk nedladdning när batteriet inte laddas - Parallella nedladdningar + Parallella Nedladdningar Episodcache Ljust Mörkt @@ -281,12 +311,16 @@ Använd standardvärden Expandera notifieringar Expandera alltid notifieringen för att visa uppspelningskontrollerna. - Bestående uppspelningskontroller + Bestående Uppspelningskontroller Behåll notifiering och kontroller på låsskärmen när uppspelningen pausas. + Visa Nedladdningsrapport + Visa en rapport med detaljer om felet när nedladdningar misslyckas. Androidversioner före 4.1 har inte stöd för expanderade notifieringar. Lägg till episoder först i kön. - Köa först. + Köa Först Avaktiverad + Bildcachestorlek + Storleken på bildcachen på disken. Aktivera automatisk Flattring Flattra episoden så snart %d procent har spelats @@ -305,19 +339,20 @@ Använd en extern applikation som Dropbox, Google Drive eller ditt favoritval av filhanterare för att öppna en OPML fil. Flera applikationer som Google Mail, Dropbox, Google Drive och de flesta filhanterare kan öppna OPML filer med AntennaPod. Påbörja importering - Importera OPML-fil + OPML Importering FEL! Läser OPML-fil Ett fel har skett vid iläsning av opml dokumentet: Katalogen är tom. Välj alla Avmarkera alla + Välj ... Från lokalt filsystem Använd extern applikation OPML export Exporterar... Exporteringsfel - OPML export lyckades + OPML Exportering lyckades. .opml filen skrevs till:\u0020 Ställ in sömntimer @@ -326,9 +361,21 @@ Sömntimer Återstående tid:\u0020 Ogiltigt tal, tiden måste vara ett heltal - sekunder - minuter - timmar + sekunder + minuter + timmar + + 1 sekund + %d sekunder + + + 1 minut + %d minuter + + + 1 timme + %d timmar + KATEGORIER BÄSTA PODCASTS @@ -360,7 +407,7 @@ Vald mapp: Skapa mapp - Välj mapp + Välj Datakatalog Skapa ny mapp med namnet \"%1$s\"? Skapade ny mapp Kan inte skriva till den här mappen @@ -370,9 +417,10 @@ Den mapp du har valt är inte tom. Filer kommer att placeras direkt i denna mapp. Fortsätt ändå? Välj standardmapp Pausa uppspelning istället för att sänka volymen när en annan app vill spela ljud - Pausa för avbrott + Pausa för Avbrott Återuppta uppspelning när ett telefonsamtal avslutas - Återuppta efter samtal + Fortsätt efter Samtal + AntennaPod behöver startas om för att denna inställning ska gälla. Prenumerera Prenumererar @@ -399,7 +447,29 @@ Autentisering Byt ditt användarnamn och lösenord för den här podcasten och dess episoder. + + Uppgraderar databasen Importerar prenumerationer från appar gjorda för ett enda syfte... Leta i iTunes + Välj ... + Alla + Välj alla Episoder + Inga + Avmarkera alla Episoder + Spelade + Valde spelade Episoder + Ospelade + Valde ospelade Episoder + Nedladdade + Valde nedladdade Episoder + Ej nedladdade + Valde ej nedladdade Episoder + Sortera efter ... + Titel (A \u2192 Ö) + Titel (Ö \u2192 A) + Datum (Ny \u2192 Gammal) + Datum (Gammal \u2192 Ny) + Längd (Kort \u2192 Lång) + Längd (Lång \u2192 Kort) diff --git a/core/src/main/res/values-uk-rUA/strings.xml b/core/src/main/res/values-uk-rUA/strings.xml index b6cd8ca98..d156d2fa1 100644 --- a/core/src/main/res/values-uk-rUA/strings.xml +++ b/core/src/main/res/values-uk-rUA/strings.xml @@ -76,7 +76,6 @@ Інформація Видалити подкаст Поділитися URL сайту - Поділитися URL каналу Ви впенені що хочете видаліти канал та всі завантажені епізоди Удаляю канал Оновити канал цілком @@ -99,8 +98,8 @@ Видалити Видалити епізод Позначити як граний - Позначити як не граний Позначено як граний + Позначити як не граний Додати до черги Додано до черги Видалити з черги @@ -229,8 +228,6 @@ Розумне позначення граних епізодів Відтворення Мережа - Частота оновлень - Визначити інтервал часу для автооновлювання або відключити автооновлення Завантажувати тільки через Wifi Грати безперервно Завантаження через Wifi @@ -326,9 +323,6 @@ Таймер сну Залишилось:\u0020 Помилка вводу, час повинен бути цілим - секунд - хвилин - годин КАТЕГОРІЇ ТОП ПОДКАСТІВ @@ -399,6 +393,7 @@ Автентикація Змінити ваші логін та пароль для подкаста та епізодів + Імпорт подкастів з інших програм... Пошук в iTunes -- cgit v1.2.3 From d252544d2fee0e8a2c6a18b38777cf4dc7b641c6 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 8 Aug 2015 14:22:09 -0400 Subject: Cache all images (should reduce lag displaying lists of episodes) Cache strategy is now set in ApGlideSettings and referenced everywhere else from there. --- .../java/de/danoeh/antennapod/core/glide/ApGlideSettings.java | 11 +++++++++++ .../antennapod/core/service/playback/PlaybackService.java | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java new file mode 100644 index 000000000..cc8a1fe4b --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java @@ -0,0 +1,11 @@ +package de.danoeh.antennapod.core.glide; + +import com.bumptech.glide.load.engine.DiskCacheStrategy; + +/** + * Created by Tom on 8/8/15. + */ +public class ApGlideSettings { + + public static final DiskCacheStrategy AP_DISK_CACHE_STRATEGY = DiskCacheStrategy.ALL; +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index aa1816e1c..7e3f27856 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -46,6 +46,7 @@ import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; +import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeAction; import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeAction.Action; import de.danoeh.antennapod.core.preferences.GpodnetPreferences; @@ -801,7 +802,7 @@ public class PlaybackService extends Service { icon = Glide.with(PlaybackService.this) .load(info.playable.getImageUri()) .asBitmap() - .diskCacheStrategy(DiskCacheStrategy.SOURCE) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) .into(-1, -1) // this resizing would not be exact, so we have // scale the bitmap ourselves .get(); -- cgit v1.2.3 From 4832b1aeb28d29644169022bc2ec8196809a9858 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 8 Aug 2015 16:37:14 -0400 Subject: updated comment --- core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java index cc8a1fe4b..fc1acd0e1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApGlideSettings.java @@ -3,7 +3,7 @@ package de.danoeh.antennapod.core.glide; import com.bumptech.glide.load.engine.DiskCacheStrategy; /** - * Created by Tom on 8/8/15. + * The settings that AntennaPod will use for various Glide options */ public class ApGlideSettings { -- cgit v1.2.3 From 652063b060e8e8407fb1ee32c262b37f7531b3c3 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Thu, 13 Aug 2015 18:34:34 -0400 Subject: updated strings from transifex --- core/src/main/res/values-da/strings.xml | 9 +-- core/src/main/res/values-de/strings.xml | 16 +++++ core/src/main/res/values-es-rES/strings.xml | 4 +- core/src/main/res/values-fr/strings.xml | 94 +++++++++++++++++++++++++++++ core/src/main/res/values-hi-rIN/strings.xml | 4 +- core/src/main/res/values-it-rIT/strings.xml | 45 ++++++++++++++ core/src/main/res/values-iw-rIL/strings.xml | 11 +--- core/src/main/res/values-ko/strings.xml | 72 ++++++++++++++++++++++ core/src/main/res/values-pl-rPL/strings.xml | 9 +-- core/src/main/res/values-pt/strings.xml | 92 ++++++++++++++-------------- core/src/main/res/values-ru/strings.xml | 24 ++++++-- core/src/main/res/values-tr/strings.xml | 9 +-- core/src/main/res/values-uk-rUA/strings.xml | 78 ++++++++++++++++++++++++ core/src/main/res/values-zh-rCN/strings.xml | 7 +-- 14 files changed, 378 insertions(+), 96 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values-da/strings.xml b/core/src/main/res/values-da/strings.xml index ba7fafca6..cc18185ec 100644 --- a/core/src/main/res/values-da/strings.xml +++ b/core/src/main/res/values-da/strings.xml @@ -71,7 +71,6 @@ Vis information Fjern podcast Del webside link - Del feed link Bekræft venligst at du vil fjerne dette feed og ALLE episoder du har downloadet fra dette feed. Fjerner feed Opdater hele feed\'et @@ -197,8 +196,6 @@ Slet Automatisk Afspilning Netværk - Opdaterings interval - Specificer et interval indenfor hvilket feeds opdaterer automatisk eller deaktiver det Download kun medie filer over WiFi Kontinuerlig afspilning WiFi medie download @@ -240,8 +237,6 @@ Skift din gpodder.net kontos login information. Afspilningshastigheder Tilpas tilgængelige hastigheder for variabelt afspilningshastigheds plugin - Søg tid - Søg så mange sekunder når der spoles tilbage eller frem Indstil værtsnavn Brug standard vært Udvid notifikation @@ -283,9 +278,6 @@ Søvn timer Tid tilbage:\u0020 Ugyldig indtastning, tid skal være et heltal - sekunder - minutter - timer KATEGORIER TOP PODCASTS @@ -354,6 +346,7 @@ Godkendelse Skift dit brugernavn og kodeord for denne podcast og dets episoder. + Importerer abonnementer fra single-purpose apps… diff --git a/core/src/main/res/values-de/strings.xml b/core/src/main/res/values-de/strings.xml index c6e7acbcc..47a0d7877 100644 --- a/core/src/main/res/values-de/strings.xml +++ b/core/src/main/res/values-de/strings.xml @@ -251,6 +251,7 @@ Netzwerk Aktualisierungsintervall oder -tageszeit Lege ein Intervall oder eine Tageszeit zur automatischen Aktualisierung der Podcasts fest + Du kannst ein festes Intervall wie \"alle 2 Stunden\", eine bestimmte Tageszeit wie \"7 Uhr morgens\" festlegen oder die automatische Aktualisierung komplett deaktivieren.\n\nBitte beachte: Der Zeitpunkt der Aktualisierung ist ungenau. Du wirst vielleicht eine kurze Verzögerung bemerken. Deaktivieren Intervall einstellen Tageszeit festlegen @@ -360,6 +361,21 @@ Schlummerfunktion Zeit übrig:\u0020 Ungültige Eingabe, Zeit muss eine Ganzzahl sein + Sekunden + Minuten + Stunden + + 1 Sekunde + %d Sekunden + + + 1 Minute + %d Minuten + + + 1 Stunde + %d Stunden + KATEGORIEN BESTE PODCASTS diff --git a/core/src/main/res/values-es-rES/strings.xml b/core/src/main/res/values-es-rES/strings.xml index d05c34876..2607d1794 100644 --- a/core/src/main/res/values-es-rES/strings.xml +++ b/core/src/main/res/values-es-rES/strings.xml @@ -42,7 +42,6 @@ Marcar todo como leído Información del programa Compartir el enlace de la web - Compartir el enlace del canal Confirme que quiere eliminar este canal y TODOS los episodios descargados del mismo. Descargar @@ -125,8 +124,6 @@ Saltar al siguiente elemento de la cola al acabar la reproducción Reproducción Red - Intervalo de actualización - Especificar el intervalo en que se actualizarán automáticamente los canales, o desactivarlo Solo descargar los contenidos por WiFi Reproducción continua Descarga de contenidos por WiFi @@ -193,5 +190,6 @@ + diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml index 3b952e56b..10d3fe9a4 100644 --- a/core/src/main/res/values-fr/strings.xml +++ b/core/src/main/res/values-fr/strings.xml @@ -26,6 +26,12 @@ Ouvrir le menu Fermer le menu + Trier par compteur + Trier alphabétiquement + Nombre de nouveaux épisodes non-lus + Nombre de nouveaux épisodes + Nombre d\'épisodes non-lus + Aucun Ouvrir dans le navigateur Copier l\'URL @@ -37,8 +43,11 @@ Confirmer Annuler + Oui + Non Auteur Langue + URL Préférences Image Erreur @@ -58,7 +67,11 @@ Fermer Réessayer Télécharger automatiquement à l\'avenir + Appliquer aux épisodes précédents \u0020téléchargements parallèles + Global + Toujours + Jamais URL du flux URL ou flux ou site web @@ -71,12 +84,29 @@ Tous les épisodes ont été marqués comme lus Veuillez confirmer que vous voulez bien marquer tous les épisodes comme lus Veuillez confirmer que vous voulez bien marquer tous les épisode de ce flux comme lus + Marquer tout comme vu Voir les détails Supprimer le podcast + Partager... Partager un lien vers le site + Partager lien avec position + Partager lien du flux + Partager lien de l\'épisode + Partager lien de l\'épisode avec position Veuillez confirmer que vous voulez bien supprimer ce flux et TOUS ses épisodes que vous avez téléchargés. Flux en cours de suppression Mettre à jour tout le flux + Cacher épisodes + Appliquer les actions + Non joués + En pause + Joués + Rajouté à la liste + Pas rajouté à la liste + Téléchargé + Non téléchargé + Filtré + {fa-exclamation-circle} Dernière mise à jour échouée Télécharger Lire @@ -89,12 +119,15 @@ Les épisodes ont été marqués comme lus Marquer comme non lu Ajouter à la liste + Ajouté à la liste Supprimer de la liste Visiter le site Flattr ça! Ajouter tous à la liste Tous télécharger Passer cet épisode + Activer téléchargement automatique + Désactiver téléchargement automatique terminé échoué @@ -113,6 +146,7 @@ Annuler tous les téléchargements Téléchargement annulé Téléchargements terminés + Rapport des téléchargements URL incorrecte Erreur d\'E/S Erreur de requête @@ -128,6 +162,9 @@ Une erreur s\'est produite durant le téléchargement du fichier :\u0020 Authentification requise La ressource que vous avez demandé nécessite un nom d\'utilisateur et un mot de passe + Confirmer téléchargement mobile + Rajouter à la liste + Permettre temporairement Erreur ! Pas de lecture en cours @@ -142,6 +179,8 @@ Lecture de podcast en cours AntennaPod - Touche média inconnue : %1$d + Bloquer la liste + Débloquer la liste Effacer la liste Annuler Élément retiré @@ -199,8 +238,12 @@ Après la fin d\'un épisode, passer au suivant Supprimer l\'épisode quand la lecture est finie Supression automatique + Marquer les épisodes comme lus même s\'il reste encore moins d\'un certain intervalle de temps + Marquer comme lu intelligent Lecture Réseau + Désactiver + Définir intervalle Ne télécharger les épisodes que par Wi-Fi Lecture continue Téléchargement en Wi-Fi @@ -220,6 +263,10 @@ Configurer les paiements flattr automatiques Interface utilisateur Choisir un thème + Définir ordre des abonnements + Change l\'ordre de vos abonnements + Définir compteur des abonnements + Change l\'information affichée à côté du compteur des abonnements Modifier l\'apparence d\'AntennaPod. Téléchargement automatique Configurer le téléchargement automatique des épisodes. @@ -243,15 +290,22 @@ Modifier les information de connexion pour votre compte gpodder.net Vitesses de lecture Modifier la liste des vitesses disponibles pour la lecture audio + Avance rapide + Retour en arrière Choisir un nom de domaine Utiliser le nom de domaine par défaut Etendre la notification Toujours étendre les notifications pour montrer les boutons de lecture Boutons de lecture permanents Garder les notifications et les boutons de lecture sur l\'écran de verouillage quand la lecture est en pause + Afficher rapport des téléchargements + Si les téléchargements échouent, générer un rapport des détails des échecs. Les versions d\'Android antérieures à 4.1 ne sont pas compatibles avec les notifications élargies Ajouter de nouveaux épisodes en tête de file Mettre au début de la file d\'attente + Désactivé + Taille de la cache d\'image + Taille de l’espace disque pour stocker temporairement les images. Activer le paiement flattr automatique Lancer un paiement flattr pour un épisode dès que %d de l\'épisode a été joué @@ -277,6 +331,7 @@ Le répertoire d\'importation est vide. Tout choisir Ne rien choisir + Sélectionner... Depuis le système de fichier local Utiliser une application tierce Exportation OPML @@ -291,6 +346,21 @@ Arrêt automatique Durée restante :\u0020 Entrée invalide, la durée doit être un nombre entier + secondes + minutes + heures + + 1 seconde + %d secondes + + + 1 minute + %d minutes + + + 1 heure + %d heures + CATEGORIES PODCASTS POPULAIRES @@ -333,6 +403,9 @@ Choisir le répertoire par défaut Mettre la lecture en pause au lieu de baisser le volume quand une autre application veut jouer un son Mettre en pause lors des interruptions + Reprendre la lecture après un appel téléphonique + Reprendre après appel + AntennaPod doit être redémarré afin que ce changement prenne effet S\'abonner Abonné @@ -360,7 +433,28 @@ Authentification Modifier votre identifiant et mot de passe pour ce podcast et tous ses épisodes + Mise à jour de la base de données Importation des abonnements à partir d\'applications à usage unique... Chercher sur iTunes + Sélectionner ... + Tout + Sélectionné tous les épisodes + Aucun + Désélectionné tous les épisodes + Joués + Sélectionné tous les épisodes joués + Non joués + Sélectionné tous les épisodes non joués + Téléchargés + Sélectionné tous les épisodes téléchargés + Non téléchargés + Sélectionné tous les épisodes non téléchargés + Trier par ... + Titre (A \u2192 Z) + Titre (Z \u2192 A) + Date (Nouveau \u2192 Ancien) + Date (Ancien \u2192 Nouveau) + Durée (Courte \u2192 Longue) + Durée (Longue \u2192 Courte) diff --git a/core/src/main/res/values-hi-rIN/strings.xml b/core/src/main/res/values-hi-rIN/strings.xml index f32c7c02f..13ef6d489 100644 --- a/core/src/main/res/values-hi-rIN/strings.xml +++ b/core/src/main/res/values-hi-rIN/strings.xml @@ -57,7 +57,6 @@ पॉडकास्ट हटाएँ शेयर वेबसाइट लिंक - शेयर फ़ीड लिंक इसकी पुष्टि करें कि आप इस फ़ीड और इस फ़ीड के सभी प्रकरणों को हटाना चाहते हैं जिन्हें आपने डाउनलोड किया है. फ़ीड निकाल रहा है @@ -158,8 +157,6 @@ प्लेबैक के पूरा होने पर अगली पंक्ति आइटम के लिए जाएँ प्लेबैक संजाल - अंतराल अद्यतन - फ़ीड स्वचालित रूप से ताजा कर रहे हैं जिसमें एक अंतराल निर्दिष्ट करें या उसे निष्क्रिय करें केवल वाईफ़ाई पर मीडिया फ़ाइलें डाउनलोड करें सतत प्लेबैक वाईफाई मीडिया डाउनलोड करें @@ -274,5 +271,6 @@ डाउनलोड कर रहा है ... + diff --git a/core/src/main/res/values-it-rIT/strings.xml b/core/src/main/res/values-it-rIT/strings.xml index c12fedbaa..a7ddf81d3 100644 --- a/core/src/main/res/values-it-rIT/strings.xml +++ b/core/src/main/res/values-it-rIT/strings.xml @@ -26,6 +26,11 @@ Apri il menù Chiudi il menù + Ordina alfabeticamente + Numero di episodi nuovi e non riprodotti + Numero di episodi nuovi + Numero di episodi non riprodotti + Nessuno Apri nel browser Copia URL @@ -37,6 +42,8 @@ Conferma Annulla + + No Autore Lingua URL @@ -59,7 +66,11 @@ Chiudi Riprova Includi nei download automatici + Applica ai Precedenti Episodi \u0020download paralleli + Globale + Sempre + Mai URL del feed www.example.com/feed @@ -70,9 +81,13 @@ Segna tutti come riprodotti Segnati tutti gli episodi come riprodotti + Segna tutti come visti Informazioni Rimuovi un podcast + Condividi... Condividi il link al sito + Condividi URL del Feed + Condividi URL dell\'Episodio Per favore conferma la cancellazione di questo feed e di TUTTI gli episodi collegati che sono stati precedentemente scaricati. Rimozione feed Ricarica il feed completo @@ -219,6 +234,7 @@ Elimina automaticamente Riproduzione Rete + Disabilita Abilita il download dei media solo tramite WiFi Playback continuo Download dei media su WiFi @@ -267,6 +283,7 @@ Espandi sempre le notifiche per mostrare i pulsanti di riproduzione. Controlli di riproduzione persistenti Mantieni le notifiche e i controlli del blocco dello schermo quando la riproduzione è in pausa. + Mostra il Rapporto del Download Le versioni di Android prima della 4.1 non supportano le notifiche estese. Disabilitato @@ -305,6 +322,21 @@ Timer di spegnimento Tempo residuo:\u0020 Input non valido, il campo deve essere un numero intero. + secondi + minuti + ore + + 1 secondo + %d secondi + + + 1 minuto + %d minuti + + + 1 ora + %d ore + CATEGORIE TOP PODCAST @@ -378,4 +410,17 @@ Importazione di sottoscrizioni da applicazioni monouso in corso... Cerca su iTunes + Seleziona ... + Tutti + Tutti gli Episodi Selezionati + Nessuno + Tutti gli Episodi Deselezionati + Riprodotto + Non riprodotto + Titolo (A \u2192 Z) + Titolo (Z \u2192 A) + Data (New \u2192 Old) + Data (Old \u2192 New) + Durata (Short \u2192 Long) + Durata (Long \u2192 Short) diff --git a/core/src/main/res/values-iw-rIL/strings.xml b/core/src/main/res/values-iw-rIL/strings.xml index 20ddd6d71..07f3602ff 100644 --- a/core/src/main/res/values-iw-rIL/strings.xml +++ b/core/src/main/res/values-iw-rIL/strings.xml @@ -78,7 +78,6 @@ הצג מידע הסר פודקאסט שתף קישור אתר - שתף קישור הזנה אשר מחיקת הזנה זו ואת כל פרקי ההזנה שהורדת. הסר הזנה רענן את כל ההזנה @@ -91,8 +90,8 @@ הסר הסר פרק סמן כנקרא - סמן כלא נקרא סומן כנקרא + סמן כלא נקרא הוסף לתור הסר מהתור בקר באתר @@ -207,8 +206,6 @@ מחיקה אוטומטית ניגון רשת - זמן בין עידכונים - ציין פרק זמן שבו ההזנות עוברות רענון באופן אוטומטי או לבטל ריענון הורד קבצי מדיה רק דרך חיבור אינטרנט אלחוטי ניגון מתמשך הורדת מדיה דרך אינטרנט אלחוטי @@ -251,8 +248,6 @@ שנה פרטי התחברות של חשבון gpodder.net. מהירויות ניגון התאמת המהיריות הזמינות לניגון במהירות משתנה - זמן דילוג - דלג מספר שניות זה בדילוג לאחור או קדימה הגדר שם שרת השתמש בשרת ברירת מידל הרחב הודעה @@ -301,9 +296,6 @@ טיימר שינה זמן נותר:\u0020 קלט לא חוקי, זמן חייב להיות מספר שלם - שניות - דקות - שעות קטגוריות פודקאסטים בכירים @@ -372,6 +364,7 @@ אימות שנה את שם המשתמש והסיסמה שלך לפודקאסט ופרקים שלו. + מייבא רישום מאפליקציות יעודיות... חפש בiTunes diff --git a/core/src/main/res/values-ko/strings.xml b/core/src/main/res/values-ko/strings.xml index fcfa89e88..7c9f76fcf 100644 --- a/core/src/main/res/values-ko/strings.xml +++ b/core/src/main/res/values-ko/strings.xml @@ -27,6 +27,12 @@ 메뉴 열기 메뉴 닫기 드로어 기본 설정 + 카운터로 정렬 + 사전 순서로 정렬 + 새로운 에피소드와 재생하지 않은 에피소드 수 + 새로운 에피소드 수 + 재생하지 않은 에피소드 수 + 없음 브라우저에서 열기 URL 복사 @@ -38,6 +44,8 @@ 확인 취소 + + 아니요 저자 언어 URL @@ -60,7 +68,13 @@ 닫기 다시 시도 자동 다운로드에 포함 + 예전 에피소드에 적용 + 새로운 <i>자동 다운로드</I> 설정은 자동으로 새로운 에피소드에 적용됩니다. 예전 에피소드에도 적용하시겠습니까? + 에피소드 자동 삭제\n(전체 설정보다 우선) \u0020동시 다운로드 + 전체 설정 + 항상 + 안 함 피드 URL 피드의 URL 또는 홈페이지 @@ -73,13 +87,20 @@ 모든 에피소드를 재생했다고 표시했습니다 모든 에피소드를 재생했다고 표시할지 확인하십시오. 이 피드에 들어 있는 모든 에피소드를 재생했다고 표시할지 확인하십시오. + 모두 봤다고 표시 정보 표시 팟캐스트 제거 + 공유... 홈페이지 링크 공유 + 위치와 같이 링크 공유 + 피드 URL 공유 + 에피소드 URL 공유 + 위치와 같이 에피소드 URL 공유 이 피드와 이 피드에서 다운로드한 모든 에피소드를 삭제하시려면 확인을 누르십시오. 피드 삭제하는 중 전체 피드 새로고침 에피소드 감추기 + 동작 적용 재생 안 함 일시 중지 재생함 @@ -228,6 +249,12 @@ 똑똑하게 재생한 것으로 표시 재생 네트워크 + 업데이트 주기 또는 하루 중 시각 + 피드를 자동으로 새로 고칠 주기 또는 하루 중 특정 시각을 지정하십시오 + \"매 2시간\"과 같이 주기를 지정할 수도 있고, \"오전 7:00\"와 같이 하루 중 시각을 지정할 수도 있고, 자동 업데이트를 모두 사용 안 할 수도 있습니다.\n\n안내: 업데이트 시간은 정확하지 않습니다. 약간 늦게 업데이트할 수 있습니다. + 사용 안 함 + 주기 지정 + 하루 중 시각 지정 Wi-Fi를 통해서만 미디어 파일 다운로드 연속 재생 Wi-Fi 미디어 다운로드 @@ -247,8 +274,14 @@ 자동 flattr 설정 사용자 인터페이스 테마 선택 + 네비게이션 드로어 사용자 설정 + 네비게이션 드로어의 모양을 사용자 설정합니다. 네비게이션 드로어 바꾸기 네비게이션 드로어에 어떤 항목을 표시할지 바꿉니다. + 구독 순서 설정 + 구독 순서를 바꿉니다 + 구독 카운터 설정 + 구독 카운터에 따라 표시되는 정보를 바꿉니다 안테나팟의 겉모양을 바꿉니다. 자동 다운로드 에피소드 자동 다운로드를 설정합니다. @@ -280,10 +313,14 @@ 항상 알림에서 재생 버튼이 표시되도록 확장 재생 조작 고정 재생이 일시 중지했을 때에도 알림과 잠금 화면의 조작 기능 유지 + 다운로드 보고서 보기 + 다운로드가 실패하면, 실패를 자세히 표시하는 보고서를 만듭니다. 안드로이드 4.1 전 버전에서는 알림 확장을 지원하지 않습니다. 새 에피소드를 대기열 앞에 추가합니다. 대기열 앞에 추가 사용 안 함 + 이미지 캐시 크기 + 이미지에 사용할 디스크 캐시 크기 자동 flattr 사용 %d 퍼센트를 재생하면 에피소드에 flattr합니다 @@ -309,6 +346,7 @@ 가져오기 디렉터리가 비어 있습니다. 모두 선택 모두 선택 해제 + 선택... 로컬 파일시스템에서 외부 앱 사용 OPML 내보내기 @@ -323,6 +361,18 @@ 취침 타이머 남은 시간:\u0020 입력이 잘못되었습니다. 시간으로 숫자를 입력해야 합니다. + + + 시간 + + %d초 + + + %d분 + + + %d시간 + 분류 상위 팟캐스트 @@ -367,6 +417,7 @@ 끼어들면 일시 중지 전화 통화가 끝난 후에 재생 다시 시작 통화 후에 다시 시작 + 이 변경 사항을 적용하려면 안테나팟을 다시 시작해야 합니다. 구독 구독함 @@ -394,7 +445,28 @@ 인증 이 팟캐스트와 에피소드에 대한 사용자 이름과 비밀번호를 바꿉니다. + 데이터베이스 업그레이드 중 단일 용도 앱에서 구독 정보를 가져옵니다... iTunes 검색 + 선택 ... + 모두 + 모든 에피소드 선택 + 없음 + 모든 에피소드 선택 해제 + 재생함 + 재생 에피소드 선택 + 재생 안 함 + 재생 안 한 에피소드 선택 + 다운로드함 + 다운로드한 에피소드 선택 + 다운로드 안 함 + 다운로드 안 한 에피소드 선택 + 정렬 ... + 제목 (A \u2192 Z) + 제목 (Z \u2192 A) + 시각 (최근 \u2192 과거) + 시각 (과거 \u2192 최근) + 길이 (짧은 \u2192 긴) + 길이 (긴 \u2192 짧은) diff --git a/core/src/main/res/values-pl-rPL/strings.xml b/core/src/main/res/values-pl-rPL/strings.xml index ba1a0bb91..a43ce7722 100644 --- a/core/src/main/res/values-pl-rPL/strings.xml +++ b/core/src/main/res/values-pl-rPL/strings.xml @@ -71,7 +71,6 @@ Pokaż informacje Usuń podcast Udostępnij stronę - Udostępnij kanał Potwierdź chęć usunięcia tego kanału wraz ze WSZYSTKIMI odcinkami, które zostały pobrane. Usuwanie kanału Odśwież cały kanał @@ -197,8 +196,6 @@ Automatyczne usuwanie Odtwarzanie Sieć - Częstość aktualizacji - Określ częstotliwość automatycznego odświeżania lub je wyłącz Pobieraj pliki tylko przez WiFi Odtwarzanie ciągłe WiFi media pobrane @@ -238,8 +235,6 @@ Zmień dane logowania konta gpodder.net. Prędkość odtwarzania Dostosuj prędkości dostępne dla odtwarzania audio o zmiennej prędkości - Seek time - Przeskocz o tyle sekund przewijając Ustaw nazwę hosta Użyj domyślnego hosta Rozwiń Powiadomienia @@ -281,9 +276,6 @@ Wyłącznik czasowy Pozostały czas:\u0020 Błąd wpisu, czas musi być liczbą całkowitą - sekundy - minuty - godziny KATEGORIE TOP PODCASTY @@ -353,6 +345,7 @@ https://gpodder.net/register/ Autoryzacja Zmień swoją nazwę użytkownika oraz hasło dla tego podcastu i jego odcinków + Importowanie subskrybcji z jednozadaniowych aplikacji diff --git a/core/src/main/res/values-pt/strings.xml b/core/src/main/res/values-pt/strings.xml index 902fe5575..f02cd629e 100644 --- a/core/src/main/res/values-pt/strings.xml +++ b/core/src/main/res/values-pt/strings.xml @@ -12,11 +12,11 @@ Lista de espera Definições Adicionar podcast - Descargas + Transferências Em curso Terminadas Registo - Cancelar\ndescarga + Cancelar\ntransferência Histórico de reprodução gpodder.net Dados gpodder.net @@ -67,11 +67,11 @@ Guardar utilizador e palavra-passe Fechar Tentar novamente - Incluir nas descargas automáticas + Incluir nas transferências automáticas Aplicar aos episódios anteriores - A definição Descarga automática será aplicada a todos os novos episódios.\nGostaria de também a aplicar aos episódios anteriores? + A definição Transferência automática será aplicada a todos os novos episódios.\nGostaria de também a aplicar aos episódios anteriores? Apagar episódio automáticamente\n(altera a definição global) - \u0020descargas simultâneas + \u0020transferências simultâneas Global Sempre Nunca @@ -96,7 +96,7 @@ Partilhar URL da fonte Partilhar URL do episódio Partilhar URL do episódio com posição - Por favor confirme que deseja apagar esta fonte e todos os episódios descarregados + Por favor confirme que deseja apagar esta fonte e todos os episódios transferidos Remover fonte Atualizar todas as páginas da fonte Ocultar episódios @@ -106,12 +106,12 @@ Reproduzidos Na fila Não na fila - Descarregados - Não descarregados + Transferidos + Não transferidos Filtrados {fa-exclamation-circle} Última atualização falhada - Descarregar + Transferir Reproduzir Pausa Parar @@ -127,16 +127,16 @@ Aceder ao sítio web Flattr Colocar tudo na fila - Descarregar tudo + Transferir tudo Ignorar episódio - Ativar descarga automática - Desativar descarga automática + Ativar transferência automática + Desativar transferência automática Repor posição de reprodução sucesso falha - Descarga pendente - Descarga atual + Transferência pendente + Transferência atual Cartão SD não encontrado Espaço insuficiente Erro no ficheiro @@ -147,29 +147,29 @@ Erro de ligação Servidor desconhecido Erro de autenticação - Cancelar descargas - Descarga cancelada - Descarga cancelada\nDescarga automática desativada para este item - Descargas terminadas com erros - Relatório de descargas + Cancelar transferências + Transferência cancelada + Transferência cancelada\nTransferência automática desativada para este item + Transferências terminadas com erros + Relatório de transferências URL inválido Erro I/O Erro de pedido Erro de acesso à base de dados - \u0020Descargas em falta - Processamento de descargas - A descarregar dados do podcast - %1$d descargas efetuadas, %2$d falhadas + \u0020Transferências em falta + Processamento de transferências + A transferir dados do podcast + %1$d transferências efetuadas, %2$d falhadas Título desconhecido Fonte Ficheiro multimédia Imagem - Ocorreu um erro ao descarregar o ficheiro:\u0020 + Ocorreu um erro ao transferir o ficheiro:\u0020 Requer autenticação O recurso solicitado requer um utilizador e uma palavra-passe - Confirmação de descarga - A descarga através de dados móveis está desativada nas definições.\n\nAtivar temporariamente ou apenas adicionar à fila?\n\nA sua decisão será memorizada durante 10 minutos. - A descarga através de dados móveis está desativada nas definições.\n\nAtivar temporariamente?\n\nA sua decisão será memorizada durante 10 minutos. + Confirmação de transferência + A transferência através de dados móveis está desativada nas definições.\n\nAtivar temporariamente ou apenas adicionar à fila?\n\nA sua decisão será memorizada durante 10 minutos. + A transferência através de dados móveis está desativada nas definições.\n\nAtivar temporariamente?\n\nA sua decisão será memorizada durante 10 minutos. Apenas adicionados à fila Ativar temporariamente @@ -227,9 +227,9 @@ O AntennaPod não fez o flattr A obter itens com flattr - Descarregar extra + Transferir extra Extra não instalado - Para que a velocidade variável de reprodução funcione, tem que instalar um biblioteca de terceiros.\n\nClique em Descarregar extra para a transferir no Google Play.\n\nQuaisquer erros que ocorram na utilização do extra devem ser reportados diretamente ao seu programador. + Para que a velocidade variável de reprodução funcione, tem que instalar um biblioteca de terceiros.\n\nClique em Transferir extra para a transferir no Google Play.\n\nQuaisquer erros que ocorram na utilização do extra devem ser reportados diretamente ao seu programador. Velocidades de reprodução Não existem itens nesta lista @@ -255,9 +255,9 @@ Desativar Definir intervalo Definir hora do dia - Apenas descarregar através de redes sem fios + Apenas transferir através de redes sem fios Reprodução contínua - Descarga por Wi-Fi + Transferir por Wi-Fi Auscultadores removidos Auscultadores inseridos Atualizações móveis @@ -283,13 +283,13 @@ Definir contador de subsrições Mudar informação mostrada no contador de subscrições Mudar o aspeto do AntennaPod - Descarga automática - Configure a descarga automática dos episódios + Transferência automática + Configure a transferência automática dos episódios Ativar filtro Wi-Fi - Apenas permitir descargas automáticas através de redes sem fios - Descarregar se não estiver a carregar - Permitir descarga automática se a bateria não estiver a ser carregada - Descargas simultâneas + Apenas permitir transferências automáticas através de redes sem fios + Transferir se não estiver a carregar + Permitir transferência automática se a bateria não estiver a ser carregada + Transferências simultâneas Cache de episódios Claro Escuro @@ -314,7 +314,7 @@ Controlos de reprodução persistentes Manter controlos de notificação e ecrã de bloqueio ao colocar a reprodução em pausa Mostrar relatório de erros - Se a descarga falhar, gera um relatório que mostra os detalhes do erro + Se a transferência falhar, gera um relatório que mostra os detalhes do erro As versões Android anteriores à 4.1 não possuem suporte à expansão de notificações Colocar novos episódios no inicio da fila Novos episódios no inicio @@ -414,7 +414,7 @@ A pasta já existe Não é possível criar a pasta A pasta não está vazia - A pasta escolhida não está vazia. As descargas multimédia e os ficheiros serão colocados nesta pasta. Continuar? + A pasta escolhida não está vazia. As transferências multimédia e os ficheiros serão colocados nesta pasta. Continuar? Escolha a pasta pré-definida Pausa na reprodução em vez de baixar o volume se outra aplicação quiser reproduzir sons Pausa nas interrupções @@ -424,7 +424,7 @@ Subscrever Subscrito - A descarregar... + A transferir... Mostrar capítulos Mostrar notas @@ -436,8 +436,8 @@ Navegar para cima Mais ações Episódio em reprodução - Episódio a ser descarregado - Episódio descarregado + Episódio a ser transferido + Episódio transferido Novo item Episódio está na fila Número de novos episódios @@ -461,10 +461,10 @@ Selecionar episódios reproduzidos Não reproduzidos Selecionar episódios não reproduzidos - Descarregados - Selecionar episódios descarregados - Não descarregados - Selecionar episódios não descarregados + Transferidos + Selecionar episódios transferidos + Não transferidos + Selecionar episódios não transferidos Ordenar por... Título (A \u2192 Z) Título (Z \u2192 A) diff --git a/core/src/main/res/values-ru/strings.xml b/core/src/main/res/values-ru/strings.xml index b8206d906..c2c27484a 100644 --- a/core/src/main/res/values-ru/strings.xml +++ b/core/src/main/res/values-ru/strings.xml @@ -17,7 +17,7 @@ Завершено Журнал Отменить загрузку - История воспроизведения + Журнал gpodder.net Войти на gpodder.net @@ -26,6 +26,12 @@ Открыть меню Закрыть меню + Сортировать по количеству + Сортировать по алфавиту + Количество новых и непрослушанных выпусков + Количество новых выпусков + Количество непрослушанных выпусков + Ничего Открыть в браузере Скопировать ссылку @@ -37,8 +43,11 @@ Подтвердить Отмена + Да + Нет Автор Язык + Адрес Настройки Обложка Ошибка @@ -58,6 +67,7 @@ Закрыть Повторить Добавить в автозагрузки + Применить к предыдущим выпускам \u0020одновременных загрузок URL канала @@ -73,7 +83,8 @@ Подтвердите, что хотите пометить все эпизоды в этом канале как прослушанные. Показать информацию Удалить подкаст - Поделиться ссылкой на сайт + Поделиться... + Поделиться ссылкой Подтвердите удаление канала и всех выпусков, загруженных с этого канала. Удаление канала Обновить весь канал @@ -84,11 +95,12 @@ Остановить Воспроизвести из сети Удалить - Удалить - Отметить как прочитанное + Удалить выпуск + Отметить как прослушанное Помечено как прослушанное - Отметить как непрочитанное + Отметить как непрослушанное Добавить в очередь + Добавлено в очередь Удалить из очереди Посетить сайт Поддержать через Flattr @@ -267,7 +279,7 @@ OPML файлы позволяют перемещать ваши подкасты из одного менеджера подкастов в другой. Укажите путь к файлу на устройстве - Откройте OPML-файл с помощью внешних приложений: Dropbox, Google Drive или любой файловый менеджер. + Откройте OPML-файл с помощью внешних приложений: Dropbox, Google Drive или любого файлового менеджера. Множество приложений умеют открывать OPML-файлы в AntennaPod, например: Google Mail, Dropbox, Google Drive и большинство файловых менеджеров. Начать импорт Импорт OPML diff --git a/core/src/main/res/values-tr/strings.xml b/core/src/main/res/values-tr/strings.xml index 9f80f8532..d202bc67c 100644 --- a/core/src/main/res/values-tr/strings.xml +++ b/core/src/main/res/values-tr/strings.xml @@ -76,7 +76,6 @@ Bilgiyi göster Cep yayını kaldır Web sayfası bağlantısı paylaş - Besleme bağlantısını paylaş Lütfen bu beslemeyi ve bu beslemeye ait indirilmiş BÜTÜN bölümleri silme isteğinizi onaylayın. Besleme kaldırılıyor Tüm beslemeyi yenile @@ -99,8 +98,8 @@ Kaldır Bölümü kaldır Oynatıldı olarak işaretle - Oynatılmadı olarak işaretle Oynatıldı olarak işaretlendi + Oynatılmadı olarak işaretle Kuyruğa Ekle Kuyruğa Eklendi Kuyruktan Kaldır @@ -227,8 +226,6 @@ Otomatik Silme Çalma - Güncelleme aralığı - Beslemeleri yenilemek için bir aralık belirtin veya devre dışı bırakın. Medya dosyalarını sadece kablosuz bağlantı üzerinden indir Devamlı çalma Kablosuz medya indirmesi @@ -322,9 +319,6 @@ Zamanlayıcı Kalan süre:\u0020 Geçersiz giriş, zaman bir tam sayı olmalıdır - saniye - dakika - saat KATEGORİLER POPÜLER CEP YAYINLARI @@ -395,6 +389,7 @@ Yetkilendirme Bu cep yayını ve içerdiği bölümler için kullanıcı adı şifreyi değiştir. + Üyelikler tek-amaçlı uygulamalardan içe aktarılıyor... iTunes\'da Arama diff --git a/core/src/main/res/values-uk-rUA/strings.xml b/core/src/main/res/values-uk-rUA/strings.xml index d156d2fa1..9715e40c3 100644 --- a/core/src/main/res/values-uk-rUA/strings.xml +++ b/core/src/main/res/values-uk-rUA/strings.xml @@ -27,6 +27,12 @@ Показати меню Сховати меню Настройки навігації + Сортувати за лічильником + Сортування за абеткою + Кількість нових та непрослуханих епізодів + Кількість нових епізодів + Кількість непрослуханих епізодів + Жодних Відкрити в браузері Копіювати URL @@ -38,6 +44,8 @@ Підтвердити Скасувати + Так + Ні Автор Мова URL @@ -60,7 +68,13 @@ Закрити Повторити знову Включити до автозавантаження + Застосувати до попередніх епізодів + Нове налаштування Автозавантаження буде автоматично застосоване до нових епізодів.\nБажаєте також застосувати його до попередніх епізодів? + Автоматичне видалення епізода\n(перевизначити глобальне налаштування за замовчуванням) \u0020паралельні завантаження + Для всіх + Завжди + Ніколи Посилання на канал URL канала або сайта @@ -73,13 +87,20 @@ Позначено всі епізоди як грані Будь ласка, підтвердіть що ви бажаєте позначити всі епізоди як грані. Будь ласка, підтвердіть що ви бажаєте позначити всі епізоди цього канала як грані. + Позначити всі як переглянуті Інформація Видалити подкаст + Поділитись... Поділитися URL сайту + Поділитись посиланням на позицію + Поділитись посиланням на канал + Поділитись посиланням на епізод + Поділитись посиланням на епізод з позицією Ви впенені що хочете видаліти канал та всі завантажені епізоди Удаляю канал Оновити канал цілком Приховати епізоди + Застосувати дії Неграні На паузі Грані @@ -228,6 +249,12 @@ Розумне позначення граних епізодів Відтворення Мережа + Частота оновлень або оновлення в зазначений час + Визначити інтервал часу або визначити час щодня для автооновлення + Можливо встановити інтервал як то \"кожні 2 години\", встановити час щодня як то \"7:00\" або відклюсити автоматичне оновлення взагалі.\n\nЗверніть увагу: Час оновлення не є точним. Можливі короткі затримки. + Вимкнути + Встановити інтервал + Встановити час щодня Завантажувати тільки через Wifi Грати безперервно Завантаження через Wifi @@ -247,8 +274,14 @@ Налаштування автоматичного заохочення авторів через сервіс flattr Вигляд Обрати тему + Налаштувати панель навігації + Налаштувати вигляд панелі навігації Змінити настройки навігації Вибрати елементи для використання у навігації + Встановити порядок підписок + Змінити порядок ваших підписок + Встановити лічильник підписок + Змінити інформацію яку відображає лічильник підписок Змінити вигляд AntennaPod Автоматичне завантаження Налаштування автоматичного завантаження епізодів @@ -280,10 +313,14 @@ Завжди розгортати повідомлення, щоб показати кнопки керування. Завжди показувати елементи керування відтворенням Показувати повідомлення та елементи керування на lockscreen в режимі паузи. + Показати звіт про завантаження + У разі помилки при завантаженні створити детальний звіт про помилку. Android до версії 4.1 не підтримує розширені повідомлення. Додавати нові епізоди до початку черги. Додавати в початок черги. Вимкнено + Розмір кеша зображень + Розмір дискового кеша для зображень. Включити автоматичне заохочення авторів через сервіс flattr Заохотити автора через Flattr щойно %d відсотків епізода було відтворено @@ -309,6 +346,7 @@ Директорія імпорту пуста Обрати все Убрати виділення + Обрати ... З локальної файлової системи За допомогою додатка OPML экспорт @@ -323,6 +361,24 @@ Таймер сну Залишилось:\u0020 Помилка вводу, час повинен бути цілим + секунд + хвилин + годин + + 1 секунда + %d секунди + %d секунд + + + 1 хвилина + %d хвилини + %d хвилин + + + 1 година + %d години + %d годин + КАТЕГОРІЇ ТОП ПОДКАСТІВ @@ -367,6 +423,7 @@ Пауза в разі переривання Відновити відтворення після закінчення дзвінка Відновити після дзвінка + Для застосування змін потрібно перезапустити AntennaPod Підписатися Підписано @@ -394,7 +451,28 @@ Автентикація Змінити ваші логін та пароль для подкаста та епізодів + Оновлення бази даних Імпорт подкастів з інших програм... Пошук в iTunes + Обрати ... + Всі + Обрано всі епізоди + Жодного + Жодного епізода обрано + Переглянуті + Обрано переглянуті епізоди + Непереглянуті + Обрано непереглянуті епізоди + Завантажені + Обрано завантажені епізоди + Незавантажені + Обрано незавантажені епізоди + Сортувати за ... + Назва (А \u2192 Я) + Назва (Я \u2192 А) + Дата (Нові \u2192 Старі) + Дата (Старі \u2192 Нові) + Тривалість (Короткі \u2192 Довгі) + Тривалість (Довгі \u2192 Короткі) diff --git a/core/src/main/res/values-zh-rCN/strings.xml b/core/src/main/res/values-zh-rCN/strings.xml index 594249a31..332c8ed4c 100644 --- a/core/src/main/res/values-zh-rCN/strings.xml +++ b/core/src/main/res/values-zh-rCN/strings.xml @@ -72,7 +72,6 @@ 查看信息 删除播客 分享网站链接 - 分享订阅链接 确认要删除这些订阅吗? 该订阅所有已经下载的曲目将一并删除. 删除订阅 刷新全部订阅 @@ -199,8 +198,6 @@ 自动删除 播放 网络 - 更新周期 - 设置订阅自动刷新周期 仅在 WIFI 情况下载媒体文件 连续播放 仅在 WIFI 情况下载 @@ -292,9 +289,6 @@ 休眠计时器 计时剩余:\u0020 无效的输入, 时间是一个整数 - - 分钟 - 小时 目录 头条播客 @@ -363,6 +357,7 @@ 验证 给本播客及曲目变更用户名及密码 + 正在从选定的应用中导入订阅... 搜索 iTunes -- cgit v1.2.3 From cf1259e0b312494dc328e45fd7074817337635dd Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 15 Aug 2015 15:18:49 +0200 Subject: Display line breaks in shownotes correctly --- .../main/java/de/danoeh/antennapod/core/util/playback/Timeline.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java index f31297b41..77cf72ba8 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java @@ -87,6 +87,9 @@ public class Timeline { return ""; } + // ASCII line breaks to HTML line breaks + shownotes = shownotes.replace("\n", "
"); + Document document = Jsoup.parse(shownotes); // apply style @@ -100,7 +103,7 @@ public class Timeline { if (BuildConfig.DEBUG) Log.d(TAG, "Recognized " + elementsWithTimeCodes.size() + " timecodes"); for (Element element : elementsWithTimeCodes) { - Matcher matcherLong = TIMECODE_REGEX.matcher(element.text()); + Matcher matcherLong = TIMECODE_REGEX.matcher(element.html()); StringBuffer buffer = new StringBuffer(); while (matcherLong.find()) { String h = matcherLong.group(1); -- cgit v1.2.3 From f8b70081822a3f85542c7b38f9d885571fecca75 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 15 Aug 2015 19:27:47 +0200 Subject: Only replace ASCII line breaks if shownotes don't already contain HTML ones --- .../de/danoeh/antennapod/core/util/playback/Timeline.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java index 77cf72ba8..0de9863e7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java @@ -14,7 +14,6 @@ import org.jsoup.select.Elements; import java.util.regex.Matcher; import java.util.regex.Pattern; -import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.util.Converter; import de.danoeh.antennapod.core.util.ShownotesProvider; @@ -59,6 +58,8 @@ public class Timeline { private static final Pattern TIMECODE_LINK_REGEX = Pattern.compile("antennapod://timecode/((\\d+))"); private static final String TIMECODE_LINK = "%s"; private static final Pattern TIMECODE_REGEX = Pattern.compile("\\b(?:(?:(([0-9][0-9])):))?(([0-9][0-9])):(([0-9][0-9]))\\b"); + private static final Pattern LINE_BREAK_REGEX = Pattern.compile("
"); + /** * Applies an app-specific CSS stylesheet and adds timecode links (optional). @@ -82,13 +83,14 @@ public class Timeline { return null; } if (shownotes == null) { - if (BuildConfig.DEBUG) - Log.d(TAG, "shownotesProvider contained no shownotes. Returning empty string"); + Log.d(TAG, "shownotesProvider contained no shownotes. Returning empty string"); return ""; } - // ASCII line breaks to HTML line breaks - shownotes = shownotes.replace("\n", "
"); + // replace ASCII line breaks with HTML ones if shownotes don't contain HTML line breaks already + if(!LINE_BREAK_REGEX.matcher(shownotes).find()) { + shownotes = shownotes.replace("\n", "
"); + } Document document = Jsoup.parse(shownotes); @@ -100,8 +102,7 @@ public class Timeline { // apply timecode links if (addTimecodes) { Elements elementsWithTimeCodes = document.body().getElementsMatchingOwnText(TIMECODE_REGEX); - if (BuildConfig.DEBUG) - Log.d(TAG, "Recognized " + elementsWithTimeCodes.size() + " timecodes"); + Log.d(TAG, "Recognized " + elementsWithTimeCodes.size() + " timecodes"); for (Element element : elementsWithTimeCodes) { Matcher matcherLong = TIMECODE_REGEX.matcher(element.html()); StringBuffer buffer = new StringBuffer(); -- cgit v1.2.3 From 04bfcacb12425c7ea2196ae9290bc4afdd74003b Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 16 Aug 2015 00:04:03 +0200 Subject: Disable feed media file size service --- .../core/service/FeedMediaSizeService.java | 100 +++++++++------------ .../de/danoeh/antennapod/core/storage/DBTasks.java | 2 +- 2 files changed, 45 insertions(+), 57 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java index 2f6e67a28..a8375bce3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java @@ -4,19 +4,6 @@ import android.app.IntentService; import android.content.Intent; import android.util.Log; -import java.io.File; -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.List; - -import de.danoeh.antennapod.core.event.FeedMediaEvent; -import de.danoeh.antennapod.core.feed.FeedMedia; -import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.storage.DBWriter; -import de.danoeh.antennapod.core.util.NetworkUtils; -import de.greenrobot.event.EventBus; - public class FeedMediaSizeService extends IntentService { private final static String TAG = "FeedMediaSizeService"; @@ -28,49 +15,50 @@ public class FeedMediaSizeService extends IntentService { @Override protected void onHandleIntent(Intent intent) { Log.d(TAG, "onHandleIntent()"); - if(false == NetworkUtils.isDownloadAllowed()) { - return; - } - List list = DBReader.getFeedMediaUnknownSize(this); - for (FeedMedia media : list) { - Log.d(TAG, "Getting size currently " + media.getSize() + " for " + media.getDownload_url()); - if(false == NetworkUtils.isDownloadAllowed()) { - return; - } - long size = Integer.MIN_VALUE; - if (media.isDownloaded()) { - File mediaFile = new File(media.getLocalMediaUrl()); - if(mediaFile.exists()) { - size = mediaFile.length(); - } - } else if (false == media.checkedOnSizeButUnknown()) { - // only query the network if we haven't already checked - HttpURLConnection conn = null; - try { - URL url = new URL(media.getDownload_url()); - conn = (HttpURLConnection) url.openConnection(); - conn.setRequestProperty("Accept-Encoding", ""); - conn.setRequestMethod("HEAD"); - size = conn.getContentLength(); - } catch (IOException e) { - Log.d(TAG, media.getDownload_url()); - e.printStackTrace(); - } finally { - if (conn != null) { - conn.disconnect(); - } - } - } - if (size <= 0) { - // they didn't tell us the size, but we don't want to keep querying on it - media.setCheckedOnSizeButUnknown(); - } else { - media.setSize(size); - } - Log.d(TAG, "Size now: " + media.getSize()); - DBWriter.setFeedMedia(this, media); - EventBus.getDefault().post(FeedMediaEvent.update(media)); - } + return; +// if(false == NetworkUtils.isDownloadAllowed()) { +// return; +// } +// List list = DBReader.getFeedMediaUnknownSize(this); +// for (FeedMedia media : list) { +// Log.d(TAG, "Getting size currently " + media.getSize() + " for " + media.getDownload_url()); +// if(false == NetworkUtils.isDownloadAllowed()) { +// return; +// } +// long size = Integer.MIN_VALUE; +// if (media.isDownloaded()) { +// File mediaFile = new File(media.getLocalMediaUrl()); +// if(mediaFile.exists()) { +// size = mediaFile.length(); +// } +// } else if (false == media.checkedOnSizeButUnknown()) { +// // only query the network if we haven't already checked +// HttpURLConnection conn = null; +// try { +// URL url = new URL(media.getDownload_url()); +// conn = (HttpURLConnection) url.openConnection(); +// conn.setRequestProperty("Accept-Encoding", ""); +// conn.setRequestMethod("HEAD"); +// size = conn.getContentLength(); +// } catch (IOException e) { +// Log.d(TAG, media.getDownload_url()); +// e.printStackTrace(); +// } finally { +// if (conn != null) { +// conn.disconnect(); +// } +// } +// } +// if (size <= 0) { +// // they didn't tell us the size, but we don't want to keep querying on it +// media.setCheckedOnSizeButUnknown(); +// } else { +// media.setSize(size); +// } +// Log.d(TAG, "Size now: " + media.getSize()); +// DBWriter.setFeedMedia(this, media); +// EventBus.getDefault().post(FeedMediaEvent.update(media)); +// } } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index 770c4f7d7..6ced03c0e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -578,7 +578,7 @@ public final class DBTasks { EventDistributor.getInstance().sendFeedUpdateBroadcast(); - context.startService(new Intent(context, FeedMediaSizeService.class)); + // context.startService(new Intent(context, FeedMediaSizeService.class)); return resultFeeds; } -- cgit v1.2.3 From bf93cf3259d1464d9c9d99b32b362676845c7700 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 16 Aug 2015 19:15:45 -0400 Subject: not every action has a timestamp. fixes AntennaPod/AntennaPod#1102 --- .../java/de/danoeh/antennapod/core/service/GpodnetSyncService.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java index b80b4303f..7878d19a0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java @@ -230,7 +230,7 @@ public class GpodnetSyncService extends Service { for(GpodnetEpisodeAction action : localActions) { Pair key = new Pair(action.getPodcast(), action.getEpisode()); GpodnetEpisodeAction mostRecent = localMostRecentPlayAction.get(key); - if (mostRecent == null) { + if (mostRecent == null || mostRecent.getTimestamp() == null) { localMostRecentPlayAction.put(key, action); } else if (mostRecent.getTimestamp().before(action.getTimestamp())) { localMostRecentPlayAction.put(key, action); @@ -255,9 +255,10 @@ public class GpodnetSyncService extends Service { Pair key = new Pair(action.getPodcast(), action.getEpisode()); GpodnetEpisodeAction localMostRecent = localMostRecentPlayAction.get(key); if(localMostRecent == null || + localMostRecent.getTimestamp() == null || localMostRecent.getTimestamp().before(action.getTimestamp())) { GpodnetEpisodeAction mostRecent = mostRecentPlayAction.get(key); - if (mostRecent == null) { + if (mostRecent == null || mostRecent.getTimestamp() == null) { mostRecentPlayAction.put(key, action); } else if (mostRecent.getTimestamp().before(action.getTimestamp())) { mostRecentPlayAction.put(key, action); -- cgit v1.2.3 From f9130671c0a3732aa8a06decbbb3f1dc33564365 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Mon, 17 Aug 2015 21:08:37 +0200 Subject: Read feed counter setting correctly --- .../de/danoeh/antennapod/core/preferences/UserPreferences.java | 6 +++--- .../main/java/de/danoeh/antennapod/core/storage/DBReader.java | 2 +- .../java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'core/src/main') 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 d56829c70..08328536d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -44,7 +44,7 @@ public class UserPreferences { public static final String PREF_THEME = "prefTheme"; public static final String PREF_HIDDEN_DRAWER_ITEMS = "prefHiddenDrawerItems"; public static final String PREF_DRAWER_FEED_ORDER = "prefDrawerFeedOrder"; - public static final String PREF_DRAWER_FEED_COUNTER = "prefDrawerFeedCounter"; + public static final String PREF_DRAWER_FEED_COUNTER = "prefDrawerFeedIndicator"; public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify"; public static final String PREF_PERSISTENT_NOTIFICATION = "prefPersistNotify"; public static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport"; @@ -90,7 +90,7 @@ public class UserPreferences { // Constants private static int EPISODE_CACHE_SIZE_UNLIMITED = -1; - public static int FEED_ORDER_UNPLAYED_EPISODES = 0; + public static int FEED_ORDER_COUNTER = 0; public static int FEED_ORDER_ALPHABETICAL = 1; public static int FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM = 0; public static int FEED_COUNTER_SHOW_NEW = 1; @@ -144,7 +144,7 @@ public class UserPreferences { return Integer.valueOf(value); } - public static int getFeedCounter() { + public static int getFeedCounterSetting() { String value = prefs.getString(PREF_DRAWER_FEED_COUNTER, "0"); return Integer.valueOf(value); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 5ed0a6ee3..2ae88cc02 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -1141,7 +1141,7 @@ public final class DBReader { Comparator comparator; int feedOrder = UserPreferences.getFeedOrder(); - if(feedOrder == UserPreferences.FEED_ORDER_UNPLAYED_EPISODES) { + if(feedOrder == UserPreferences.FEED_ORDER_COUNTER) { comparator = new Comparator() { @Override public int compare(Feed lhs, Feed rhs) { 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 edb7598ab..3bfcaa539 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 @@ -1301,16 +1301,16 @@ public class PodDBAdapter { } public final LongIntMap getFeedCounters(long... feedIds) { - int counter = UserPreferences.getFeedCounter(); + int setting = UserPreferences.getFeedCounterSetting(); String whereRead; - if(counter == UserPreferences.FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM) { + if(setting == UserPreferences.FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM) { whereRead = "(" + KEY_READ + "=" + FeedItem.NEW + " OR " + KEY_READ + "=" + FeedItem.UNPLAYED + ")"; - } else if(counter == UserPreferences.FEED_COUNTER_SHOW_NEW) { + } else if(setting == UserPreferences.FEED_COUNTER_SHOW_NEW) { whereRead = KEY_READ + "=" + FeedItem.NEW; - } else if(counter == UserPreferences.FEED_COUNTER_SHOW_UNPLAYED) { + } else if(setting == UserPreferences.FEED_COUNTER_SHOW_UNPLAYED) { whereRead = KEY_READ + "=" + FeedItem.UNPLAYED; - } else { + } else { // NONE return new LongIntMap(0); } -- cgit v1.2.3 From 3abce4c597bc74b95d9cbdb88e2bf3671047c811 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Tue, 18 Aug 2015 17:38:51 +0200 Subject: Load feed media size on demand --- core/src/main/AndroidManifest.xml | 3 - .../core/service/FeedMediaSizeService.java | 64 -------------------- .../danoeh/antennapod/core/storage/DBReader.java | 23 -------- .../de/danoeh/antennapod/core/storage/DBTasks.java | 8 --- .../antennapod/core/storage/PodDBAdapter.java | 7 --- .../danoeh/antennapod/core/util/NetworkUtils.java | 68 ++++++++++++++++++++++ 6 files changed, 68 insertions(+), 105 deletions(-) delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/service/FeedMediaSizeService.java (limited to 'core/src/main') diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index 17dcb4ad8..3ec519844 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -23,9 +23,6 @@ - list = DBReader.getFeedMediaUnknownSize(this); -// for (FeedMedia media : list) { -// Log.d(TAG, "Getting size currently " + media.getSize() + " for " + media.getDownload_url()); -// if(false == NetworkUtils.isDownloadAllowed()) { -// return; -// } -// long size = Integer.MIN_VALUE; -// if (media.isDownloaded()) { -// File mediaFile = new File(media.getLocalMediaUrl()); -// if(mediaFile.exists()) { -// size = mediaFile.length(); -// } -// } else if (false == media.checkedOnSizeButUnknown()) { -// // only query the network if we haven't already checked -// HttpURLConnection conn = null; -// try { -// URL url = new URL(media.getDownload_url()); -// conn = (HttpURLConnection) url.openConnection(); -// conn.setRequestProperty("Accept-Encoding", ""); -// conn.setRequestMethod("HEAD"); -// size = conn.getContentLength(); -// } catch (IOException e) { -// Log.d(TAG, media.getDownload_url()); -// e.printStackTrace(); -// } finally { -// if (conn != null) { -// conn.disconnect(); -// } -// } -// } -// if (size <= 0) { -// // they didn't tell us the size, but we don't want to keep querying on it -// media.setCheckedOnSizeButUnknown(); -// } else { -// media.setSize(size); -// } -// Log.d(TAG, "Size now: " + media.getSize()); -// DBWriter.setFeedMedia(this, media); -// EventBus.getDefault().post(FeedMediaEvent.update(media)); -// } - } - -} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 5ed0a6ee3..86e788c7a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -521,29 +521,6 @@ public final class DBReader { return itemIds; } - /** - * Loads FeedMedia whose file size is unknown - * - * @param context A context that is used for opening a database connection. - * @return A list of FeedMedia items whose size is 0 (unknown and never tried to - * determine the correct size) - */ - public static List getFeedMediaUnknownSize(Context context) { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - Cursor cursor = adapter.getFeedMediaUnknownSizeCursor(); - List result = new ArrayList<>(cursor.getCount()); - if (cursor.moveToFirst()) { - do { - FeedMedia media = extractFeedMediaFromCursorRow(cursor); - result.add(media); - } while (cursor.moveToNext()); - } - cursor.close(); - return result; - } - - /** * Loads a list of FeedItems sorted by pubDate in descending order. * diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index 6ced03c0e..5a3822a81 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -5,9 +5,6 @@ import android.content.Intent; import android.database.Cursor; import android.util.Log; -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -28,11 +25,8 @@ import de.danoeh.antennapod.core.asynctask.FlattrClickWorker; import de.danoeh.antennapod.core.asynctask.FlattrStatusFetcher; import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; -import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.service.FeedMediaSizeService; import de.danoeh.antennapod.core.service.GpodnetSyncService; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.service.playback.PlaybackService; @@ -578,8 +572,6 @@ public final class DBTasks { EventDistributor.getInstance().sendFeedUpdateBroadcast(); - // context.startService(new Intent(context, FeedMediaSizeService.class)); - return resultFeeds; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index edb7598ab..c14365911 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 @@ -1110,13 +1110,6 @@ public class PodDBAdapter { return db.rawQuery(query, null); } - public final Cursor getFeedMediaUnknownSizeCursor() { - final String query = "SELECT * " - + " FROM " + TABLE_NAME_FEED_MEDIA - + " WHERE " + KEY_SIZE + "<= 0"; - return db.rawQuery(query, null); - } - /** * Returns a cursor which contains all items of a feed that are considered new. * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection. 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 9296039f0..1b57baa11 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 @@ -7,10 +7,23 @@ import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.util.Log; +import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Request; +import com.squareup.okhttp.Response; + +import java.io.File; +import java.io.IOException; import java.util.Arrays; import java.util.List; +import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; +import de.danoeh.antennapod.core.storage.DBWriter; +import rx.Observable; +import rx.Subscriber; +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; public class NetworkUtils { @@ -78,4 +91,59 @@ public class NetworkUtils { return mWifi.isConnected(); } + public static Observable getFeedMediaSizeObservable(FeedMedia media) { + return Observable.create(new Observable.OnSubscribe() { + @Override + public void call(Subscriber subscriber) { + if (false == NetworkUtils.isDownloadAllowed()) { + subscriber.onNext(0L); + subscriber.onCompleted(); + return; + } + long size = Integer.MIN_VALUE; + if (media.isDownloaded()) { + File mediaFile = new File(media.getLocalMediaUrl()); + if (mediaFile.exists()) { + size = mediaFile.length(); + } + } else if (false == media.checkedOnSizeButUnknown()) { + // only query the network if we haven't already checked + OkHttpClient client = AntennapodHttpClient.getHttpClient(); + Request.Builder httpReq = new Request.Builder() + .url(media.getDownload_url()) + .header("Accept-Encoding", "identity") + .head(); + try { + Response response = client.newCall(httpReq.build()).execute(); + if (response.isSuccessful()) { + String contentLength = response.header("Content-Length"); + try { + size = Integer.parseInt(contentLength); + } catch (NumberFormatException e) { + Log.e(TAG, Log.getStackTraceString(e)); + } + } + } catch (IOException e) { + subscriber.onNext(0L); + subscriber.onCompleted(); + Log.e(TAG, Log.getStackTraceString(e)); + return; // better luck next time + } + } + Log.d(TAG, "new size: " + size); + if (size <= 0) { + // they didn't tell us the size, but we don't want to keep querying on it + media.setCheckedOnSizeButUnknown(); + } else { + media.setSize(size); + } + subscriber.onNext(size); + subscriber.onCompleted(); + DBWriter.setFeedMedia(context, media); + } + }) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()); + } + } -- cgit v1.2.3 From 3321e8db4f51834eb9bd7de54f081fe4c14d1fca Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 16 Aug 2015 17:37:43 +0200 Subject: Custom SSL Socket Factory for Android 4.1+ (but below 5) --- .../service/download/AntennapodHttpClient.java | 80 ++++++++++++++++++++++ 1 file changed, 80 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java index ec3d3e2fe..402a7a8bd 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java @@ -1,13 +1,22 @@ package de.danoeh.antennapod.core.service.download; +import android.os.Build; import android.util.Log; import com.squareup.okhttp.OkHttpClient; +import java.io.IOException; import java.net.CookieManager; import java.net.CookiePolicy; +import java.net.InetAddress; +import java.net.Socket; +import java.security.GeneralSecurityException; import java.util.concurrent.TimeUnit; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; + import de.danoeh.antennapod.core.BuildConfig; /** @@ -50,6 +59,10 @@ public class AntennapodHttpClient { client.setFollowRedirects(true); client.setFollowSslRedirects(true); + if(16 <= Build.VERSION.SDK_INT && Build.VERSION.SDK_INT < 21) { + client.setSslSocketFactory(new CustomSslSocketFactory()); + } + httpClient = client; } return httpClient; @@ -64,4 +77,71 @@ public class AntennapodHttpClient { // does nothing at the moment } } + + private static class CustomSslSocketFactory extends SSLSocketFactory { + + private SSLSocketFactory factory; + + public CustomSslSocketFactory() { + try { + SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); + sslContext.init(null, null, null); + factory= sslContext.getSocketFactory(); + } catch(GeneralSecurityException e) { + e.printStackTrace(); + } + } + + @Override + public String[] getDefaultCipherSuites() { + return factory.getDefaultCipherSuites(); + } + + @Override + public String[] getSupportedCipherSuites() { + return factory.getSupportedCipherSuites(); + } + + public Socket createSocket() throws IOException { + SSLSocket result = (SSLSocket) factory.createSocket(); + configureSocket(result); + return result; + } + + public Socket createSocket(String var1, int var2) throws IOException { + SSLSocket result = (SSLSocket) factory.createSocket(var1, var2); + configureSocket(result); + return result; + } + + public Socket createSocket(Socket var1, String var2, int var3, boolean var4) throws IOException { + SSLSocket result = (SSLSocket) factory.createSocket(var1, var2, var3, var4); + configureSocket(result); + return result; + } + + public Socket createSocket(InetAddress var1, int var2) throws IOException { + SSLSocket result = (SSLSocket) factory.createSocket(var1, var2); + configureSocket(result); + return result; + } + + public Socket createSocket(String var1, int var2, InetAddress var3, int var4) throws IOException { + SSLSocket result = (SSLSocket) factory.createSocket(var1, var2, var3, var4); + configureSocket(result); + return result; + } + + public Socket createSocket(InetAddress var1, int var2, InetAddress var3, int var4) throws IOException { + SSLSocket result = (SSLSocket) factory.createSocket(var1, var2, var3, var4); + configureSocket(result); + return result; + } + + private void configureSocket(SSLSocket s) { + s.setEnabledProtocols(new String[] { "TLSv1.2", "TLSv1.1" } ); + } + + } + } -- cgit v1.2.3 From 1e1b5ff99b0d0ffb8c5948ba96d01e410905177c Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Wed, 19 Aug 2015 21:03:31 -0400 Subject: Can now download things while on mobile. The glide url loader now uses its own OkHttpClient. The result is that we can now search for podcasts and download them while on mobile even if the user doesn't allow mobile downloads (NOTE that we don't do anything they haven't asked us to do while on mobile). fixes AntennaPod/AntennaPod#1101 --- .../antennapod/core/glide/ApOkHttpUrlLoader.java | 2 +- .../service/download/AntennapodHttpClient.java | 46 ++++++++++++++-------- 2 files changed, 30 insertions(+), 18 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java index c7ac146b5..cf3af7d4c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java @@ -43,7 +43,7 @@ public class ApOkHttpUrlLoader implements ModelLoader { if (internalClient == null) { synchronized (Factory.class) { if (internalClient == null) { - internalClient = AntennapodHttpClient.getHttpClient(); + internalClient = AntennapodHttpClient.newHttpClient(); internalClient.interceptors().add(new NetworkAllowanceInterceptor()); internalClient.interceptors().add(new BasicAuthenticationInterceptor()); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java index ec3d3e2fe..012678cd0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/AntennapodHttpClient.java @@ -1,5 +1,6 @@ package de.danoeh.antennapod.core.service.download; +import android.support.annotation.NonNull; import android.util.Log; import com.squareup.okhttp.OkHttpClient; @@ -30,29 +31,40 @@ public class AntennapodHttpClient { public static synchronized OkHttpClient getHttpClient() { if (httpClient == null) { - if (BuildConfig.DEBUG) Log.d(TAG, "Creating new instance of HTTP client"); + httpClient = newHttpClient(); + } + return httpClient; + } - System.setProperty("http.maxConnections", String.valueOf(MAX_CONNECTIONS)); + /** + * Creates a new HTTP client. Most users should just use + * getHttpClient() to get the standard AntennaPod client, + * but sometimes it's necessary for others to have their own + * copy so that the clients don't share state. + * @return http client + */ + @NonNull + public static OkHttpClient newHttpClient() { + Log.d(TAG, "Creating new instance of HTTP client"); - OkHttpClient client = new OkHttpClient(); + System.setProperty("http.maxConnections", String.valueOf(MAX_CONNECTIONS)); - // set cookie handler - CookieManager cm = new CookieManager(); - cm.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER); - client.setCookieHandler(cm); + OkHttpClient client = new OkHttpClient(); - // set timeouts - client.setConnectTimeout(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); - client.setReadTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS); - client.setWriteTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS); + // set cookie handler + CookieManager cm = new CookieManager(); + cm.setCookiePolicy(CookiePolicy.ACCEPT_ORIGINAL_SERVER); + client.setCookieHandler(cm); - // configure redirects - client.setFollowRedirects(true); - client.setFollowSslRedirects(true); + // set timeouts + client.setConnectTimeout(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); + client.setReadTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS); + client.setWriteTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS); - httpClient = client; - } - return httpClient; + // configure redirects + client.setFollowRedirects(true); + client.setFollowSslRedirects(true); + return client; } /** -- cgit v1.2.3 From b76675048e378e64699cc3e0b656ec4c964971e5 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 23 Aug 2015 00:04:05 +0200 Subject: POST empty string --- .../antennapod/core/gpoddernet/GpodnetService.java | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java index 1a40120e2..d8e07085d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/gpoddernet/GpodnetService.java @@ -1,8 +1,5 @@ package de.danoeh.antennapod.core.gpoddernet; -import android.os.Build; -import android.util.Log; - import com.squareup.okhttp.Credentials; import com.squareup.okhttp.MediaType; import com.squareup.okhttp.OkHttpClient; @@ -25,23 +22,10 @@ import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; -import java.security.KeyStore; -import java.security.Principal; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; import java.util.LinkedList; import java.util.List; -import java.util.Map; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; -import javax.security.auth.x500.X500Principal; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.gpoddernet.model.GpodnetDevice; @@ -562,7 +546,8 @@ public class GpodnetService { e.printStackTrace(); throw new GpodnetServiceException(e); } - Request.Builder request = new Request.Builder().url(url).post(null); + RequestBody body = RequestBody.create(TEXT, ""); + Request.Builder request = new Request.Builder().url(url).post(body); executeRequestWithAuthentication(request, username, password); } -- cgit v1.2.3 From 93273748b18689160c5d0e4cc3e34ba851f06dac Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 25 Aug 2015 20:03:58 -0400 Subject: Remove selective downloading of new things and just let auto-download do it's thing. refs AntennaPod/AntennaPod#1009 --- .../antennapod/core/service/download/DownloadService.java | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'core/src/main') 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 4fdaf6843..77772f8e0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadService.java @@ -325,16 +325,8 @@ public class DownloadService extends Service { cancelNotificationUpdater(); unregisterReceiver(cancelDownloadReceiver); - // TODO: I'm not sure this is actually needed. - // We could just invoke the autodownloadUndownloadeditems method - // and it would get everything it's supposed to. By sending it the - // items in newMediaFiles we're overriding the download algorithm, - // which is not something we should probably do. - if (!newMediaFiles.isEmpty()) { - Log.d(TAG, "newMediaFiles exist, autodownload them"); - DBTasks.autodownloadUndownloadedItems(getApplicationContext(), - ArrayUtils.toPrimitive(newMediaFiles.toArray(new Long[newMediaFiles.size()]))); - } + // start auto download in case anything new has shown up + DBTasks.autodownloadUndownloadedItems(getApplicationContext()); } @SuppressLint("NewApi") -- cgit v1.2.3 From 38db1636101d3e9dd8c849867b358c1dc274e917 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Wed, 26 Aug 2015 17:40:29 -0400 Subject: removed unused queuing of new media files. --- .../core/service/download/DownloadService.java | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) (limited to 'core/src/main') 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 77772f8e0..04ba77cda 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 @@ -113,11 +113,6 @@ public class DownloadService extends Service { */ public static final String EXTRA_REQUEST = "request"; - /** - * Stores new media files that will be queued for auto-download if possible. - */ - private List newMediaFiles; - /** * Contains all completed downloads that have not been included in the report yet. */ @@ -171,7 +166,7 @@ public class DownloadService extends Service { } private Thread downloadCompletionThread = new Thread() { - private static final String TAG = "downloadCompletionThread"; + private static final String TAG = "downloadCompletionThd"; @Override public void run() { @@ -241,7 +236,6 @@ public class DownloadService extends Service { Log.d(TAG, "Service started"); isRunning = true; handler = new Handler(); - newMediaFiles = Collections.synchronizedList(new ArrayList()); reportQueue = Collections.synchronizedList(new ArrayList()); downloads = Collections.synchronizedList(new ArrayList()); numberOfDownloads = new AtomicInteger(0); @@ -775,16 +769,6 @@ public class DownloadService extends Service { for (int i = 0; i < savedFeeds.length; i++) { Feed savedFeed = savedFeeds[i]; - // queue new media files for automatic download - for (FeedItem item : savedFeed.getItems()) { - if(item.getPubDate() == null) { - Log.d(TAG, item.toString()); - } - if (item.isNew() && item.hasMedia() && !item.getMedia().isDownloaded()) { - newMediaFiles.add(item.getMedia().getId()); - } - } - // If loadAllPages=true, check if another page is available and queue it for download final boolean loadAllPages = results.get(i).first.getArguments().getBoolean(DownloadRequester.REQUEST_ARG_LOAD_ALL_PAGES); final Feed feed = results.get(i).second.feed; -- cgit v1.2.3 From 30d06f62d928304bc81b1040e2e39760edea8904 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 28 Aug 2015 23:07:20 +0200 Subject: Localize option label --- core/src/main/res/values/strings.xml | 1 + 1 file changed, 1 insertion(+) (limited to 'core/src/main') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 00bc077e8..c8fb83e46 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -358,6 +358,7 @@ OPML files allow you to move your podcasts from one podcatcher to another. + Option %1$d Choose a specific file path from the local filesystem. Use an external applications like Dropbox, Google Drive or your favourite file manager to open an OPML file. Many applications like Google Mail, Dropbox, Google Drive and most file managers can open OPML files with AntennaPod. Start import -- cgit v1.2.3 From 55cc2a0d2dc384b3f42a3d7fe4384d078bc3b877 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 28 Aug 2015 23:05:58 +0200 Subject: Resume playback when bluetooth device is reconnected --- core/src/main/AndroidManifest.xml | 1 + .../antennapod/core/service/playback/PlaybackService.java | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index 3ec519844..f5b000abf 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -7,6 +7,7 @@ + Date: Mon, 31 Aug 2015 08:39:03 +0200 Subject: Update strings.xml Update auto_download_apply_to_items_title #1155 --- core/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index c8fb83e46..1cba2bb02 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -77,7 +77,7 @@ Close Retry Include in auto downloads - Apply to Previous Episodes + Apply to Existing Episodes The new Auto Download setting will automatically be applied to new episodes.\nDo you also want to apply it to previous episodes? Auto Delete Episode\n(override global default) \u0020parallel downloads -- cgit v1.2.3 From ff7b5de14450522c33957d5dcda5e46b075c2c99 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Mon, 31 Aug 2015 10:58:43 +0200 Subject: Remove needless leading and trailing spaces in feed or episode title --- .../de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java index 31eb2efd6..25a57f71b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java @@ -119,13 +119,14 @@ public class NSRSS20 extends Namespace { state.getCurrentItem().setItemIdentifier(content); } } else if (top.equals(TITLE)) { + String title = content.trim(); if (second.equals(ITEM)) { - state.getCurrentItem().setTitle(content); + state.getCurrentItem().setTitle(title); } else if (second.equals(CHANNEL)) { - state.getFeed().setTitle(content); + state.getFeed().setTitle(title); } else if (second.equals(IMAGE) && third != null && third.equals(CHANNEL)) { - state.getFeed().getImage().setTitle(content); + state.getFeed().getImage().setTitle(title); } } else if (top.equals(LINK)) { if (second.equals(CHANNEL)) { -- cgit v1.2.3 From dbf243267ec4fa37b0d67693856a7369356c548a Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Tue, 1 Sep 2015 23:47:39 +0200 Subject: Check that URL is not null or empty --- .../java/de/danoeh/antennapod/core/util/NetworkUtils.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'core/src/main') 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 1b57baa11..f6486163c 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 @@ -5,6 +5,7 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; +import android.text.TextUtils; import android.util.Log; import com.squareup.okhttp.OkHttpClient; @@ -108,9 +109,17 @@ public class NetworkUtils { } } else if (false == media.checkedOnSizeButUnknown()) { // only query the network if we haven't already checked + + String url = media.getDownload_url(); + if(TextUtils.isEmpty(url)) { + subscriber.onNext(0L); + subscriber.onCompleted(); + return; + } + OkHttpClient client = AntennapodHttpClient.getHttpClient(); Request.Builder httpReq = new Request.Builder() - .url(media.getDownload_url()) + .url(url) .header("Accept-Encoding", "identity") .head(); try { -- cgit v1.2.3 From a2e61bee111e509073b7b755b7e5733eee3da2ee Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Thu, 3 Sep 2015 17:41:19 -0400 Subject: Compiling with api 22 with thanks to @mfietz https://github.com/mfietz/AntennaPod/commit/4ccefe5e84363e25089f93d486d8dc52caea1d27 --- .../playback/MediaButtonIntentReceiver.java | 27 ++++++ .../core/service/playback/PlaybackService.java | 75 --------------- .../playback/PlaybackServiceMediaPlayer.java | 101 +++++++++++++++++---- 3 files changed, 112 insertions(+), 91 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/service/playback/MediaButtonIntentReceiver.java (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/MediaButtonIntentReceiver.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/MediaButtonIntentReceiver.java new file mode 100644 index 000000000..3e401b5ea --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/MediaButtonIntentReceiver.java @@ -0,0 +1,27 @@ +package de.danoeh.antennapod.core.service.playback; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.util.Log; +import android.view.KeyEvent; + +public class MediaButtonIntentReceiver extends BroadcastReceiver { + + private static final String TAG = "MediaButtonIntentReceiver"; + + private static PlaybackServiceMediaPlayer mMediaPlayer; + + public static void setMediaPlayer(PlaybackServiceMediaPlayer mediaPlayer) { + mMediaPlayer = mediaPlayer; + } + + @Override + public void onReceive(Context context, Intent intent) { + Log.d(TAG, "onReceive(Context, " + intent.toString() +")"); + if (mMediaPlayer != null && Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) { + mMediaPlayer.handleMediaKey((KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT)); + } + } + +} \ No newline at end of file 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 f6ea38ab5..507b0b43c 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 @@ -241,7 +241,6 @@ public class PlaybackService extends Service { ACTION_PAUSE_PLAY_CURRENT_EPISODE)); registerReceiver(pauseResumeCurrentEpisodeReceiver, new IntentFilter( ACTION_RESUME_PLAY_CURRENT_EPISODE)); - remoteControlClient = setupRemoteControlClient(); taskManager = new PlaybackServiceTaskManager(this, taskManagerCallback); mediaPlayer = new PlaybackServiceMediaPlayer(this, mediaPlayerCallback); @@ -493,7 +492,6 @@ public class PlaybackService extends Service { // statusUpdate.putExtra(EXTRA_NEW_PLAYER_STATUS, newInfo.playerStatus.ordinal()); sendBroadcast(statusUpdate); updateWidget(); - refreshRemoteControlClientState(newInfo); bluetoothNotifyChange(newInfo, AVRCP_ACTION_PLAYER_STATUS_CHANGED); bluetoothNotifyChange(newInfo, AVRCP_ACTION_META_CHANGED); } @@ -546,11 +544,6 @@ public class PlaybackService extends Service { PlaybackService.this.endPlayback(true); return true; } - - @Override - public RemoteControlClient getRemoteControlClient() { - return remoteControlClient; - } }; private void endPlayback(boolean playNextEpisode) { @@ -960,74 +953,6 @@ public class PlaybackService extends Service { return taskManager.getSleepTimerTimeLeft(); } - @SuppressLint("NewApi") - private RemoteControlClient setupRemoteControlClient() { - if (Build.VERSION.SDK_INT < 14) { - return null; - } - - Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); - mediaButtonIntent.setComponent(new ComponentName(getPackageName(), - MediaButtonReceiver.class.getName())); - PendingIntent mediaPendingIntent = PendingIntent.getBroadcast( - getApplicationContext(), 0, mediaButtonIntent, 0); - remoteControlClient = new RemoteControlClient(mediaPendingIntent); - int controlFlags; - if (android.os.Build.VERSION.SDK_INT < 16) { - controlFlags = RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE - | RemoteControlClient.FLAG_KEY_MEDIA_NEXT; - } else { - controlFlags = RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE; - } - remoteControlClient.setTransportControlFlags(controlFlags); - return remoteControlClient; - } - - /** - * Refresh player status and metadata. - */ - @SuppressLint("NewApi") - private void refreshRemoteControlClientState(PlaybackServiceMediaPlayer.PSMPInfo info) { - if (android.os.Build.VERSION.SDK_INT >= 14) { - if (remoteControlClient != null) { - switch (info.playerStatus) { - case PLAYING: - remoteControlClient - .setPlaybackState(RemoteControlClient.PLAYSTATE_PLAYING); - break; - case PAUSED: - case INITIALIZED: - remoteControlClient - .setPlaybackState(RemoteControlClient.PLAYSTATE_PAUSED); - break; - case STOPPED: - remoteControlClient - .setPlaybackState(RemoteControlClient.PLAYSTATE_STOPPED); - break; - case ERROR: - remoteControlClient - .setPlaybackState(RemoteControlClient.PLAYSTATE_ERROR); - break; - default: - remoteControlClient - .setPlaybackState(RemoteControlClient.PLAYSTATE_BUFFERING); - } - if (info.playable != null) { - MetadataEditor editor = remoteControlClient - .editMetadata(false); - editor.putString(MediaMetadataRetriever.METADATA_KEY_TITLE, - info.playable.getEpisodeTitle()); - - editor.putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, - info.playable.getFeedTitle()); - - editor.apply(); - } - Log.d(TAG, "RemoteControlClient state was refreshed"); - } - } - } - private void bluetoothNotifyChange(PlaybackServiceMediaPlayer.PSMPInfo info, String whatChanged) { boolean isPlaying = false; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 835a8c1d1..b6bbae6fe 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -1,9 +1,10 @@ package de.danoeh.antennapod.core.service.playback; +import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; +import android.content.Intent; import android.media.AudioManager; -import android.media.RemoteControlClient; import android.net.wifi.WifiManager; import android.os.PowerManager; import android.support.v4.media.MediaMetadataCompat; @@ -12,6 +13,7 @@ import android.support.v4.media.session.PlaybackStateCompat; import android.telephony.TelephonyManager; import android.util.Log; import android.util.Pair; +import android.view.KeyEvent; import android.view.SurfaceHolder; import org.apache.commons.lang3.Validate; @@ -29,7 +31,6 @@ import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.receiver.MediaButtonReceiver; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.playback.AudioPlayer; import de.danoeh.antennapod.core.util.playback.IPlayer; @@ -98,9 +99,16 @@ public class PlaybackServiceMediaPlayer { } ); - mediaSession = new MediaSessionCompat(context, TAG); + MediaButtonIntentReceiver.setMediaPlayer(this); + ComponentName eventReceiver = new ComponentName(context.getPackageName(), MediaButtonIntentReceiver.class.getName()); + Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); + mediaButtonIntent.setComponent(eventReceiver); + PendingIntent buttonReceiverIntent = PendingIntent.getBroadcast(context, 0, mediaButtonIntent, 0); + + mediaSession = new MediaSessionCompat(context, TAG, eventReceiver, buttonReceiverIntent); mediaSession.setCallback(sessionCallback); - mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); + mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); + mediaSession.setActive(true); mediaPlayer = null; statusBeforeSeeking = null; @@ -249,7 +257,9 @@ public class PlaybackServiceMediaPlayer { private MediaMetadataCompat getMediaSessionMetadata(Playable p) { MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder(); + builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, p.getFeedTitle()); builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, p.getEpisodeTitle()); + builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, p.getEpisodeTitle()); builder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, p.getFeedTitle()); return builder.build(); } @@ -287,16 +297,6 @@ public class PlaybackServiceMediaPlayer { setPlayerStatus(PlayerStatus.PLAYING, media); pausedBecauseOfTransientAudiofocusLoss = false; - if (android.os.Build.VERSION.SDK_INT >= 14) { - RemoteControlClient remoteControlClient = callback.getRemoteControlClient(); - if (remoteControlClient != null) { - audioManager - .registerRemoteControlClient(remoteControlClient); - } - } - audioManager - .registerMediaButtonEventReceiver(new ComponentName(context.getPackageName(), - MediaButtonReceiver.class.getName())); media.onPlaybackStart(); } else { @@ -949,8 +949,6 @@ public class PlaybackServiceMediaPlayer { public boolean onMediaPlayerError(Object inObj, int what, int extra); public boolean endPlayback(boolean playNextEpisode); - - public RemoteControlClient getRemoteControlClient(); } private IPlayer setMediaPlayerListeners(IPlayer mp) { @@ -1128,5 +1126,76 @@ public class PlaybackServiceMediaPlayer { super.onSeekTo(pos); seekTo((int) pos); } + + @Override + public boolean onMediaButtonEvent(final Intent mediaButton) { + Log.d(TAG, "GOT MediaButton EVENT"); + if (mediaButton != null) { + KeyEvent keyEvent = (KeyEvent) mediaButton.getExtras().get(Intent.EXTRA_KEY_EVENT); + handleMediaKey(keyEvent); + } + return super.onMediaButtonEvent(mediaButton); + } }; + + public boolean handleMediaKey(KeyEvent event) { + if (event != null + && event.getAction() == KeyEvent.ACTION_DOWN + && event.getRepeatCount() == 0) { + switch (event.getKeyCode()) { + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + case KeyEvent.KEYCODE_HEADSETHOOK: + { + Log.d(TAG, "Received Play/Pause event from RemoteControlClient"); + if (playerStatus == PlayerStatus.PAUSED || playerStatus == PlayerStatus.PREPARED) { + resume(); + } else if (playerStatus == PlayerStatus.INITIALIZED) { + setStartWhenPrepared(true); + prepare(); + } else if (playerStatus == PlayerStatus.PLAYING) { + pause(false, true); + if (UserPreferences.isPersistNotify()) { + pause(false, true); + } else { + pause(true, true); + } + } + return true; + } + case KeyEvent.KEYCODE_MEDIA_PLAY: + { + Log.d(TAG, "Received Play event from RemoteControlClient"); + if (playerStatus == PlayerStatus.PAUSED || playerStatus == PlayerStatus.PREPARED) { + resume(); + } else if (playerStatus == PlayerStatus.INITIALIZED) { + setStartWhenPrepared(true); + prepare(); + } + return true; + } + case KeyEvent.KEYCODE_MEDIA_PAUSE: + { + Log.d(TAG, "Received Pause event from RemoteControlClient"); + if (playerStatus == PlayerStatus.PLAYING) { + pause(false, true); + } + if (UserPreferences.isPersistNotify()) { + pause(false, true); + } else { + pause(true, true); + } + return true; + } + case KeyEvent.KEYCODE_MEDIA_STOP: + { + Log.d(TAG, "Received Stop event from RemoteControlClient"); + stop(); + return true; + } + default: + break; + } + } + return false; + } } -- cgit v1.2.3 From 2292b82252c2d098fdd95a1f11541418e830f57f Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Fri, 4 Sep 2015 18:08:41 -0400 Subject: fix NPE when action has no timestamp --- .../java/de/danoeh/antennapod/core/service/GpodnetSyncService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java index 7878d19a0..915f5ee1b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java @@ -260,8 +260,10 @@ public class GpodnetSyncService extends Service { GpodnetEpisodeAction mostRecent = mostRecentPlayAction.get(key); if (mostRecent == null || mostRecent.getTimestamp() == null) { mostRecentPlayAction.put(key, action); - } else if (mostRecent.getTimestamp().before(action.getTimestamp())) { + } else if (action.getTimestamp() != null && mostRecent.getTimestamp().before(action.getTimestamp())) { mostRecentPlayAction.put(key, action); + } else { + Log.d(TAG, "No date information in action, skipping it"); } } break; -- cgit v1.2.3 From ff85fb93144cc2f4fba00611bf44d36c34266b03 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Fri, 4 Sep 2015 18:41:49 -0400 Subject: Revert "Update strings.xml" --- core/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 1cba2bb02..c8fb83e46 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -77,7 +77,7 @@ Close Retry Include in auto downloads - Apply to Existing Episodes + Apply to Previous Episodes The new Auto Download setting will automatically be applied to new episodes.\nDo you also want to apply it to previous episodes? Auto Delete Episode\n(override global default) \u0020parallel downloads -- cgit v1.2.3 From 946d5ef50c109549f2d15160c0345b0b8b2f4d84 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 9 Aug 2015 11:40:46 +0200 Subject: Add options to sleep timer dialog --- core/src/main/res/values/strings.xml | 3 +++ 1 file changed, 3 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index c8fb83e46..f5ba1b636 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -385,6 +385,9 @@ Sleep timer Time left:\u0020 Invalid input, time has to be an integer + When timer is about to expire: + Shake to reset timer + Vibrate seconds minutes hours -- cgit v1.2.3 From 771b1e2a16545cc6a8bca433be6089e93a649359 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 9 Aug 2015 11:42:43 +0200 Subject: Vibrate and lower volume when timer is about to expire, shake to reset timer --- core/src/main/AndroidManifest.xml | 1 + .../core/service/playback/PlaybackService.java | 16 ++- .../playback/PlaybackServiceMediaPlayer.java | 26 +++++ .../playback/PlaybackServiceTaskManager.java | 107 +++++++++++++-------- .../core/service/playback/ShakeListener.java | 63 ++++++++++++ .../core/util/playback/PlaybackController.java | 4 +- 6 files changed, 169 insertions(+), 48 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java (limited to 'core/src/main') diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index f5b000abf..47bd8b666 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -8,6 +8,7 @@ + 0, "Waiting time <= 0"); - if (BuildConfig.DEBUG) - Log.d(TAG, "Setting sleep timer to " + Long.toString(waitingTime) - + " milliseconds"); + Log.d(TAG, "Setting sleep timer to " + Long.toString(waitingTime) + " milliseconds"); if (isSleepTimerActive()) { sleepTimerFuture.cancel(true); } - sleepTimer = new SleepTimer(waitingTime); + sleepTimer = new SleepTimer(waitingTime, shakeToReset, vibrate); sleepTimerFuture = schedExecutor.schedule(sleepTimer, 0, TimeUnit.MILLISECONDS); } @@ -216,7 +213,11 @@ public class PlaybackServiceTaskManager { * Returns true if the sleep timer is currently active. */ public synchronized boolean isSleepTimerActive() { - return sleepTimer != null && sleepTimerFuture != null && !sleepTimerFuture.isCancelled() && !sleepTimerFuture.isDone() && sleepTimer.isWaiting; + return sleepTimer != null + && sleepTimerFuture != null + && !sleepTimerFuture.isCancelled() + && !sleepTimerFuture.isDone() + && sleepTimer.getWaitingTime() > 0; } /** @@ -224,8 +225,7 @@ public class PlaybackServiceTaskManager { */ public synchronized void disableSleepTimer() { if (isSleepTimerActive()) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Disabling sleep timer"); + Log.d(TAG, "Disabling sleep timer"); sleepTimerFuture.cancel(true); } } @@ -255,7 +255,7 @@ public class PlaybackServiceTaskManager { public synchronized void cancelWidgetUpdater() { if (isWidgetUpdaterActive()) { widgetUpdaterFuture.cancel(false); - if (BuildConfig.DEBUG) Log.d(TAG, "Cancelled WidgetUpdater"); + Log.d(TAG, "Cancelled WidgetUpdater"); } } @@ -284,16 +284,14 @@ public class PlaybackServiceTaskManager { Runnable chapterLoader = new Runnable() { @Override public void run() { - if (BuildConfig.DEBUG) - Log.d(TAG, "Chapter loader started"); + Log.d(TAG, "Chapter loader started"); if (media.getChapters() == null) { media.loadChapterMarks(); if (!Thread.currentThread().isInterrupted() && media.getChapters() != null) { callback.onChapterLoaded(media); } } - if (BuildConfig.DEBUG) - Log.d(TAG, "Chapter loader stopped"); + Log.d(TAG, "Chapter loader stopped"); } }; chapterLoaderFuture = schedExecutor.submit(chapterLoader); @@ -324,63 +322,88 @@ public class PlaybackServiceTaskManager { /** * Sleeps for a given time and then pauses playback. */ - private class SleepTimer implements Runnable { + protected class SleepTimer implements Runnable { private static final String TAG = "SleepTimer"; - private static final long UPDATE_INTERVALL = 1000L; - private volatile long waitingTime; - private volatile boolean isWaiting; - - public SleepTimer(long waitingTime) { + private static final long UPDATE_INTERVAL = 1000L; + private static final long NOTIFICATION_THRESHOLD = 10000; + private long waitingTime; + private final boolean shakeToReset; + private final boolean vibrate; + private ShakeListener shakeListener; + + public SleepTimer(long waitingTime, boolean shakeToReset, boolean vibrate) { super(); this.waitingTime = waitingTime; - isWaiting = true; + this.shakeToReset = shakeToReset; + this.vibrate = vibrate; } @Override public void run() { - if (BuildConfig.DEBUG) - Log.d(TAG, "Starting"); + Log.d(TAG, "Starting"); + boolean notifiedAlmostExpired = false; + long lastTick = System.currentTimeMillis(); while (waitingTime > 0) { try { - Thread.sleep(UPDATE_INTERVALL); - waitingTime -= UPDATE_INTERVALL; - + Thread.sleep(UPDATE_INTERVAL); + long now = System.currentTimeMillis(); + waitingTime -= now - lastTick; + lastTick = now; + + Log.d(TAG, "time left: " + waitingTime); + + if(waitingTime < NOTIFICATION_THRESHOLD && !notifiedAlmostExpired) { + Log.d(TAG, "Sleep timer is about to expire"); + if(vibrate) { + Vibrator v = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); + if(v != null) { + v.vibrate(500); + } + } + if(shakeListener == null && shakeToReset) { + shakeListener = new ShakeListener(context, this); + } + callback.onSleepTimerAlmostExpired(); + notifiedAlmostExpired = true; + } if (waitingTime <= 0) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Waiting completed"); - postExecute(); + Log.d(TAG, "Sleep timer expired"); + shakeListener.pause(); + shakeListener = null; if (!Thread.currentThread().isInterrupted()) { callback.onSleepTimerExpired(); } - } } catch (InterruptedException e) { Log.d(TAG, "Thread was interrupted while waiting"); + e.printStackTrace(); break; } } - postExecute(); - } - - protected void postExecute() { - isWaiting = false; } public long getWaitingTime() { return waitingTime; } - public boolean isWaiting() { - return isWaiting; + public void onShake() { + setSleepTimer(15 * 60 * 1000, shakeToReset, vibrate); + callback.onSleepTimerReset(); + shakeListener.pause(); + shakeListener = null; } } - public static interface PSTMCallback { + public interface PSTMCallback { void positionSaverTick(); + void onSleepTimerAlmostExpired(); + void onSleepTimerExpired(); + void onSleepTimerReset(); + void onWidgetUpdaterTick(); void onChapterLoaded(Playable media); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java new file mode 100644 index 000000000..77d765a85 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java @@ -0,0 +1,63 @@ +package de.danoeh.antennapod.core.service.playback; + +import android.content.Context; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.util.FloatMath; +import android.util.Log; + +public class ShakeListener implements SensorEventListener +{ + private static final String TAG = ShakeListener.class.getSimpleName(); + + private Sensor mAccelerometer; + private SensorManager mSensorMgr; + private PlaybackServiceTaskManager.SleepTimer mSleepTimer; + private Context mContext; + + public ShakeListener(Context context, PlaybackServiceTaskManager.SleepTimer sleepTimer) { + mContext = context; + mSleepTimer = sleepTimer; + resume(); + } + + public void resume() { + mSensorMgr = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); + if (mSensorMgr == null) { + throw new UnsupportedOperationException("Sensors not supported"); + } + mAccelerometer = mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); + if (!mSensorMgr.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_UI)) { // if not supported + mSensorMgr.unregisterListener(this); + throw new UnsupportedOperationException("Accelerometer not supported"); + } + } + + public void pause() { + if (mSensorMgr != null) { + mSensorMgr.unregisterListener(this); + mSensorMgr = null; + } + } + + @Override + public void onSensorChanged(SensorEvent event) { + float gX = event.values[0] / SensorManager.GRAVITY_EARTH; + float gY = event.values[1] / SensorManager.GRAVITY_EARTH; + float gZ = event.values[2] / SensorManager.GRAVITY_EARTH; + + float gForce = FloatMath.sqrt(gX*gX + gY*gY + gZ*gZ); + if (gForce > 2.25f) { + Log.d(TAG, "Detected shake " + gForce); + mSleepTimer.onShake(); + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) { + return; + } + +} \ No newline at end of file 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 ba5428b81..42aa3b713 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 @@ -652,9 +652,9 @@ public abstract class PlaybackController { } } - public void setSleepTimer(long time) { + public void setSleepTimer(long time, boolean shakeToReset, boolean vibrate) { if (playbackService != null) { - playbackService.setSleepTimer(time); + playbackService.setSleepTimer(time, shakeToReset, vibrate); } } -- cgit v1.2.3 From 98a6ab144bdf44bc9aa3c93c3ab04313180a9d53 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 9 Aug 2015 12:14:09 +0200 Subject: On sleep timer about to expire, lower volume even more --- .../de/danoeh/antennapod/core/service/playback/PlaybackService.java | 6 +----- .../core/service/playback/PlaybackServiceTaskManager.java | 2 -- .../de/danoeh/antennapod/core/service/playback/ShakeListener.java | 2 ++ 3 files changed, 3 insertions(+), 7 deletions(-) (limited to 'core/src/main') 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 ae927e6d6..c69a31bc3 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 @@ -19,7 +19,6 @@ import android.media.MediaMetadataRetriever; import android.media.MediaPlayer; import android.media.RemoteControlClient; import android.media.RemoteControlClient.MetadataEditor; -import android.os.AsyncTask; import android.os.Binder; import android.os.Build; import android.os.IBinder; @@ -33,12 +32,9 @@ import android.widget.Toast; import com.bumptech.glide.Glide; import com.bumptech.glide.load.engine.DiskCacheStrategy; -import com.bumptech.glide.request.animation.GlideAnimation; -import com.bumptech.glide.request.target.SimpleTarget; import org.apache.commons.lang3.StringUtils; -import java.io.IOException; import java.util.List; import java.util.concurrent.ExecutionException; @@ -406,7 +402,7 @@ public class PlaybackService extends Service { @Override public void onSleepTimerAlmostExpired() { - mediaPlayer.setVolume(0.5f); + mediaPlayer.setVolume(0.1f); } @Override 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 0a89860a8..4872dd7bd 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 @@ -350,8 +350,6 @@ public class PlaybackServiceTaskManager { waitingTime -= now - lastTick; lastTick = now; - Log.d(TAG, "time left: " + waitingTime); - if(waitingTime < NOTIFICATION_THRESHOLD && !notifiedAlmostExpired) { Log.d(TAG, "Sleep timer is about to expire"); if(vibrate) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java index 77d765a85..446061ea6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ShakeListener.java @@ -24,6 +24,8 @@ public class ShakeListener implements SensorEventListener } public void resume() { + // only a precaution, the user should actually not be able to activate shake to reset + // when the accelerometer is not available mSensorMgr = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); if (mSensorMgr == null) { throw new UnsupportedOperationException("Sensors not supported"); -- cgit v1.2.3 From 59f257a67866360061db4f5a63bc6212d39250b8 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 5 Sep 2015 01:32:47 +0200 Subject: Reset playback volume when going to sleep --- .../java/de/danoeh/antennapod/core/service/playback/PlaybackService.java | 1 + 1 file changed, 1 insertion(+) (limited to 'core/src/main') 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 c69a31bc3..80ba4fca7 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 @@ -408,6 +408,7 @@ public class PlaybackService extends Service { @Override public void onSleepTimerExpired() { mediaPlayer.pause(true, true); + mediaPlayer.setVolume(1.0f); sendNotificationBroadcast(NOTIFICATION_TYPE_SLEEPTIMER_UPDATE, 0); } -- cgit v1.2.3 From 37fd0a73ed978a65f22096c67fc7007cc308bd0c Mon Sep 17 00:00:00 2001 From: keunes Date: Sat, 5 Sep 2015 10:02:50 +0200 Subject: Update strings.xml --- core/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index c8fb83e46..0a45b883a 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -78,7 +78,7 @@ Retry Include in auto downloads Apply to Previous Episodes - The new Auto Download setting will automatically be applied to new episodes.\nDo you also want to apply it to previous episodes? + The new Auto Download setting will automatically be applied to new episodes.\nDo you also want to apply it to previously published episodes? Auto Delete Episode\n(override global default) \u0020parallel downloads Global -- cgit v1.2.3 From 152e497cfaaae1e8918c485d9cd6039465d4410b Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 29 Aug 2015 16:24:09 +0200 Subject: Fix gears color --- core/src/main/res/values/attrs.xml | 1 + core/src/main/res/values/colors.xml | 1 + core/src/main/res/values/styles.xml | 2 ++ 3 files changed, 4 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/res/values/attrs.xml b/core/src/main/res/values/attrs.xml index 2bdda2378..de641f518 100644 --- a/core/src/main/res/values/attrs.xml +++ b/core/src/main/res/values/attrs.xml @@ -1,6 +1,7 @@ + diff --git a/core/src/main/res/values/colors.xml b/core/src/main/res/values/colors.xml index bc0521dcd..566032da8 100644 --- a/core/src/main/res/values/colors.xml +++ b/core/src/main/res/values/colors.xml @@ -3,6 +3,7 @@ #FFFFFF #808080 + #757575 #bfbfbf #000000 #33B5E5 diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index 85c908f64..f6b66cc8a 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -4,6 +4,7 @@ + + + + \ No newline at end of file -- cgit v1.2.3 From 75dfc89a445c84e22639d101c229b0cfef6346f0 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Wed, 9 Sep 2015 14:05:58 +0200 Subject: Refactor database access --- .../core/asynctask/FlattrClickWorker.java | 2 +- .../core/asynctask/FlattrStatusFetcher.java | 2 +- .../antennapod/core/backup/OpmlBackupAgent.java | 2 +- .../de/danoeh/antennapod/core/feed/Chapter.java | 31 + .../java/de/danoeh/antennapod/core/feed/Feed.java | 63 +- .../de/danoeh/antennapod/core/feed/FeedImage.java | 19 + .../de/danoeh/antennapod/core/feed/FeedItem.java | 36 +- .../antennapod/core/feed/FeedItemFilter.java | 2 +- .../de/danoeh/antennapod/core/feed/FeedMedia.java | 68 +- .../antennapod/core/feed/FeedPreferences.java | 25 +- .../antennapod/core/glide/ApOkHttpUrlLoader.java | 2 +- .../core/service/GpodnetSyncService.java | 14 +- .../core/service/download/DownloadService.java | 21 +- .../core/service/download/DownloadStatus.java | 31 +- .../core/service/playback/PlaybackService.java | 4 +- .../playback/PlaybackServiceMediaPlayer.java | 4 +- .../playback/PlaybackServiceTaskManager.java | 2 +- .../core/storage/APCleanupAlgorithm.java | 44 +- .../core/storage/APDownloadAlgorithm.java | 8 +- .../danoeh/antennapod/core/storage/DBReader.java | 593 ++++------- .../de/danoeh/antennapod/core/storage/DBTasks.java | 48 +- .../danoeh/antennapod/core/storage/DBWriter.java | 1082 ++++++++------------ .../core/storage/EpisodeCleanupAlgorithm.java | 4 +- .../core/storage/FeedItemStatistics.java | 11 + .../antennapod/core/storage/PodDBAdapter.java | 212 +--- .../danoeh/antennapod/core/util/NetworkUtils.java | 2 +- .../danoeh/antennapod/core/util/QueueSorter.java | 2 +- .../antennapod/core/util/flattr/FlattrUtils.java | 2 +- .../core/util/gui/UndoBarController.java | 4 +- .../antennapod/core/util/playback/Playable.java | 2 +- .../core/util/playback/PlaybackController.java | 8 +- 31 files changed, 1025 insertions(+), 1325 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java index f91d4557e..93b584677 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrClickWorker.java @@ -94,7 +94,7 @@ public class FlattrClickWorker extends AsyncTask flattrQueue = DBReader.getFlattrQueue(context); + final List flattrQueue = DBReader.getFlattrQueue(); if (extraFlattrThing != null) { flattrQueue.add(extraFlattrThing); } else if (flattrQueue.size() == 1) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrStatusFetcher.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrStatusFetcher.java index c4aa76ac7..888591e89 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrStatusFetcher.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FlattrStatusFetcher.java @@ -32,7 +32,7 @@ public class FlattrStatusFetcher extends Thread { try { List flattredThings = FlattrUtils.retrieveFlattredThings(); - DBWriter.setFlattredStatus(context, flattredThings).get(); + DBWriter.setFlattredStatus(flattredThings).get(); } catch (FlattrException e) { e.printStackTrace(); Log.d(TAG, "flattrQueue exception retrieving list with flattred items " + e.getMessage()); diff --git a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java index 1535e2e9a..5ea0ba904 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java +++ b/core/src/main/java/de/danoeh/antennapod/core/backup/OpmlBackupAgent.java @@ -89,7 +89,7 @@ public class OpmlBackupAgent extends BackupAgentHelper { try { // Write OPML - new OpmlWriter().writeDocument(DBReader.getFeedList(mContext), writer); + new OpmlWriter().writeDocument(DBReader.getFeedList(), writer); // Compare checksum of new and old file to see if we need to perform a backup at all if (digester != null) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java index ce3352ed6..bb594ff87 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Chapter.java @@ -1,5 +1,9 @@ package de.danoeh.antennapod.core.feed; +import android.database.Cursor; + +import de.danoeh.antennapod.core.storage.PodDBAdapter; + public abstract class Chapter extends FeedComponent { /** Defines starting point in milliseconds. */ @@ -22,6 +26,33 @@ public abstract class Chapter extends FeedComponent { this.link = link; } + public static Chapter fromCursor(Cursor cursor, FeedItem item) { + int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_TITLE); + int indexStart = cursor.getColumnIndex(PodDBAdapter.KEY_START); + int indexLink = cursor.getColumnIndex(PodDBAdapter.KEY_LINK); + int indexChapterType = cursor.getColumnIndex(PodDBAdapter.KEY_CHAPTER_TYPE); + + String title = cursor.getString(indexTitle); + long start = cursor.getLong(indexStart); + String link = cursor.getString(indexLink); + int chapterType = cursor.getInt(indexChapterType); + + Chapter chapter = null; + switch (chapterType) { + case SimpleChapter.CHAPTERTYPE_SIMPLECHAPTER: + chapter = new SimpleChapter(start, title, item, link); + break; + case ID3Chapter.CHAPTERTYPE_ID3CHAPTER: + chapter = new ID3Chapter(start, title, item, link); + break; + case VorbisCommentChapter.CHAPTERTYPE_VORBISCOMMENT_CHAPTER: + chapter = new VorbisCommentChapter(start, title, item, link); + break; + } + return chapter; + } + + public abstract int getChapterType(); public long getStart() { diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java index 2a483ca9b..6b93723a0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/Feed.java @@ -1,6 +1,7 @@ package de.danoeh.antennapod.core.feed; import android.content.Context; +import android.database.Cursor; import android.net.Uri; import android.support.annotation.Nullable; @@ -12,6 +13,7 @@ import java.util.List; import de.danoeh.antennapod.core.asynctask.ImageResource; import de.danoeh.antennapod.core.storage.DBWriter; +import de.danoeh.antennapod.core.storage.PodDBAdapter; import de.danoeh.antennapod.core.util.flattr.FlattrStatus; import de.danoeh.antennapod.core.util.flattr.FlattrThing; @@ -170,11 +172,60 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { preferences = new FeedPreferences(0, true, FeedPreferences.AutoDeleteAction.GLOBAL, username, password); } - - /** - * Returns true if at least one item in the itemlist is unread. - * - */ + public static Feed fromCursor(Cursor cursor) { + int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID); + int indexLastUpdate = cursor.getColumnIndex(PodDBAdapter.KEY_LASTUPDATE); + int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_TITLE); + int indexLink = cursor.getColumnIndex(PodDBAdapter.KEY_LINK); + int indexDescription = cursor.getColumnIndex(PodDBAdapter.KEY_DESCRIPTION); + int indexPaymentLink = cursor.getColumnIndex(PodDBAdapter.KEY_PAYMENT_LINK); + int indexAuthor = cursor.getColumnIndex(PodDBAdapter.KEY_AUTHOR); + int indexLanguage = cursor.getColumnIndex(PodDBAdapter.KEY_LANGUAGE); + int indexType = cursor.getColumnIndex(PodDBAdapter.KEY_TYPE); + int indexFeedIdentifier = cursor.getColumnIndex(PodDBAdapter.KEY_FEED_IDENTIFIER); + int indexFileUrl = cursor.getColumnIndex(PodDBAdapter.KEY_FILE_URL); + int indexDownloadUrl = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOAD_URL); + int indexDownloaded = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOADED); + int indexFlattrStatus = cursor.getColumnIndex(PodDBAdapter.KEY_FLATTR_STATUS); + int indexIsPaged = cursor.getColumnIndex(PodDBAdapter.KEY_IS_PAGED); + int indexNextPageLink = cursor.getColumnIndex(PodDBAdapter.KEY_NEXT_PAGE_LINK); + int indexHide = cursor.getColumnIndex(PodDBAdapter.KEY_HIDE); + int indexLastUpdateFailed = cursor.getColumnIndex(PodDBAdapter.KEY_LAST_UPDATE_FAILED); + + Date lastUpdate = new Date(cursor.getLong(indexLastUpdate)); + + Feed feed = new Feed( + cursor.getLong(indexId), + lastUpdate, + cursor.getString(indexTitle), + cursor.getString(indexLink), + cursor.getString(indexDescription), + cursor.getString(indexPaymentLink), + cursor.getString(indexAuthor), + cursor.getString(indexLanguage), + cursor.getString(indexType), + cursor.getString(indexFeedIdentifier), + null, + cursor.getString(indexFileUrl), + cursor.getString(indexDownloadUrl), + cursor.getInt(indexDownloaded) > 0, + new FlattrStatus(cursor.getLong(indexFlattrStatus)), + cursor.getInt(indexIsPaged) > 0, + cursor.getString(indexNextPageLink), + cursor.getString(indexHide), + cursor.getInt(indexLastUpdateFailed) > 0 + ); + + FeedPreferences preferences = FeedPreferences.fromCursor(cursor); + feed.setPreferences(preferences); + return feed; + } + + + /** + * Returns true if at least one item in the itemlist is unread. + * + */ public boolean hasNewItems() { for (FeedItem item : items) { if (item.isNew()) { @@ -444,7 +495,7 @@ public class Feed extends FeedFile implements FlattrThing, ImageResource { } public void savePreferences(Context context) { - DBWriter.setFeedPreferences(context, preferences); + DBWriter.setFeedPreferences(preferences); } @Override diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java index f77a78721..bd7ceb54f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedImage.java @@ -1,10 +1,12 @@ package de.danoeh.antennapod.core.feed; +import android.database.Cursor; import android.net.Uri; import java.io.File; import de.danoeh.antennapod.core.asynctask.ImageResource; +import de.danoeh.antennapod.core.storage.PodDBAdapter; public class FeedImage extends FeedFile implements ImageResource { @@ -31,6 +33,23 @@ public class FeedImage extends FeedFile implements ImageResource { super(); } + public static FeedImage fromCursor(Cursor cursor) { + int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID); + int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_TITLE); + int indexFileUrl = cursor.getColumnIndex(PodDBAdapter.KEY_FILE_URL); + int indexDownloadUrl = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOAD_URL); + int indexDownloaded = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOADED); + + return new FeedImage( + cursor.getLong(indexId), + cursor.getString(indexTitle), + cursor.getString(indexFileUrl), + cursor.getString(indexDownloadUrl), + cursor.getInt(indexDownloaded) > 0 + ); + } + + @Override public String getHumanReadableIdentifier() { if (owner != null && owner.getHumanReadableIdentifier() != null) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java index 9229172f0..5c3ed303f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java @@ -1,5 +1,6 @@ package de.danoeh.antennapod.core.feed; +import android.database.Cursor; import android.net.Uri; import org.apache.commons.lang3.builder.ToStringBuilder; @@ -9,9 +10,9 @@ import java.util.Date; import java.util.List; import java.util.concurrent.Callable; -import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.asynctask.ImageResource; import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.core.storage.PodDBAdapter; import de.danoeh.antennapod.core.util.ShownotesProvider; import de.danoeh.antennapod.core.util.flattr.FlattrStatus; import de.danoeh.antennapod.core.util.flattr.FlattrThing; @@ -125,6 +126,37 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr this.hasChapters = hasChapters; } + public static FeedItem fromCursor(Cursor cursor) { + int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID); + int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_TITLE); + int indexLink = cursor.getColumnIndex(PodDBAdapter.KEY_LINK); + int indexPubDate = cursor.getColumnIndex(PodDBAdapter.KEY_PUBDATE); + int indexPaymentLink = cursor.getColumnIndex(PodDBAdapter.KEY_PAYMENT_LINK); + int indexFeedId = cursor.getColumnIndex(PodDBAdapter.KEY_FEED); + int indexFlattrStatus = cursor.getColumnIndex(PodDBAdapter.KEY_FLATTR_STATUS); + int indexHasChapters = cursor.getColumnIndex(PodDBAdapter.KEY_HAS_CHAPTERS); + int indexRead = cursor.getColumnIndex(PodDBAdapter.KEY_READ); + int indexItemIdentifier = cursor.getColumnIndex(PodDBAdapter.KEY_ITEM_IDENTIFIER); + int indexAutoDownload = cursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DOWNLOAD); + + long id = cursor.getInt(indexId); + assert(id > 0); + String title = cursor.getString(indexTitle); + String link = cursor.getString(indexLink); + Date pubDate = new Date(cursor.getLong(indexPubDate)); + String paymentLink = cursor.getString(indexPaymentLink); + long feedId = cursor.getLong(indexFeedId); + boolean hasChapters = cursor.getInt(indexHasChapters) > 0; + FlattrStatus flattrStatus = new FlattrStatus(cursor.getLong(indexFlattrStatus)); + int state = cursor.getInt(indexRead); + String itemIdentifier = cursor.getString(indexItemIdentifier); + boolean autoDownload = cursor.getInt(indexAutoDownload) > 0; + + FeedItem item = new FeedItem(id, title, link, pubDate, paymentLink, feedId, flattrStatus, + hasChapters, null, state, itemIdentifier, autoDownload); + return item; + } + public void updateFromOther(FeedItem other) { super.updateFromOther(other); if (other.title != null) { @@ -321,7 +353,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr public String call() throws Exception { if (contentEncoded == null || description == null) { - DBReader.loadExtraInformationOfFeedItem(ClientConfig.applicationCallbacks.getApplicationInstance(), FeedItem.this); + DBReader.loadExtraInformationOfFeedItem(FeedItem.this); } return (contentEncoded != null) ? contentEncoded : description; diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java index 2fd5666c8..879b28096 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java @@ -64,7 +64,7 @@ public class FeedItemFilter { if(hideUnplayed && false == item.isPlayed()) continue; if(hidePaused && item.getState() == FeedItem.State.IN_PROGRESS) continue; if(hidePlayed && item.isPlayed()) continue; - boolean isQueued = DBReader.getQueueIDList(context).contains(item.getId()); + boolean isQueued = DBReader.getQueueIDList().contains(item.getId()); if(hideQueued && isQueued) continue; if(hideNotQueued && false == isQueued) continue; boolean isDownloaded = item.getMedia() != null && item.getMedia().isDownloaded(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index ddb71fa7e..7397dd935 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -2,6 +2,7 @@ package de.danoeh.antennapod.core.feed; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; +import android.database.Cursor; import android.media.MediaMetadataRetriever; import android.net.Uri; import android.os.Parcel; @@ -11,11 +12,11 @@ import java.util.Date; import java.util.List; import java.util.concurrent.Callable; -import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; +import de.danoeh.antennapod.core.storage.PodDBAdapter; import de.danoeh.antennapod.core.util.ChapterUtils; import de.danoeh.antennapod.core.util.playback.Playable; @@ -83,6 +84,55 @@ public class FeedMedia extends FeedFile implements Playable { this.hasEmbeddedPicture = hasEmbeddedPicture; } + public static FeedMedia fromCursor(Cursor cursor) { + int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID); + int indexPlaybackCompletionDate = cursor.getColumnIndex(PodDBAdapter.KEY_PLAYBACK_COMPLETION_DATE); + int indexDuration = cursor.getColumnIndex(PodDBAdapter.KEY_DURATION); + int indexPosition = cursor.getColumnIndex(PodDBAdapter.KEY_POSITION); + int indexSize = cursor.getColumnIndex(PodDBAdapter.KEY_SIZE); + int indexMimeType = cursor.getColumnIndex(PodDBAdapter.KEY_MIME_TYPE); + int indexFileUrl = cursor.getColumnIndex(PodDBAdapter.KEY_FILE_URL); + int indexDownloadUrl = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOAD_URL); + int indexDownloaded = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOADED); + int indexPlayedDuration = cursor.getColumnIndex(PodDBAdapter.KEY_PLAYED_DURATION); + + long mediaId = cursor.getLong(indexId); + Date playbackCompletionDate = null; + long playbackCompletionTime = cursor.getLong(indexPlaybackCompletionDate); + if (playbackCompletionTime > 0) { + playbackCompletionDate = new Date(playbackCompletionTime); + } + + Boolean hasEmbeddedPicture; + switch(cursor.getInt(cursor.getColumnIndex(PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE))) { + case 1: + hasEmbeddedPicture = Boolean.TRUE; + break; + case 0: + hasEmbeddedPicture = Boolean.FALSE; + break; + default: + hasEmbeddedPicture = null; + break; + } + + return new FeedMedia( + mediaId, + null, + cursor.getInt(indexDuration), + cursor.getInt(indexPosition), + cursor.getLong(indexSize), + cursor.getString(indexMimeType), + cursor.getString(indexFileUrl), + cursor.getString(indexDownloadUrl), + cursor.getInt(indexDownloaded) > 0, + playbackCompletionDate, + cursor.getInt(indexPlayedDuration), + hasEmbeddedPicture + ); + } + + @Override public String getHumanReadableIdentifier() { if (item != null && item.getTitle() != null) { @@ -297,22 +347,22 @@ public class FeedMedia extends FeedFile implements Playable { @Override public void loadMetadata() throws PlayableException { if (item == null && itemID != 0) { - item = DBReader.getFeedItem(ClientConfig.applicationCallbacks.getApplicationInstance(), itemID); + item = DBReader.getFeedItem(itemID); } } @Override public void loadChapterMarks() { if (item == null && itemID != 0) { - item = DBReader.getFeedItem(ClientConfig.applicationCallbacks.getApplicationInstance(), itemID); + item = DBReader.getFeedItem(itemID); } // check if chapters are stored in db and not loaded yet. if (item != null && item.hasChapters() && item.getChapters() == null) { - DBReader.loadChaptersOfFeedItem(ClientConfig.applicationCallbacks.getApplicationInstance(), item); + DBReader.loadChaptersOfFeedItem(item); } else if (item != null && item.getChapters() == null && !localFileAvailable()) { ChapterUtils.loadChaptersFromStreamUrl(this); if (getChapters() != null && item != null) { - DBWriter.setFeedItem(ClientConfig.applicationCallbacks.getApplicationInstance(), + DBWriter.setFeedItem( item); } } @@ -389,9 +439,9 @@ public class FeedMedia extends FeedFile implements Playable { @Override public void saveCurrentPosition(SharedPreferences pref, int newPosition) { - DBWriter.setFeedMediaPlaybackInformation(ClientConfig.applicationCallbacks.getApplicationInstance(), this); + DBWriter.setFeedMediaPlaybackInformation(this); if(item.isNew()) { - DBWriter.markItemPlayed(ClientConfig.applicationCallbacks.getApplicationInstance(), FeedItem.UNPLAYED, item.getId()); + DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId()); } setPosition(newPosition); } @@ -421,11 +471,11 @@ public class FeedMedia extends FeedFile implements Playable { public String call() throws Exception { if (item == null) { item = DBReader.getFeedItem( - ClientConfig.applicationCallbacks.getApplicationInstance(), itemID); + itemID); } if (item.getContentEncoded() == null || item.getDescription() == null) { DBReader.loadExtraInformationOfFeedItem( - ClientConfig.applicationCallbacks.getApplicationInstance(), item); + item); } return (item.getContentEncoded() != null) ? item.getContentEncoded() : item.getDescription(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java index 88da865cc..eb28a3185 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedPreferences.java @@ -1,9 +1,13 @@ package de.danoeh.antennapod.core.feed; import android.content.Context; -import de.danoeh.antennapod.core.storage.DBWriter; +import android.database.Cursor; + import org.apache.commons.lang3.StringUtils; + import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.storage.DBWriter; +import de.danoeh.antennapod.core.storage.PodDBAdapter; /** * Contains preferences for a single feed. @@ -29,6 +33,23 @@ public class FeedPreferences { this.password = password; } + public static FeedPreferences fromCursor(Cursor cursor) { + int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID); + int indexAutoDownload = cursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DOWNLOAD); + int indexAutoDeleteAction = cursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DELETE_ACTION); + int indexUsername = cursor.getColumnIndex(PodDBAdapter.KEY_USERNAME); + int indexPassword = cursor.getColumnIndex(PodDBAdapter.KEY_PASSWORD); + + long feedId = cursor.getLong(indexId); + boolean autoDownload = cursor.getInt(indexAutoDownload) > 0; + int autoDeleteActionIndex = cursor.getInt(indexAutoDeleteAction); + AutoDeleteAction autoDeleteAction = AutoDeleteAction.values()[autoDeleteActionIndex]; + String username = cursor.getString(indexUsername); + String password = cursor.getString(indexPassword); + return new FeedPreferences(feedId, autoDownload, autoDeleteAction, username, password); + } + + /** * Compare another FeedPreferences with this one. The feedID, autoDownload and AutoDeleteAction attribute are excluded from the @@ -98,7 +119,7 @@ public class FeedPreferences { } public void save(Context context) { - DBWriter.setFeedPreferences(context, this); + DBWriter.setFeedPreferences(this); } public String getUsername() { diff --git a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java index cf3af7d4c..86baa459c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/glide/ApOkHttpUrlLoader.java @@ -108,7 +108,7 @@ public class ApOkHttpUrlLoader implements ModelLoader { com.squareup.okhttp.Request request = chain.request(); String url = request.urlString(); Context context = ClientConfig.applicationCallbacks.getApplicationInstance(); - String authentication = DBReader.getImageAuthentication(context, url); + String authentication = DBReader.getImageAuthentication(url); if(TextUtils.isEmpty(authentication)) { Log.d(TAG, "no credentials for '" + url + "'"); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java index e925f89a7..d5660f67e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/GpodnetSyncService.java @@ -126,7 +126,7 @@ public class GpodnetSyncService extends Service { private synchronized void syncSubscriptionChanges() { final long timestamp = GpodnetPreferences.getLastSubscriptionSyncTimestamp(); try { - final List localSubscriptions = DBReader.getFeedListDownloadUrls(this); + final List localSubscriptions = DBReader.getFeedListDownloadUrls(); Collection localAdded = GpodnetPreferences.getAddedFeedsCopy(); Collection localRemoved = GpodnetPreferences.getRemovedFeedsCopy(); GpodnetService service = tryLogin(); @@ -242,9 +242,9 @@ public class GpodnetSyncService extends Service { for (GpodnetEpisodeAction action : remoteActions) { switch (action.getAction()) { case NEW: - FeedItem newItem = DBReader.getFeedItem(this, action.getPodcast(), action.getEpisode()); + FeedItem newItem = DBReader.getFeedItem(action.getPodcast(), action.getEpisode()); if(newItem != null) { - DBWriter.markItemPlayed(this, newItem, FeedItem.UNPLAYED, true); + DBWriter.markItemPlayed(newItem, FeedItem.UNPLAYED, true); } else { Log.i(TAG, "Unknown feed item: " + action); } @@ -273,14 +273,14 @@ public class GpodnetSyncService extends Service { } } for (GpodnetEpisodeAction action : mostRecentPlayAction.values()) { - FeedItem playItem = DBReader.getFeedItem(this, action.getPodcast(), action.getEpisode()); + FeedItem playItem = DBReader.getFeedItem(action.getPodcast(), action.getEpisode()); if (playItem != null) { FeedMedia media = playItem.getMedia(); media.setPosition(action.getPosition() * 1000); - DBWriter.setFeedMedia(this, media); + DBWriter.setFeedMedia(media); if(playItem.getMedia().hasAlmostEnded()) { - DBWriter.markItemPlayed(this, playItem, FeedItem.PLAYED, true); - DBWriter.addItemToPlaybackHistory(this, playItem.getMedia()); + DBWriter.markItemPlayed(playItem, FeedItem.PLAYED, true); + DBWriter.addItemToPlaybackHistory(playItem.getMedia()); } } } 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 04ba77cda..36ea1e222 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,7 +20,6 @@ import android.util.Log; import android.webkit.URLUtil; import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; import org.apache.http.HttpStatus; @@ -504,7 +503,7 @@ public class DownloadService extends Service { */ private void saveDownloadStatus(DownloadStatus status) { reportQueue.add(status); - DBWriter.addDownloadStatus(this, status); + DBWriter.addDownloadStatus(status); } private void sendDownloadHandledIntent() { @@ -888,7 +887,7 @@ public class DownloadService extends Service { if (successful) { // we create a 'successful' download log if the feed's last refresh failed - List log = DBReader.getFeedDownloadLog(DownloadService.this, feed); + List log = DBReader.getFeedDownloadLog(feed); if(log.size() > 0 && log.get(0).isSuccessful() == false) { saveDownloadStatus(new DownloadStatus(feed, feed.getHumanReadableIdentifier(), DownloadError.SUCCESS, successful, @@ -1011,17 +1010,17 @@ public class DownloadService extends Service { @Override public void run() { if(request.getFeedfileType() == Feed.FEEDFILETYPE_FEED) { - DBWriter.setFeedLastUpdateFailed(DownloadService.this, request.getFeedfileId(), true); + DBWriter.setFeedLastUpdateFailed(request.getFeedfileId(), true); } else if (request.isDeleteOnFailure()) { Log.d(TAG, "Ignoring failed download, deleteOnFailure=true"); } else { File dest = new File(request.getDestination()); if (dest.exists() && request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { Log.d(TAG, "File has been partially downloaded. Writing file url"); - FeedMedia media = DBReader.getFeedMedia(DownloadService.this, request.getFeedfileId()); + FeedMedia media = DBReader.getFeedMedia(request.getFeedfileId()); media.setFile_url(request.getDestination()); try { - DBWriter.setFeedMedia(DownloadService.this, media).get(); + DBWriter.setFeedMedia(media).get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { @@ -1050,7 +1049,7 @@ public class DownloadService extends Service { @Override public void run() { - FeedImage image = DBReader.getFeedImage(DownloadService.this, request.getFeedfileId()); + FeedImage image = DBReader.getFeedImage(request.getFeedfileId()); if (image == null) { throw new IllegalStateException("Could not find downloaded image in database"); } @@ -1060,7 +1059,7 @@ public class DownloadService extends Service { saveDownloadStatus(status); sendDownloadHandledIntent(); - DBWriter.setFeedImage(DownloadService.this, image); + DBWriter.setFeedImage(image); numberOfDownloads.decrementAndGet(); queryDownloadsAsync(); } @@ -1084,7 +1083,7 @@ public class DownloadService extends Service { @Override public void run() { - FeedMedia media = DBReader.getFeedMedia(DownloadService.this, + FeedMedia media = DBReader.getFeedMedia( request.getFeedfileId()); if (media == null) { throw new IllegalStateException( @@ -1126,9 +1125,9 @@ public class DownloadService extends Service { item.setAutoDownload(false); // update the db - DBWriter.setFeedItem(DownloadService.this, item).get(); + DBWriter.setFeedItem(item).get(); - DBWriter.setFeedMedia(DownloadService.this, media).get(); + DBWriter.setFeedMedia(media).get(); if (!DBTasks.isInQueue(DownloadService.this, item.getId())) { DBWriter.addQueueItem(DownloadService.this, item.getId()).get(); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java index d05650d10..21928c94f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/DownloadStatus.java @@ -1,12 +1,15 @@ package de.danoeh.antennapod.core.service.download; +import android.database.Cursor; + import org.apache.commons.lang3.Validate; +import java.util.Date; + import de.danoeh.antennapod.core.feed.FeedFile; +import de.danoeh.antennapod.core.storage.PodDBAdapter; import de.danoeh.antennapod.core.util.DownloadError; -import java.util.Date; - /** Contains status attributes for one download */ public class DownloadStatus { /** @@ -101,6 +104,30 @@ public class DownloadStatus { this.reasonDetailed = reasonDetailed; } + public static DownloadStatus fromCursor(Cursor cursor) { + int indexId = cursor.getColumnIndex(PodDBAdapter.KEY_ID); + int indexTitle = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOADSTATUS_TITLE); + int indexFeedFile = cursor.getColumnIndex(PodDBAdapter.KEY_FEEDFILE); + int indexFileFileType = cursor.getColumnIndex(PodDBAdapter.KEY_FEEDFILETYPE); + int indexSuccessful = cursor.getColumnIndex(PodDBAdapter.KEY_SUCCESSFUL); + int indexReason = cursor.getColumnIndex(PodDBAdapter.KEY_REASON); + int indexCompletionDate = cursor.getColumnIndex(PodDBAdapter.KEY_COMPLETION_DATE); + int indexReasonDetailed = cursor.getColumnIndex(PodDBAdapter.KEY_REASON_DETAILED); + + long id = cursor.getLong(indexId); + String title = cursor.getString(indexTitle); + long feedfileId = cursor.getLong(indexFeedFile); + int feedfileType = cursor.getInt(indexFileFileType); + boolean successful = cursor.getInt(indexSuccessful) > 0; + int reason = cursor.getInt(indexReason); + Date completionDate = new Date(cursor.getLong(indexCompletionDate)); + String reasonDetailed = cursor.getString(indexReasonDetailed); + + return new DownloadStatus(id, title, feedfileId, + feedfileType, successful, DownloadError.fromCode(reason), completionDate, + reasonDetailed); + } + @Override public String toString() { return "DownloadStatus [id=" + id + ", title=" + title + ", reason=" 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 0ccc04238..9b6d17b98 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 @@ -564,7 +564,7 @@ public class PlaybackService extends Service { if (playable instanceof FeedMedia) { FeedMedia media = (FeedMedia) playable; FeedItem item = media.getItem(); - DBWriter.markItemPlayed(PlaybackService.this, item, FeedItem.PLAYED, true); + DBWriter.markItemPlayed(item, FeedItem.PLAYED, true); try { final List queue = taskManager.getQueue(); @@ -577,7 +577,7 @@ public class PlaybackService extends Service { if (isInQueue) { DBWriter.removeQueueItem(PlaybackService.this, item, true); } - DBWriter.addItemToPlaybackHistory(PlaybackService.this, media); + DBWriter.addItemToPlaybackHistory(media); // auto-flattr if enabled if (isAutoFlattrable(media) && UserPreferences.getAutoFlattrPlayedDurationThreshold() == 1.0f) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index c54afc7d6..2012549fc 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -201,9 +201,9 @@ public class PlaybackServiceMediaPlayer { if(oldMedia.hasAlmostEnded()) { Log.d(TAG, "smart mark as read"); FeedItem item = oldMedia.getItem(); - DBWriter.markItemPlayed(context, item, FeedItem.PLAYED, false); + DBWriter.markItemPlayed(item, FeedItem.PLAYED, false); DBWriter.removeQueueItem(context, item, false); - DBWriter.addItemToPlaybackHistory(context, oldMedia); + DBWriter.addItemToPlaybackHistory(oldMedia); if (item.getFeed().getPreferences().getCurrentAutoDelete()) { Log.d(TAG, "Delete " + oldMedia.toString()); DBWriter.deleteFeedMediaOfItem(context, oldMedia.getId()); 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 4872dd7bd..dba66a36d 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 @@ -100,7 +100,7 @@ public class PlaybackServiceTaskManager { queueFuture = schedExecutor.submit(new Callable>() { @Override public List call() throws Exception { - return DBReader.getQueue(context); + return DBReader.getQueue(); } }); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java index a07705e69..70b3aa90a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java @@ -5,7 +5,6 @@ import android.util.Log; import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.concurrent.ExecutionException; @@ -18,13 +17,14 @@ import de.danoeh.antennapod.core.util.LongList; * Implementation of the EpisodeCleanupAlgorithm interface used by AntennaPod. */ public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm { + private static final String TAG = "APCleanupAlgorithm"; @Override public int performCleanup(Context context, Integer episodeNumber) { - List candidates = new ArrayList(); - List downloadedItems = DBReader.getDownloadedItems(context); - LongList queue = DBReader.getQueueIDList(context); + List candidates = new ArrayList<>(); + List downloadedItems = DBReader.getDownloadedItems(); + LongList queue = DBReader.getQueueIDList(); List delete; for (FeedItem item : downloadedItems) { if (item.hasMedia() && item.getMedia().isDownloaded() @@ -34,20 +34,17 @@ public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm { } - Collections.sort(candidates, new Comparator() { - @Override - public int compare(FeedItem lhs, FeedItem rhs) { - Date l = lhs.getMedia().getPlaybackCompletionDate(); - Date r = rhs.getMedia().getPlaybackCompletionDate(); - - if (l == null) { - l = new Date(); - } - if (r == null) { - r = new Date(); - } - return l.compareTo(r); + Collections.sort(candidates, (lhs, rhs) -> { + Date l = lhs.getMedia().getPlaybackCompletionDate(); + Date r = rhs.getMedia().getPlaybackCompletionDate(); + + if (l == null) { + l = new Date(); + } + if (r == null) { + r = new Date(); } + return l.compareTo(r); }); if (candidates.size() > episodeNumber) { @@ -75,22 +72,21 @@ public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm { } @Override - public Integer getDefaultCleanupParameter(Context context) { - return getPerformAutoCleanupArgs(context, 0); + public Integer getDefaultCleanupParameter() { + return getPerformAutoCleanupArgs(0); } @Override - public Integer getPerformCleanupParameter(Context context, List items) { - return getPerformAutoCleanupArgs(context, items.size()); + public Integer getPerformCleanupParameter(List items) { + return getPerformAutoCleanupArgs(items.size()); } - static int getPerformAutoCleanupArgs(Context context, - final int episodeNumber) { + static int getPerformAutoCleanupArgs(final int episodeNumber) { if (episodeNumber >= 0 && UserPreferences.getEpisodeCacheSize() != UserPreferences .getEpisodeCacheSizeUnlimited()) { int downloadedEpisodes = DBReader - .getNumberOfDownloadedEpisodes(context); + .getNumberOfDownloadedEpisodes(); if (downloadedEpisodes + episodeNumber >= UserPreferences .getEpisodeCacheSize()) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java index be9ae1157..f2c56ee79 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java @@ -51,8 +51,8 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm { Log.d(TAG, "Performing auto-dl of undownloaded episodes"); List candidates; - final List queue = DBReader.getQueue(context); - final List newItems = DBReader.getNewItemsList(context); + final List queue = DBReader.getQueue(); + final List newItems = DBReader.getNewItemsList(); candidates = new ArrayList(queue.size() + newItems.size()); candidates.addAll(queue); for(FeedItem newItem : newItems) { @@ -71,9 +71,9 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm { } int autoDownloadableEpisodes = candidates.size(); - int downloadedEpisodes = DBReader.getNumberOfDownloadedEpisodes(context); + int downloadedEpisodes = DBReader.getNumberOfDownloadedEpisodes(); int deletedEpisodes = cleanupAlgorithm.performCleanup(context, - APCleanupAlgorithm.getPerformAutoCleanupArgs(context, autoDownloadableEpisodes)); + APCleanupAlgorithm.getPerformAutoCleanupArgs(autoDownloadableEpisodes)); boolean cacheIsUnlimited = UserPreferences.getEpisodeCacheSize() == UserPreferences .getEpisodeCacheSizeUnlimited(); int episodeCacheSize = UserPreferences.getEpisodeCacheSize(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 3da3824a2..4ef4ac067 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -1,6 +1,5 @@ package de.danoeh.antennapod.core.storage; -import android.content.Context; import android.database.Cursor; import android.util.Log; @@ -9,10 +8,8 @@ import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; -import java.util.Date; import java.util.List; -import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedImage; @@ -24,13 +21,11 @@ import de.danoeh.antennapod.core.feed.SimpleChapter; import de.danoeh.antennapod.core.feed.VorbisCommentChapter; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.DownloadStatus; -import de.danoeh.antennapod.core.util.DownloadError; import de.danoeh.antennapod.core.util.LongIntMap; import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.comparator.DownloadStatusComparator; import de.danoeh.antennapod.core.util.comparator.FeedItemPubdateComparator; import de.danoeh.antennapod.core.util.comparator.PlaybackCompletionDateComparator; -import de.danoeh.antennapod.core.util.flattr.FlattrStatus; import de.danoeh.antennapod.core.util.flattr.FlattrThing; /** @@ -40,15 +35,16 @@ import de.danoeh.antennapod.core.util.flattr.FlattrThing; * This class will use the {@link de.danoeh.antennapod.core.feed.EventDistributor} to notify listeners about changes in the database. */ public final class DBReader { + private static final String TAG = "DBReader"; /** - * Maximum size of the list returned by {@link #getPlaybackHistory(android.content.Context)}. + * Maximum size of the list returned by {@link #getPlaybackHistory()}. */ public static final int PLAYBACK_HISTORY_SIZE = 50; /** - * Maximum size of the list returned by {@link #getDownloadLog(android.content.Context)}. + * Maximum size of the list returned by {@link #getDownloadLog()}. */ public static final int DOWNLOAD_LOG_SIZE = 200; @@ -59,16 +55,14 @@ public final class DBReader { /** * Returns a list of Feeds, sorted alphabetically by their title. * - * @param context A context that is used for opening a database connection. * @return A list of Feeds, sorted alphabetically by their title. A Feed-object * of the returned list does NOT have its list of FeedItems yet. The FeedItem-list - * can be loaded separately with {@link #getFeedItemList(android.content.Context, de.danoeh.antennapod.core.feed.Feed)}. + * can be loaded separately with {@link #getFeedItemList(Feed)}. */ - public static List getFeedList(final Context context) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Extracting Feedlist"); + public static List getFeedList() { + Log.d(TAG, "Extracting Feedlist"); - PodDBAdapter adapter = new PodDBAdapter(context); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); List result = getFeedList(adapter); adapter.close(); @@ -76,11 +70,8 @@ public final class DBReader { } private static List getFeedList(PodDBAdapter adapter) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Extracting Feedlist"); - Cursor feedlistCursor = adapter.getAllFeedsCursor(); - List feeds = new ArrayList(feedlistCursor.getCount()); + List feeds = new ArrayList<>(feedlistCursor.getCount()); if (feedlistCursor.moveToFirst()) { do { @@ -95,12 +86,11 @@ public final class DBReader { /** * Returns a list with the download URLs of all feeds. * - * @param context A context that is used for opening the database connection. * @return A list of Strings with the download URLs of all feeds. */ - public static List getFeedListDownloadUrls(final Context context) { - PodDBAdapter adapter = new PodDBAdapter(context); - List result = new ArrayList(); + public static List getFeedListDownloadUrls() { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + List result = new ArrayList<>(); adapter.open(); Cursor feeds = adapter.getFeedCursorDownloadUrls(); if (feeds.moveToFirst()) { @@ -119,12 +109,10 @@ public final class DBReader { * The feedID-attribute of a FeedItem must be set to the ID of its feed or the method will * not find the correct feed of an item. * - * @param context A context that is used for opening a database connection. * @param items The FeedItems whose Feed-objects should be loaded. */ - public static void loadFeedDataOfFeedItemlist(Context context, - List items) { - List feeds = getFeedList(context); + public static void loadFeedDataOfFeedItemlist(List items) { + List feeds = getFeedList(); for (FeedItem item : items) { for (Feed feed : feeds) { if (feed.getId() == item.getFeedId()) { @@ -140,18 +128,16 @@ public final class DBReader { /** * Loads the list of FeedItems for a certain Feed-object. This method should NOT be used if the FeedItems are not - * used. In order to get information ABOUT the list of FeedItems, consider using {@link #getFeedStatisticsList(android.content.Context)} instead. + * used. In order to get information ABOUT the list of FeedItems, consider using {@link #getFeedStatisticsList()} instead. * - * @param context A context that is used for opening a database connection. * @param feed The Feed whose items should be loaded * @return A list with the FeedItems of the Feed. The Feed-attribute of the FeedItems will already be set correctly. * The method does NOT change the items-attribute of the feed. */ - public static List getFeedItemList(Context context, - final Feed feed) { + public static List getFeedItemList(final Feed feed) { Log.d(TAG, "Extracting Feeditems of feed " + feed.getTitle()); - PodDBAdapter adapter = new PodDBAdapter(context); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor itemlistCursor = adapter.getAllItemsOfFeedCursor(feed); @@ -170,8 +156,8 @@ public final class DBReader { return items; } - static List extractItemlistFromCursor(Context context, Cursor itemlistCursor) { - PodDBAdapter adapter = new PodDBAdapter(context); + public static List extractItemlistFromCursor(Cursor itemlistCursor) { + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); List result = extractItemlistFromCursor(adapter, itemlistCursor); adapter.close(); @@ -180,31 +166,20 @@ public final class DBReader { private static List extractItemlistFromCursor( PodDBAdapter adapter, Cursor itemlistCursor) { - ArrayList itemIds = new ArrayList(); - List items = new ArrayList( - itemlistCursor.getCount()); + ArrayList itemIds = new ArrayList<>(); + List items = new ArrayList<>(itemlistCursor.getCount()); if (itemlistCursor.moveToFirst()) { do { - long imageIndex = itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_IMAGE); + int indexImage = itemlistCursor.getColumnIndex(PodDBAdapter.KEY_IMAGE); + long imageId = itemlistCursor.getLong(indexImage); FeedImage image = null; - if (imageIndex != 0) { - image = getFeedImage(adapter, imageIndex); + if (imageId != 0) { + image = getFeedImage(adapter, imageId); } - FeedItem item = new FeedItem(itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_ID), - itemlistCursor.getString(PodDBAdapter.IDX_FI_SMALL_TITLE), - itemlistCursor.getString(PodDBAdapter.IDX_FI_SMALL_LINK), - new Date(itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_PUBDATE)), - itemlistCursor.getString(PodDBAdapter.IDX_FI_SMALL_PAYMENT_LINK), - itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_FEED), - new FlattrStatus(itemlistCursor.getLong(PodDBAdapter.IDX_FI_SMALL_FLATTR_STATUS)), - itemlistCursor.getInt(PodDBAdapter.IDX_FI_SMALL_HAS_CHAPTERS) > 0, - image, - itemlistCursor.getInt(PodDBAdapter.IDX_FI_SMALL_READ), - itemlistCursor.getString(PodDBAdapter.IDX_FI_SMALL_ITEM_IDENTIFIER), - itemlistCursor.getInt(itemlistCursor.getColumnIndex(PodDBAdapter.KEY_AUTO_DOWNLOAD)) > 0 - ); + FeedItem item = FeedItem.fromCursor(itemlistCursor); + item.setImage(image); itemIds.add(String.valueOf(item.getId())); @@ -219,16 +194,18 @@ public final class DBReader { private static void extractMediafromItemlist(PodDBAdapter adapter, List items, ArrayList itemIds) { - List itemsCopy = new ArrayList(items); + List itemsCopy = new ArrayList<>(items); Cursor cursor = adapter.getFeedMediaCursorByItemID(itemIds .toArray(new String[itemIds.size()])); if (cursor.moveToFirst()) { do { - long itemId = cursor.getLong(PodDBAdapter.KEY_MEDIA_FEEDITEM_INDEX); + int index = cursor.getColumnIndex(PodDBAdapter.KEY_FEEDITEM); + long itemId = cursor.getLong(index); // find matching feed item FeedItem item = getMatchingItemForMedia(itemId, itemsCopy); if (item != null) { - item.setMedia(extractFeedMediaFromCursorRow(cursor)); + FeedMedia media = FeedMedia.fromCursor(cursor); + item.setMedia(media); item.getMedia().setItem(item); } } while (cursor.moveToNext()); @@ -236,105 +213,29 @@ public final class DBReader { cursor.close(); } - private static FeedMedia extractFeedMediaFromCursorRow(final Cursor cursor) { - long mediaId = cursor.getLong(PodDBAdapter.KEY_ID_INDEX); - Date playbackCompletionDate = null; - long playbackCompletionTime = cursor - .getLong(PodDBAdapter.KEY_PLAYBACK_COMPLETION_DATE_INDEX); - if (playbackCompletionTime > 0) { - playbackCompletionDate = new Date( - playbackCompletionTime); - } - Boolean hasEmbeddedPicture; - switch(cursor.getInt(cursor.getColumnIndex(PodDBAdapter.KEY_HAS_EMBEDDED_PICTURE))) { - case 1: - hasEmbeddedPicture = Boolean.TRUE; - break; - case 0: - hasEmbeddedPicture = Boolean.FALSE; - break; - default: - hasEmbeddedPicture = null; - break; - } - - return new FeedMedia( - mediaId, - null, - cursor.getInt(PodDBAdapter.KEY_DURATION_INDEX), - cursor.getInt(PodDBAdapter.KEY_POSITION_INDEX), - cursor.getLong(PodDBAdapter.KEY_SIZE_INDEX), - cursor.getString(PodDBAdapter.KEY_MIME_TYPE_INDEX), - cursor.getString(PodDBAdapter.KEY_FILE_URL_INDEX), - cursor.getString(PodDBAdapter.KEY_DOWNLOAD_URL_INDEX), - cursor.getInt(PodDBAdapter.KEY_DOWNLOADED_INDEX) > 0, - playbackCompletionDate, - cursor.getInt(PodDBAdapter.KEY_PLAYED_DURATION_INDEX), - hasEmbeddedPicture); - } - private static Feed extractFeedFromCursorRow(PodDBAdapter adapter, Cursor cursor) { - Date lastUpdate = new Date( - cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_LASTUPDATE)); - final FeedImage image; - long imageIndex = cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_IMAGE); - if (imageIndex != 0) { - image = getFeedImage(adapter, imageIndex); + int indexImage = cursor.getColumnIndex(PodDBAdapter.KEY_IMAGE); + long imageId = cursor.getLong(indexImage); + if (imageId != 0) { + image = getFeedImage(adapter, imageId); } else { image = null; } - Feed feed = new Feed(cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_ID), - lastUpdate, - cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_TITLE), - cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_LINK), - cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_DESCRIPTION), - cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_PAYMENT_LINK), - cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_AUTHOR), - cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_LANGUAGE), - cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_TYPE), - cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_FEED_IDENTIFIER), - image, - cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_FILE_URL), - cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_DOWNLOAD_URL), - cursor.getInt(PodDBAdapter.IDX_FEED_SEL_STD_DOWNLOADED) > 0, - new FlattrStatus(cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_FLATTR_STATUS)), - cursor.getInt(PodDBAdapter.IDX_FEED_SEL_STD_IS_PAGED) > 0, - cursor.getString(PodDBAdapter.IDX_FEED_SEL_STD_NEXT_PAGE_LINK), - cursor.getString(cursor.getColumnIndex(PodDBAdapter.KEY_HIDE)), - cursor.getInt(cursor.getColumnIndex(PodDBAdapter.KEY_LAST_UPDATE_FAILED)) > 0 - ); + Feed feed = Feed.fromCursor(cursor); if (image != null) { + feed.setImage(image); image.setOwner(feed); } - FeedPreferences preferences = new FeedPreferences(cursor.getLong(PodDBAdapter.IDX_FEED_SEL_STD_ID), - cursor.getInt(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_AUTO_DOWNLOAD) > 0, - FeedPreferences.AutoDeleteAction.values()[cursor.getInt(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_AUTO_DELETE_ACTION)], - cursor.getString(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_USERNAME), - cursor.getString(PodDBAdapter.IDX_FEED_SEL_PREFERENCES_PASSWORD)); + FeedPreferences preferences = FeedPreferences.fromCursor(cursor); feed.setPreferences(preferences); - return feed; - } - private static DownloadStatus extractDownloadStatusFromCursorRow(final Cursor cursor) { - long id = cursor.getLong(PodDBAdapter.KEY_ID_INDEX); - long feedfileId = cursor.getLong(PodDBAdapter.KEY_FEEDFILE_INDEX); - int feedfileType = cursor.getInt(PodDBAdapter.KEY_FEEDFILETYPE_INDEX); - boolean successful = cursor.getInt(PodDBAdapter.KEY_SUCCESSFUL_INDEX) > 0; - int reason = cursor.getInt(PodDBAdapter.KEY_REASON_INDEX); - String reasonDetailed = cursor.getString(PodDBAdapter.KEY_REASON_DETAILED_INDEX); - String title = cursor.getString(PodDBAdapter.KEY_DOWNLOADSTATUS_TITLE_INDEX); - Date completionDate = new Date(cursor.getLong(PodDBAdapter.KEY_COMPLETION_DATE_INDEX)); - - return new DownloadStatus(id, title, feedfileId, - feedfileType, successful, DownloadError.fromCode(reason), completionDate, - reasonDetailed); + return feed; } - private static FeedItem getMatchingItemForMedia(long itemId, List items) { for (FeedItem item : items) { @@ -345,33 +246,27 @@ public final class DBReader { return null; } - static List getQueue(Context context, PodDBAdapter adapter) { + static List getQueue(PodDBAdapter adapter) { Log.d(TAG, "getQueue()"); - Cursor itemlistCursor = adapter.getQueueCursor(); - List items = extractItemlistFromCursor(adapter, - itemlistCursor); + List items = extractItemlistFromCursor(adapter, itemlistCursor); itemlistCursor.close(); - loadFeedDataOfFeedItemlist(context, items); - + loadFeedDataOfFeedItemlist(items); return items; } /** * Loads the IDs of the FeedItems in the queue. This method should be preferred over - * {@link #getQueue(android.content.Context)} if the FeedItems of the queue are not needed. + * {@link #getQueue()} if the FeedItems of the queue are not needed. * - * @param context A context that is used for opening a database connection. * @return A list of IDs sorted by the same order as the queue. The caller can wrap the returned * list in a {@link de.danoeh.antennapod.core.util.QueueAccess} object for easier access to the queue's properties. */ - public static LongList getQueueIDList(Context context) { - PodDBAdapter adapter = new PodDBAdapter(context); - + public static LongList getQueueIDList() { + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); LongList result = getQueueIDList(adapter); adapter.close(); - return result; } @@ -389,37 +284,19 @@ public final class DBReader { return queueIds; } - - /** - * Return the size of the queue. - * - * @param context A context that is used for opening a database connection. - * @return Size of the queue. - */ - public static int getQueueSize(Context context) { - Log.d(TAG, "getQueueSize()"); - - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - int size = adapter.getQueueSize(); - adapter.close(); - return size; - } - /** * Loads a list of the FeedItems in the queue. If the FeedItems of the queue are not used directly, consider using - * {@link #getQueueIDList(android.content.Context)} instead. + * {@link #getQueueIDList()} instead. * - * @param context A context that is used for opening a database connection. * @return A list of FeedItems sorted by the same order as the queue. The caller can wrap the returned * list in a {@link de.danoeh.antennapod.core.util.QueueAccess} object for easier access to the queue's properties. */ - public static List getQueue(Context context) { + public static List getQueue() { Log.d(TAG, "getQueue()"); - PodDBAdapter adapter = new PodDBAdapter(context); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - List items = getQueue(context, adapter); + List items = getQueue(adapter); adapter.close(); return items; } @@ -427,21 +304,19 @@ public final class DBReader { /** * Loads a list of FeedItems whose episode has been downloaded. * - * @param context A context that is used for opening a database connection. * @return A list of FeedItems whose episdoe has been downloaded. */ - public static List getDownloadedItems(Context context) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Extracting downloaded items"); + public static List getDownloadedItems() { + Log.d(TAG, "Extracting downloaded items"); - PodDBAdapter adapter = new PodDBAdapter(context); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor itemlistCursor = adapter.getDownloadedItemsCursor(); List items = extractItemlistFromCursor(adapter, itemlistCursor); itemlistCursor.close(); - loadFeedDataOfFeedItemlist(context, items); + loadFeedDataOfFeedItemlist(items); Collections.sort(items, new FeedItemPubdateComparator()); adapter.close(); @@ -452,22 +327,18 @@ public final class DBReader { /** * Loads a list of FeedItems whose 'read'-attribute is set to false. * - * @param context A context that is used for opening a database connection. * @return A list of FeedItems whose 'read'-attribute it set to false. */ - public static List getUnreadItemsList(Context context) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Extracting unread items list"); + public static List getUnreadItemsList() { + Log.d(TAG, "Extracting unread items list"); - PodDBAdapter adapter = new PodDBAdapter(context); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - Cursor itemlistCursor = adapter.getUnreadItemsCursor(); - List items = extractItemlistFromCursor(adapter, - itemlistCursor); + List items = extractItemlistFromCursor(adapter, itemlistCursor); itemlistCursor.close(); - loadFeedDataOfFeedItemlist(context, items); + loadFeedDataOfFeedItemlist(items); adapter.close(); @@ -477,69 +348,41 @@ public final class DBReader { /** * Loads a list of FeedItems that are considered new. * - * @param context A context that is used for opening a database connection. * @return A list of FeedItems that are considered new. */ - public static List getNewItemsList(Context context) { + public static List getNewItemsList() { Log.d(TAG, "getNewItemsList()"); - PodDBAdapter adapter = new PodDBAdapter(context); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor itemlistCursor = adapter.getNewItemsCursor(); List items = extractItemlistFromCursor(adapter, itemlistCursor); itemlistCursor.close(); - loadFeedDataOfFeedItemlist(context, items); + loadFeedDataOfFeedItemlist(items); adapter.close(); return items; } - /** - * Loads the IDs of the FeedItems whose 'read'-attribute is set to false. - * - * @param context A context that is used for opening a database connection. - * @return A list of IDs of the FeedItems whose 'read'-attribute is set to false. This method should be preferred - * over {@link #getUnreadItemsList(android.content.Context)} if the FeedItems in the UnreadItems list are not used. - */ - public static LongList getNewItemIds(Context context) { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - Cursor cursor = adapter.getNewItemIdsCursor(); - LongList itemIds = new LongList(cursor.getCount()); - int i = 0; - if (cursor.moveToFirst()) { - do { - long id = cursor.getLong(PodDBAdapter.KEY_ID_INDEX); - itemIds.add(id); - i++; - } while (cursor.moveToNext()); - } - cursor.close(); - return itemIds; - } - /** * Loads a list of FeedItems sorted by pubDate in descending order. * - * @param context A context that is used for opening a database connection. * @param limit The maximum number of episodes that should be loaded. */ - public static List getRecentlyPublishedEpisodes(Context context, int limit) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Extracting recently published items list"); + public static List getRecentlyPublishedEpisodes(int limit) { + Log.d(TAG, "Extracting recently published items list"); - PodDBAdapter adapter = new PodDBAdapter(context); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor itemlistCursor = adapter.getRecentlyPublishedItemsCursor(limit); - List items = extractItemlistFromCursor(adapter, - itemlistCursor); + List items = extractItemlistFromCursor(adapter, itemlistCursor); itemlistCursor.close(); - loadFeedDataOfFeedItemlist(context, items); + loadFeedDataOfFeedItemlist(items); adapter.close(); @@ -550,26 +393,25 @@ public final class DBReader { * Loads the playback history from the database. A FeedItem is in the playback history if playback of the correpsonding episode * has been completed at least once. * - * @param context A context that is used for opening a database connection. * @return The playback history. The FeedItems are sorted by their media's playbackCompletionDate in descending order. * The size of the returned list is limited by {@link #PLAYBACK_HISTORY_SIZE}. */ - public static List getPlaybackHistory(final Context context) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Loading playback history"); + public static List getPlaybackHistory() { + Log.d(TAG, "Loading playback history"); - PodDBAdapter adapter = new PodDBAdapter(context); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor mediaCursor = adapter.getCompletedMediaCursor(PLAYBACK_HISTORY_SIZE); String[] itemIds = new String[mediaCursor.getCount()]; for (int i = 0; i < itemIds.length && mediaCursor.moveToPosition(i); i++) { - itemIds[i] = Long.toString(mediaCursor.getLong(PodDBAdapter.KEY_MEDIA_FEEDITEM_INDEX)); + int index = mediaCursor.getColumnIndex(PodDBAdapter.KEY_FEEDITEM); + itemIds[i] = Long.toString(mediaCursor.getLong(index)); } mediaCursor.close(); Cursor itemCursor = adapter.getFeedItemCursor(itemIds); List items = extractItemlistFromCursor(adapter, itemCursor); - loadFeedDataOfFeedItemlist(context, items); + loadFeedDataOfFeedItemlist(items); itemCursor.close(); adapter.close(); @@ -580,23 +422,21 @@ public final class DBReader { /** * Loads the download log from the database. * - * @param context A context that is used for opening a database connection. * @return A list with DownloadStatus objects that represent the download log. * The size of the returned list is limited by {@link #DOWNLOAD_LOG_SIZE}. */ - public static List getDownloadLog(Context context) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Extracting DownloadLog"); + public static List getDownloadLog() { + Log.d(TAG, "Extracting DownloadLog"); - PodDBAdapter adapter = new PodDBAdapter(context); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor logCursor = adapter.getDownloadLogCursor(DOWNLOAD_LOG_SIZE); - List downloadLog = new ArrayList( - logCursor.getCount()); + List downloadLog = new ArrayList<>(logCursor.getCount()); if (logCursor.moveToFirst()) { do { - downloadLog.add(extractDownloadStatusFromCursorRow(logCursor)); + DownloadStatus status = DownloadStatus.fromCursor(logCursor); + downloadLog.add(status); } while (logCursor.moveToNext()); } logCursor.close(); @@ -607,50 +447,22 @@ public final class DBReader { /** * Loads the download log for a particular feed from the database. * - * @param context A context that is used for opening a database connection. * @param feed Feed for which the download log is loaded * @return A list with DownloadStatus objects that represent the feed's download log, * newest events first. */ - public static List getFeedDownloadLog(Context context, Feed feed) { - Log.d(TAG, "getFeedDownloadLog(CONTEXT, " + feed.toString() + ")"); + public static List getFeedDownloadLog(Feed feed) { + Log.d(TAG, "getFeedDownloadLog(" + feed.toString() + ")"); - PodDBAdapter adapter = new PodDBAdapter(context); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor cursor = adapter.getDownloadLog(Feed.FEEDFILETYPE_FEED, feed.getId()); - List downloadLog = new ArrayList( - cursor.getCount()); + List downloadLog = new ArrayList<>(cursor.getCount()); if (cursor.moveToFirst()) { do { - downloadLog.add(extractDownloadStatusFromCursorRow(cursor)); - } while (cursor.moveToNext()); - } - cursor.close(); - Collections.sort(downloadLog, new DownloadStatusComparator()); - return downloadLog; - } - - /** - * Loads the download log for a particular feed media from the database. - * - * @param context A context that is used for opening a database connection. - * @param media Feed media for which the download log is loaded - * @return A list with DownloadStatus objects that represent the feed media's download log, - * newest events first. - */ - public static List getFeedMediaDownloadLog(Context context, FeedMedia media) { - Log.d(TAG, "getFeedDownloadLog(CONTEXT, " + media.toString() + ")"); - - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - Cursor cursor = adapter.getDownloadLog(FeedMedia.FEEDFILETYPE_FEEDMEDIA, media.getId()); - List downloadLog = new ArrayList( - cursor.getCount()); - - if (cursor.moveToFirst()) { - do { - downloadLog.add(extractDownloadStatusFromCursorRow(cursor)); + DownloadStatus status = DownloadStatus.fromCursor(cursor); + downloadLog.add(status); } while (cursor.moveToNext()); } cursor.close(); @@ -660,24 +472,20 @@ public final class DBReader { /** * Loads the FeedItemStatistics objects of all Feeds in the database. This method should be preferred over - * {@link #getFeedItemList(android.content.Context, de.danoeh.antennapod.core.feed.Feed)} if only metadata about + * {@link #getFeedItemList(Feed)} if only metadata about * the FeedItems is needed. * - * @param context A context that is used for opening a database connection. * @return A list of FeedItemStatistics objects sorted alphabetically by their Feed's title. */ - public static List getFeedStatisticsList(final Context context) { - PodDBAdapter adapter = new PodDBAdapter(context); + public static List getFeedStatisticsList() { + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - List result = new ArrayList(); + List result = new ArrayList<>(); Cursor cursor = adapter.getFeedStatisticsCursor(); if (cursor.moveToFirst()) { do { - result.add(new FeedItemStatistics(cursor.getLong(PodDBAdapter.IDX_FEEDSTATISTICS_FEED), - cursor.getInt(PodDBAdapter.IDX_FEEDSTATISTICS_NUM_ITEMS), - cursor.getInt(PodDBAdapter.IDX_FEEDSTATISTICS_NEW_ITEMS), - cursor.getInt(PodDBAdapter.IDX_FEEDSTATISTICS_IN_PROGRESS_EPISODES), - new Date(cursor.getLong(PodDBAdapter.IDX_FEEDSTATISTICS_LATEST_EPISODE)))); + FeedItemStatistics fis = FeedItemStatistics.fromCursor(cursor); + result.add(fis); } while (cursor.moveToNext()); } @@ -689,28 +497,26 @@ public final class DBReader { /** * Loads a specific Feed from the database. * - * @param context A context that is used for opening a database connection. * @param feedId The ID of the Feed * @return The Feed or null if the Feed could not be found. The Feeds FeedItems will also be loaded from the * database and the items-attribute will be set correctly. */ - public static Feed getFeed(final Context context, final long feedId) { - PodDBAdapter adapter = new PodDBAdapter(context); + public static Feed getFeed(final long feedId) { + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - Feed result = getFeed(context, feedId, adapter); + Feed result = getFeed(feedId, adapter); adapter.close(); return result; } - static Feed getFeed(final Context context, final long feedId, PodDBAdapter adapter) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Loading feed with id " + feedId); + static Feed getFeed(final long feedId, PodDBAdapter adapter) { + Log.d(TAG, "Loading feed with id " + feedId); Feed feed = null; Cursor feedCursor = adapter.getFeedCursor(feedId); if (feedCursor.moveToFirst()) { feed = extractFeedFromCursorRow(adapter, feedCursor); - feed.setItems(getFeedItemList(context, feed)); + feed.setItems(getFeedItemList(feed)); } else { Log.e(TAG, "getFeed could not find feed with id " + feedId); } @@ -718,9 +524,8 @@ public final class DBReader { return feed; } - static FeedItem getFeedItem(final Context context, final long itemId, PodDBAdapter adapter) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Loading feeditem with id " + itemId); + static FeedItem getFeedItem(final long itemId, PodDBAdapter adapter) { + Log.d(TAG, "Loading feeditem with id " + itemId); FeedItem item = null; Cursor itemCursor = adapter.getFeedItemCursor(Long.toString(itemId)); @@ -728,7 +533,7 @@ public final class DBReader { List list = extractItemlistFromCursor(adapter, itemCursor); if (list.size() > 0) { item = list.get(0); - loadFeedDataOfFeedItemlist(context, list); + loadFeedDataOfFeedItemlist(list); if (item.hasChapters()) { loadChaptersOfFeedItem(adapter, item); } @@ -738,7 +543,7 @@ public final class DBReader { return item; } - static List getFeedItems(final Context context, PodDBAdapter adapter, final long... itemIds) { + static List getFeedItems(PodDBAdapter adapter, final long... itemIds) { String[] ids = new String[itemIds.length]; for(int i = 0; i < itemIds.length; i++) { @@ -751,7 +556,7 @@ public final class DBReader { Cursor itemCursor = adapter.getFeedItemCursor(ids); if (itemCursor.moveToFirst()) { result = extractItemlistFromCursor(adapter, itemCursor); - loadFeedDataOfFeedItemlist(context, result); + loadFeedDataOfFeedItemlist(result); for(FeedItem item : result) { if (item.hasChapters()) { loadChaptersOfFeedItem(adapter, item); @@ -769,23 +574,21 @@ public final class DBReader { * Loads a specific FeedItem from the database. This method should not be used for loading more * than one FeedItem because this method might query the database several times for each item. * - * @param context A context that is used for opening a database connection. * @param itemId The ID of the FeedItem * @return The FeedItem or null if the FeedItem could not be found. All FeedComponent-attributes * as well as chapter marks of the FeedItem will also be loaded from the database. */ - public static FeedItem getFeedItem(final Context context, final long itemId) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Loading feeditem with id " + itemId); + public static FeedItem getFeedItem(final long itemId) { + Log.d(TAG, "Loading feeditem with id " + itemId); - PodDBAdapter adapter = new PodDBAdapter(context); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - FeedItem item = getFeedItem(context, itemId, adapter); + FeedItem item = getFeedItem(itemId, adapter); adapter.close(); return item; } - static FeedItem getFeedItem(final Context context, final String podcastUrl, final String episodeUrl, PodDBAdapter adapter) { + static FeedItem getFeedItem(final String podcastUrl, final String episodeUrl, PodDBAdapter adapter) { Log.d(TAG, "Loading feeditem with podcast url " + podcastUrl + " and episode url " + episodeUrl); FeedItem item = null; Cursor itemCursor = adapter.getFeedItemCursor(podcastUrl, episodeUrl); @@ -793,7 +596,7 @@ public final class DBReader { List list = extractItemlistFromCursor(adapter, itemCursor); if (list.size() > 0) { item = list.get(0); - loadFeedDataOfFeedItemlist(context, list); + loadFeedDataOfFeedItemlist(list); if (item.hasChapters()) { loadChaptersOfFeedItem(adapter, item); } @@ -807,17 +610,16 @@ public final class DBReader { * Loads specific FeedItems from the database. This method canbe used for loading more * than one FeedItem * - * @param context A context that is used for opening a database connection. * @param itemIds The IDs of the FeedItems * @return The FeedItems or an empty list if none of the FeedItems could be found. All FeedComponent-attributes * as well as chapter marks of the FeedItems will also be loaded from the database. */ - public static List getFeedItems(final Context context, final long... itemIds) { + public static List getFeedItems(final long... itemIds) { Log.d(TAG, "Loading feeditem with ids: " + StringUtils.join(itemIds, ",")); - PodDBAdapter adapter = new PodDBAdapter(context); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - List items = getFeedItems(context, adapter, itemIds); + List items = getFeedItems(adapter, itemIds); adapter.close(); return items; } @@ -826,22 +628,21 @@ public final class DBReader { /** * Returns credentials based on image URL * - * @param context A context that is used for opening a database connection. * @param imageUrl The URL of the image * @return Credentials in format ":", empty String if no authorization given */ - public static String getImageAuthentication(final Context context, final String imageUrl) { + public static String getImageAuthentication(final String imageUrl) { Log.d(TAG, "Loading credentials for image with URL " + imageUrl); - PodDBAdapter adapter = new PodDBAdapter(context); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - String credentials = getImageAuthentication(context, imageUrl, adapter); + String credentials = getImageAuthentication(imageUrl, adapter); adapter.close(); return credentials; } - static String getImageAuthentication(final Context context, final String imageUrl, PodDBAdapter adapter) { + static String getImageAuthentication(final String imageUrl, PodDBAdapter adapter) { String credentials = null; Cursor cursor = adapter.getImageAuthenticationCursor(imageUrl); try { @@ -849,32 +650,33 @@ public final class DBReader { String username = cursor.getString(0); String password = cursor.getString(1); if(username != null && password != null) { - return username + ":" + password; + credentials = username + ":" + password; } else { - return ""; + credentials = ""; } + } else { + credentials = ""; } - return ""; } finally { cursor.close(); } + return credentials; } /** * Loads a specific FeedItem from the database. * - * @param context A context that is used for opening a database connection. * @param podcastUrl the corresponding feed's url * @param episodeUrl the feed item's url * @return The FeedItem or null if the FeedItem could not be found. All FeedComponent-attributes * as well as chapter marks of the FeedItem will also be loaded from the database. */ - public static FeedItem getFeedItem(final Context context, final String podcastUrl, final String episodeUrl) { + public static FeedItem getFeedItem(final String podcastUrl, final String episodeUrl) { Log.d(TAG, "Loading feeditem with podcast url " + podcastUrl + " and episode url " + episodeUrl); - PodDBAdapter adapter = new PodDBAdapter(context); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - FeedItem item = getFeedItem(context, podcastUrl, episodeUrl, adapter); + FeedItem item = getFeedItem(podcastUrl, episodeUrl, adapter); adapter.close(); return item; } @@ -882,18 +684,17 @@ public final class DBReader { /** * Loads additional information about a FeedItem, e.g. shownotes * - * @param context A context that is used for opening a database connection. * @param item The FeedItem */ - public static void loadExtraInformationOfFeedItem(final Context context, final FeedItem item) { - PodDBAdapter adapter = new PodDBAdapter(context); + public static void loadExtraInformationOfFeedItem(final FeedItem item) { + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor extraCursor = adapter.getExtraInformationOfItem(item); if (extraCursor.moveToFirst()) { - String description = extraCursor - .getString(PodDBAdapter.IDX_FI_EXTRA_DESCRIPTION); - String contentEncoded = extraCursor - .getString(PodDBAdapter.IDX_FI_EXTRA_CONTENT_ENCODED); + int indexDescription = extraCursor.getColumnIndex(PodDBAdapter.KEY_DESCRIPTION); + String description = extraCursor.getString(indexDescription); + int indexContentEncoded = extraCursor.getColumnIndex(PodDBAdapter.KEY_CONTENT_ENCODED); + String contentEncoded = extraCursor.getString(indexContentEncoded); item.setDescription(description); item.setContentEncoded(contentEncoded); } @@ -906,31 +707,30 @@ public final class DBReader { * any chapters that this FeedItem has. If no chapters were found in the database, the chapters * reference of the FeedItem will be set to null. * - * @param context A context that is used for opening a database connection. * @param item The FeedItem */ - public static void loadChaptersOfFeedItem(final Context context, final FeedItem item) { - PodDBAdapter adapter = new PodDBAdapter(context); + public static void loadChaptersOfFeedItem(final FeedItem item) { + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); loadChaptersOfFeedItem(adapter, item); adapter.close(); } static void loadChaptersOfFeedItem(PodDBAdapter adapter, FeedItem item) { - Cursor chapterCursor = adapter - .getSimpleChaptersOfFeedItemCursor(item); + Cursor chapterCursor = adapter.getSimpleChaptersOfFeedItemCursor(item); if (chapterCursor.moveToFirst()) { - item.setChapters(new ArrayList()); + item.setChapters(new ArrayList<>()); do { - int chapterType = chapterCursor - .getInt(PodDBAdapter.KEY_CHAPTER_TYPE_INDEX); + int indexType = chapterCursor.getColumnIndex(PodDBAdapter.KEY_CHAPTER_TYPE); + int indexStart = chapterCursor.getColumnIndex(PodDBAdapter.KEY_START); + int indexTitle = chapterCursor.getColumnIndex(PodDBAdapter.KEY_TITLE); + int indexLink = chapterCursor.getColumnIndex(PodDBAdapter.KEY_LINK); + + int chapterType = chapterCursor.getInt(indexType); Chapter chapter = null; - long start = chapterCursor - .getLong(PodDBAdapter.KEY_CHAPTER_START_INDEX); - String title = chapterCursor - .getString(PodDBAdapter.KEY_TITLE_INDEX); - String link = chapterCursor - .getString(PodDBAdapter.KEY_CHAPTER_LINK_INDEX); + long start = chapterCursor.getLong(indexStart); + String title = chapterCursor.getString(indexTitle); + String link = chapterCursor.getString(indexLink); switch (chapterType) { case SimpleChapter.CHAPTERTYPE_SIMPLECHAPTER: @@ -947,8 +747,8 @@ public final class DBReader { break; } if (chapter != null) { - chapter.setId(chapterCursor - .getLong(PodDBAdapter.KEY_ID_INDEX)); + int indexId = chapterCursor.getColumnIndex(PodDBAdapter.KEY_ID); + chapter.setId(chapterCursor.getLong(indexId)); item.getChapters().add(chapter); } } while (chapterCursor.moveToNext()); @@ -961,40 +761,24 @@ public final class DBReader { /** * Returns the number of downloaded episodes. * - * @param context A context that is used for opening a database connection. * @return The number of downloaded episodes. */ - public static int getNumberOfDownloadedEpisodes(final Context context) { - PodDBAdapter adapter = new PodDBAdapter(context); + public static int getNumberOfDownloadedEpisodes() { + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); final int result = adapter.getNumberOfDownloadedEpisodes(); adapter.close(); return result; } - /** - * Returns the number of unread items. - * - * @param context A context that is used for opening a database connection. - * @return The number of unread items. - */ - public static int getNumberOfNewItems(final Context context) { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - final int result = adapter.getNumberOfNewItems(); - adapter.close(); - return result; - } - /** * Searches the DB for a FeedImage of the given id. * - * @param context A context that is used for opening a database connection. * @param imageId The id of the object * @return The found object */ - public static FeedImage getFeedImage(final Context context, final long imageId) { - PodDBAdapter adapter = new PodDBAdapter(context); + public static FeedImage getFeedImage(final long imageId) { + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); FeedImage result = getFeedImage(adapter, imageId); adapter.close(); @@ -1012,15 +796,8 @@ public final class DBReader { if ((cursor.getCount() == 0) || !cursor.moveToFirst()) { return null; } - FeedImage image = new FeedImage(id, cursor.getString(cursor - .getColumnIndex(PodDBAdapter.KEY_TITLE)), - cursor.getString(cursor - .getColumnIndex(PodDBAdapter.KEY_FILE_URL)), - cursor.getString(cursor - .getColumnIndex(PodDBAdapter.KEY_DOWNLOAD_URL)), - cursor.getInt(cursor - .getColumnIndex(PodDBAdapter.KEY_DOWNLOADED)) > 0 - ); + FeedImage image = FeedImage.fromCursor(cursor); + image.setId(id); cursor.close(); return image; } @@ -1028,21 +805,21 @@ public final class DBReader { /** * Searches the DB for a FeedMedia of the given id. * - * @param context A context that is used for opening a database connection. * @param mediaId The id of the object * @return The found object */ - public static FeedMedia getFeedMedia(final Context context, final long mediaId) { - PodDBAdapter adapter = new PodDBAdapter(context); + public static FeedMedia getFeedMedia(final long mediaId) { + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor mediaCursor = adapter.getSingleFeedMediaCursor(mediaId); FeedMedia media = null; if (mediaCursor.moveToFirst()) { - final long itemId = mediaCursor.getLong(PodDBAdapter.KEY_MEDIA_FEEDITEM_INDEX); - media = extractFeedMediaFromCursorRow(mediaCursor); - FeedItem item = getFeedItem(context, itemId); + int indexFeedItem = mediaCursor.getColumnIndex(PodDBAdapter.KEY_FEEDITEM); + final long itemId = mediaCursor.getLong(indexFeedItem); + media = FeedMedia.fromCursor(mediaCursor); + FeedItem item = getFeedItem(itemId); if (media != null && item != null) { media.setItem(item); item.setMedia(media); @@ -1058,13 +835,12 @@ public final class DBReader { /** * Returns the flattr queue as a List of FlattrThings. The list consists of Feeds and FeedItems. * - * @param context A context that is used for opening a database connection. * @return The flattr queue as a List. */ - public static List getFlattrQueue(Context context) { - PodDBAdapter adapter = new PodDBAdapter(context); + public static List getFlattrQueue() { + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - List result = new ArrayList(); + List result = new ArrayList<>(); // load feeds Cursor feedCursor = adapter.getFeedsInFlattrQueueCursor(); @@ -1085,29 +861,14 @@ public final class DBReader { return result; } - - /** - * Returns true if the flattr queue is empty. - * - * @param context A context that is used for opening a database connection. - */ - public static boolean getFlattrQueueEmpty(Context context) { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - boolean empty = adapter.getFlattrQueueSize() == 0; - adapter.close(); - return empty; - } - /** * Returns data necessary for displaying the navigation drawer. This includes * the list of subscriptions, the number of items in the queue and the number of unread * items. * - * @param context A context that is used for opening a database connection. */ - public static NavDrawerData getNavDrawerData(Context context) { - PodDBAdapter adapter = new PodDBAdapter(context); + public static NavDrawerData getNavDrawerData() { + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); List feeds = getFeedList(adapter); long[] feedIds = new long[feeds.size()]; @@ -1119,30 +880,24 @@ public final class DBReader { Comparator comparator; int feedOrder = UserPreferences.getFeedOrder(); if(feedOrder == UserPreferences.FEED_ORDER_COUNTER) { - comparator = new Comparator() { - @Override - public int compare(Feed lhs, Feed rhs) { - long counterLhs = feedCounters.get(lhs.getId()); - long counterRhs = feedCounters.get(rhs.getId()); - if(counterLhs > counterRhs) { - // reverse natural order: podcast with most unplayed episodes first - return -1; - } else if(counterLhs == counterRhs) { - return lhs.getTitle().compareTo(rhs.getTitle()); - } else { - return 1; - } + comparator = (lhs, rhs) -> { + long counterLhs = feedCounters.get(lhs.getId()); + long counterRhs = feedCounters.get(rhs.getId()); + if(counterLhs > counterRhs) { + // reverse natural order: podcast with most unplayed episodes first + return -1; + } else if(counterLhs == counterRhs) { + return lhs.getTitle().compareTo(rhs.getTitle()); + } else { + return 1; } }; } else { - comparator = new Comparator() { - @Override - public int compare(Feed lhs, Feed rhs) { - if(lhs.getTitle() == null) { - return 1; - } - return lhs.getTitle().compareTo(rhs.getTitle()); + comparator = (lhs, rhs) -> { + if(lhs.getTitle() == null) { + return 1; } + return lhs.getTitle().compareTo(rhs.getTitle()); }; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index 6ed99ec41..96a632d68 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -68,7 +68,7 @@ public final class DBTasks { * @param downloadUrl URL of the feed. */ public static void removeFeedWithDownloadUrl(Context context, String downloadUrl) { - PodDBAdapter adapter = new PodDBAdapter(context); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); Cursor cursor = adapter.getFeedCursorDownloadUrls(); long feedID = 0; @@ -163,7 +163,7 @@ public final class DBTasks { if (feeds != null) { refreshFeeds(context, feeds); } else { - refreshFeeds(context, DBReader.getFeedList(context)); + refreshFeeds(context, DBReader.getFeedList()); } isRefreshing.set(false); @@ -196,7 +196,6 @@ public final class DBTasks { } catch (DownloadRequestException e) { e.printStackTrace(); DBWriter.addDownloadStatus( - context, new DownloadStatus(feed, feed .getHumanReadableIdentifier(), DownloadError.ERROR_REQUEST_ERROR, false, e @@ -220,7 +219,6 @@ public final class DBTasks { } catch (DownloadRequestException e) { e.printStackTrace(); DBWriter.addDownloadStatus( - context, new DownloadStatus(feed, feed .getHumanReadableIdentifier(), DownloadError.ERROR_REQUEST_ERROR, false, e @@ -287,7 +285,7 @@ public final class DBTasks { "The feedmanager was notified about a missing episode. It will update its database now."); media.setDownloaded(false); media.setFile_url(null); - DBWriter.setFeedMedia(context, media); + DBWriter.setFeedMedia(media); EventDistributor.getInstance().sendFeedUpdateBroadcast(); } @@ -299,7 +297,7 @@ public final class DBTasks { public static void downloadAllItemsInQueue(final Context context) { new Thread() { public void run() { - List queue = DBReader.getQueue(context); + List queue = DBReader.getQueue(); if (!queue.isEmpty()) { try { downloadFeedItems(context, @@ -336,7 +334,7 @@ public final class DBTasks { ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm() .performCleanup(context, ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm() - .getPerformCleanupParameter(context, Arrays.asList(items))); + .getPerformCleanupParameter(Arrays.asList(items))); } }.start(); @@ -350,7 +348,7 @@ public final class DBTasks { requester.downloadMedia(context, item.getMedia()); } catch (DownloadRequestException e) { e.printStackTrace(); - DBWriter.addDownloadStatus(context, + DBWriter.addDownloadStatus( new DownloadStatus(item.getMedia(), item .getMedia() .getHumanReadableIdentifier(), @@ -393,7 +391,7 @@ public final class DBTasks { */ public static void performAutoCleanup(final Context context) { ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm().performCleanup(context, - ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm().getDefaultCleanupParameter(context)); + ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm().getDefaultCleanupParameter()); } /** @@ -409,7 +407,7 @@ public final class DBTasks { final long itemId, List queue) { FeedItem result = null; if (queue == null) { - queue = DBReader.getQueue(context); + queue = DBReader.getQueue(); } if (queue != null) { Iterator iterator = queue.iterator(); @@ -434,19 +432,19 @@ public final class DBTasks { * @param feedItemId ID of the FeedItem */ public static boolean isInQueue(Context context, final long feedItemId) { - LongList queue = DBReader.getQueueIDList(context); + LongList queue = DBReader.getQueueIDList(); return queue.contains(feedItemId); } private static Feed searchFeedByIdentifyingValueOrID(Context context, PodDBAdapter adapter, Feed feed) { if (feed.getId() != 0) { - return DBReader.getFeed(context, feed.getId(), adapter); + return DBReader.getFeed(feed.getId(), adapter); } else { - List feeds = DBReader.getFeedList(context); + List feeds = DBReader.getFeedList(); for (Feed f : feeds) { if (f.getIdentifyingValue().equals(feed.getIdentifyingValue())) { - f.setItems(DBReader.getFeedItemList(context, f)); + f.setItems(DBReader.getFeedItemList(f)); return f; } } @@ -485,7 +483,7 @@ public final class DBTasks { List newFeedsList = new ArrayList(); List updatedFeedsList = new ArrayList(); Feed[] resultFeeds = new Feed[newFeeds.length]; - PodDBAdapter adapter = new PodDBAdapter(context); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); for (int feedIdx = 0; feedIdx < newFeeds.length; feedIdx++) { @@ -574,7 +572,7 @@ public final class DBTasks { try { DBWriter.addNewFeed(context, newFeedsList.toArray(new Feed[newFeedsList.size()])).get(); - DBWriter.setCompleteFeed(context, updatedFeedsList.toArray(new Feed[updatedFeedsList.size()])).get(); + DBWriter.setCompleteFeed(updatedFeedsList.toArray(new Feed[updatedFeedsList.size()])).get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { @@ -602,8 +600,8 @@ public final class DBTasks { public void execute(PodDBAdapter adapter) { Cursor searchResult = adapter.searchItemTitles(feedID, query); - List items = DBReader.extractItemlistFromCursor(context, searchResult); - DBReader.loadFeedDataOfFeedItemlist(context, items); + List items = DBReader.extractItemlistFromCursor(searchResult); + DBReader.loadFeedDataOfFeedItemlist(items); setResult(items); searchResult.close(); } @@ -626,8 +624,8 @@ public final class DBTasks { public void execute(PodDBAdapter adapter) { Cursor searchResult = adapter.searchItemDescriptions(feedID, query); - List items = DBReader.extractItemlistFromCursor(context, searchResult); - DBReader.loadFeedDataOfFeedItemlist(context, items); + List items = DBReader.extractItemlistFromCursor(searchResult); + DBReader.loadFeedDataOfFeedItemlist(items); setResult(items); searchResult.close(); } @@ -650,8 +648,8 @@ public final class DBTasks { public void execute(PodDBAdapter adapter) { Cursor searchResult = adapter.searchItemContentEncoded(feedID, query); - List items = DBReader.extractItemlistFromCursor(context, searchResult); - DBReader.loadFeedDataOfFeedItemlist(context, items); + List items = DBReader.extractItemlistFromCursor(searchResult); + DBReader.loadFeedDataOfFeedItemlist(items); setResult(items); searchResult.close(); } @@ -673,8 +671,8 @@ public final class DBTasks { public void execute(PodDBAdapter adapter) { Cursor searchResult = adapter.searchItemChapters(feedID, query); - List items = DBReader.extractItemlistFromCursor(context, searchResult); - DBReader.loadFeedDataOfFeedItemlist(context, items); + List items = DBReader.extractItemlistFromCursor(searchResult); + DBReader.loadFeedDataOfFeedItemlist(items); setResult(items); searchResult.close(); } @@ -697,7 +695,7 @@ public final class DBTasks { @Override public T call() throws Exception { - PodDBAdapter adapter = new PodDBAdapter(context); + PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); execute(adapter); adapter.close(); 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 0f7065c59..521f960ec 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 @@ -22,7 +22,6 @@ import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; -import java.util.concurrent.ThreadFactory; import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.ClientConfig; @@ -56,19 +55,16 @@ import de.greenrobot.event.EventBus; * This class will use the {@link EventDistributor} to notify listeners about changes in the database. */ public class DBWriter { + private static final String TAG = "DBWriter"; private static final ExecutorService dbExec; static { - dbExec = Executors.newSingleThreadExecutor(new ThreadFactory() { - - @Override - public Thread newThread(Runnable r) { - Thread t = new Thread(r); - t.setPriority(Thread.MIN_PRIORITY); - return t; - } + dbExec = Executors.newSingleThreadExecutor(r -> { + Thread t = new Thread(r); + t.setPriority(Thread.MIN_PRIORITY); + return t; }); } @@ -83,63 +79,59 @@ public class DBWriter { */ public static Future deleteFeedMediaOfItem(final Context context, final long mediaId) { - return dbExec.submit(new Runnable() { - @Override - public void run() { - - final FeedMedia media = DBReader.getFeedMedia(context, mediaId); - if (media != null) { - Log.i(TAG, String.format("Requested to delete FeedMedia [id=%d, title=%s, downloaded=%s", - media.getId(), media.getEpisodeTitle(), String.valueOf(media.isDownloaded()))); - boolean result = false; - if (media.isDownloaded()) { - // delete downloaded media file - File mediaFile = new File(media.getFile_url()); - if (mediaFile.exists()) { - result = mediaFile.delete(); - } - media.setDownloaded(false); - media.setFile_url(null); - media.setHasEmbeddedPicture(false); - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setMedia(media); - adapter.close(); - - // If media is currently being played, change playback - // type to 'stream' and shutdown playback service - SharedPreferences prefs = PreferenceManager - .getDefaultSharedPreferences(context); - if (PlaybackPreferences.getCurrentlyPlayingMedia() == FeedMedia.PLAYABLE_TYPE_FEEDMEDIA) { - if (media.getId() == PlaybackPreferences - .getCurrentlyPlayingFeedMediaId()) { - SharedPreferences.Editor editor = prefs.edit(); - editor.putBoolean( - PlaybackPreferences.PREF_CURRENT_EPISODE_IS_STREAM, - true); - editor.commit(); - } - if (PlaybackPreferences - .getCurrentlyPlayingFeedMediaId() == media - .getId()) { - context.sendBroadcast(new Intent( - PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE)); - } + return dbExec.submit(() -> { + final FeedMedia media = DBReader.getFeedMedia(mediaId); + if (media != null) { + Log.i(TAG, String.format("Requested to delete FeedMedia [id=%d, title=%s, downloaded=%s", + media.getId(), media.getEpisodeTitle(), String.valueOf(media.isDownloaded()))); + boolean result = false; + if (media.isDownloaded()) { + // delete downloaded media file + File mediaFile = new File(media.getFile_url()); + if (mediaFile.exists()) { + result = mediaFile.delete(); + } + media.setDownloaded(false); + media.setFile_url(null); + media.setHasEmbeddedPicture(false); + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setMedia(media); + adapter.close(); + + // If media is currently being played, change playback + // type to 'stream' and shutdown playback service + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(context); + if (PlaybackPreferences.getCurrentlyPlayingMedia() == FeedMedia.PLAYABLE_TYPE_FEEDMEDIA) { + if (media.getId() == PlaybackPreferences + .getCurrentlyPlayingFeedMediaId()) { + SharedPreferences.Editor editor = prefs.edit(); + editor.putBoolean( + PlaybackPreferences.PREF_CURRENT_EPISODE_IS_STREAM, + true); + editor.commit(); } - // Gpodder: queue delete action for synchronization - if(GpodnetPreferences.loggedIn()) { - FeedItem item = media.getItem(); - GpodnetEpisodeAction action = new GpodnetEpisodeAction.Builder(item, GpodnetEpisodeAction.Action.DELETE) - .currentDeviceId() - .currentTimestamp() - .build(); - GpodnetPreferences.enqueueEpisodeAction(action); + if (PlaybackPreferences + .getCurrentlyPlayingFeedMediaId() == media + .getId()) { + context.sendBroadcast(new Intent( + PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE)); } } - Log.d(TAG, "Deleting File. Result: " + result); - EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.DELETED_MEDIA, media.getItem())); - EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + // Gpodder: queue delete action for synchronization + if(GpodnetPreferences.loggedIn()) { + FeedItem item = media.getItem(); + GpodnetEpisodeAction action = new GpodnetEpisodeAction.Builder(item, GpodnetEpisodeAction.Action.DELETE) + .currentDeviceId() + .currentTimestamp() + .build(); + GpodnetPreferences.enqueueEpisodeAction(action); + } } + Log.d(TAG, "Deleting File. Result: " + result); + EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.DELETED_MEDIA, media.getItem())); + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); } }); } @@ -151,87 +143,85 @@ public class DBWriter { * @param feedId ID of the Feed that should be deleted. */ public static Future deleteFeed(final Context context, final long feedId) { - return dbExec.submit(new Runnable() { - @Override - public void run() { - DownloadRequester requester = DownloadRequester.getInstance(); - SharedPreferences prefs = PreferenceManager - .getDefaultSharedPreferences(context - .getApplicationContext()); - final Feed feed = DBReader.getFeed(context, feedId); - if (feed != null) { - if (PlaybackPreferences.getCurrentlyPlayingMedia() == FeedMedia.PLAYABLE_TYPE_FEEDMEDIA - && PlaybackPreferences.getLastPlayedFeedId() == feed - .getId()) { - context.sendBroadcast(new Intent( - PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE)); - SharedPreferences.Editor editor = prefs.edit(); - editor.putLong( - PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID, - -1); - editor.commit(); - } + return dbExec.submit(() -> { + DownloadRequester requester = DownloadRequester.getInstance(); + SharedPreferences prefs = PreferenceManager + .getDefaultSharedPreferences(context + .getApplicationContext()); + final Feed feed = DBReader.getFeed(feedId); + + if (feed != null) { + if (PlaybackPreferences.getCurrentlyPlayingMedia() == FeedMedia.PLAYABLE_TYPE_FEEDMEDIA + && PlaybackPreferences.getLastPlayedFeedId() == feed + .getId()) { + context.sendBroadcast(new Intent( + PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE)); + SharedPreferences.Editor editor = prefs.edit(); + editor.putLong( + PlaybackPreferences.PREF_CURRENTLY_PLAYING_FEED_ID, + -1); + editor.commit(); + } - // delete image file - if (feed.getImage() != null) { - if (feed.getImage().isDownloaded() - && feed.getImage().getFile_url() != null) { - File imageFile = new File(feed.getImage() - .getFile_url()); - imageFile.delete(); - } else if (requester.isDownloadingFile(feed.getImage())) { - requester.cancelDownload(context, feed.getImage()); - } - } - // delete stored media files and mark them as read - List queue = DBReader.getQueue(context); - List removed = new ArrayList<>(); - if (feed.getItems() == null) { - DBReader.getFeedItemList(context, feed); + // delete image file + if (feed.getImage() != null) { + if (feed.getImage().isDownloaded() + && feed.getImage().getFile_url() != null) { + File imageFile = new File(feed.getImage() + .getFile_url()); + imageFile.delete(); + } else if (requester.isDownloadingFile(feed.getImage())) { + requester.cancelDownload(context, feed.getImage()); } + } + // delete stored media files and mark them as read + List queue = DBReader.getQueue(); + List removed = new ArrayList<>(); + if (feed.getItems() == null) { + DBReader.getFeedItemList(feed); + } - for (FeedItem item : feed.getItems()) { - if(queue.remove(item)) { - removed.add(item); - } - if (item.getMedia() != null - && item.getMedia().isDownloaded()) { - File mediaFile = new File(item.getMedia() - .getFile_url()); - mediaFile.delete(); - } else if (item.getMedia() != null - && requester.isDownloadingFile(item.getMedia())) { - requester.cancelDownload(context, item.getMedia()); - } - - if (item.hasItemImage()) { - FeedImage image = item.getImage(); - if (image.isDownloaded() && image.getFile_url() != null) { - File imgFile = new File(image.getFile_url()); - imgFile.delete(); - } else if (requester.isDownloadingFile(image)) { - requester.cancelDownload(context, item.getImage()); - } - } + for (FeedItem item : feed.getItems()) { + if(queue.remove(item)) { + removed.add(item); } - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - if (removed.size() > 0) { - adapter.setQueue(queue); - EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.IRREVERSIBLE_REMOVED, - removed)); + if (item.getMedia() != null + && item.getMedia().isDownloaded()) { + File mediaFile = new File(item.getMedia() + .getFile_url()); + mediaFile.delete(); + } else if (item.getMedia() != null + && requester.isDownloadingFile(item.getMedia())) { + requester.cancelDownload(context, item.getMedia()); } - adapter.removeFeed(feed); - adapter.close(); - if (ClientConfig.gpodnetCallbacks.gpodnetEnabled()) { - GpodnetPreferences.addRemovedFeed(feed.getDownload_url()); + if (item.hasItemImage()) { + FeedImage image = item.getImage(); + if (image.isDownloaded() && image.getFile_url() != null) { + File imgFile = new File(image.getFile_url()); + imgFile.delete(); + } else if (requester.isDownloadingFile(image)) { + requester.cancelDownload(context, item.getImage()); + } } - EventDistributor.getInstance().sendFeedUpdateBroadcast(); + } + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + if (removed.size() > 0) { + adapter.setQueue(queue); + EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.IRREVERSIBLE_REMOVED, + removed)); + } + adapter.removeFeed(feed); + adapter.close(); - BackupManager backupManager = new BackupManager(context); - backupManager.dataChanged(); + if (ClientConfig.gpodnetCallbacks.gpodnetEnabled()) { + GpodnetPreferences.addRemovedFeed(feed.getDownload_url()); } + EventDistributor.getInstance().sendFeedUpdateBroadcast(); + + BackupManager backupManager = new BackupManager(context); + backupManager.dataChanged(); } }); } @@ -239,39 +229,27 @@ public class DBWriter { /** * Deletes the entire playback history. * - * @param context A context that is used for opening a database connection. */ - public static Future clearPlaybackHistory(final Context context) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.clearPlaybackHistory(); - adapter.close(); - EventDistributor.getInstance() - .sendPlaybackHistoryUpdateBroadcast(); - } + public static Future clearPlaybackHistory() { + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.clearPlaybackHistory(); + adapter.close(); + EventDistributor.getInstance().sendPlaybackHistoryUpdateBroadcast(); }); } /** * Deletes the entire download log. - * - * @param context A context that is used for opening a database connection. */ - public static Future clearDownloadLog(final Context context) { - return dbExec.submit(new Runnable() { - @Override - public void run() { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.clearDownloadLog(); - adapter.close(); - EventDistributor.getInstance() - .sendDownloadLogUpdateBroadcast(); - } + public static Future clearDownloadLog() { + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.clearDownloadLog(); + adapter.close(); + EventDistributor.getInstance().sendDownloadLogUpdateBroadcast(); }); } @@ -281,58 +259,36 @@ public class DBWriter { * its playback completion date is set to a non-null value. This method will set the playback completion date to the * current date regardless of the current value. * - * @param context A context that is used for opening a database connection. * @param media FeedMedia that should be added to the playback history. */ - public static Future addItemToPlaybackHistory(final Context context, - final FeedMedia media) { - return dbExec.submit(new Runnable() { - @Override - public void run() { - if (BuildConfig.DEBUG) - Log.d(TAG, "Adding new item to playback history"); - media.setPlaybackCompletionDate(new Date()); - // reset played_duration to 0 so that it behaves correctly when the episode is played again - media.setPlayedDuration(0); + public static Future addItemToPlaybackHistory(final FeedMedia media) { + return dbExec.submit(() -> { + Log.d(TAG, "Adding new item to playback history"); + media.setPlaybackCompletionDate(new Date()); + // reset played_duration to 0 so that it behaves correctly when the episode is played again + media.setPlayedDuration(0); - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setFeedMediaPlaybackCompletionDate(media); - adapter.close(); - EventDistributor.getInstance().sendPlaybackHistoryUpdateBroadcast(); + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setFeedMediaPlaybackCompletionDate(media); + adapter.close(); + EventDistributor.getInstance().sendPlaybackHistoryUpdateBroadcast(); - } }); } - private static void cleanupDownloadLog(final PodDBAdapter adapter) { - final long logSize = adapter.getDownloadLogSize(); - if (logSize > DBReader.DOWNLOAD_LOG_SIZE) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Cleaning up download log"); - adapter.removeDownloadLogItems(logSize - DBReader.DOWNLOAD_LOG_SIZE); - } - } - /** * Adds a Download status object to the download log. * - * @param context A context that is used for opening a database connection. * @param status The DownloadStatus object. */ - public static Future addDownloadStatus(final Context context, - final DownloadStatus status) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setDownloadStatus(status); - adapter.close(); - EventDistributor.getInstance().sendDownloadLogUpdateBroadcast(); - } + public static Future addDownloadStatus(final DownloadStatus status) { + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setDownloadStatus(status); + adapter.close(); + EventDistributor.getInstance().sendDownloadLogUpdateBroadcast(); }); } @@ -349,35 +305,31 @@ public class DBWriter { */ public static Future addQueueItemAt(final Context context, final long itemId, final int index, final boolean performAutoDownload) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - final PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - final List queue = DBReader.getQueue(context, adapter); - FeedItem item; - - if (queue != null) { - if (!itemListContains(queue, itemId)) { - item = DBReader.getFeedItem(context, itemId); - if (item != null) { - queue.add(index, item); - adapter.setQueue(queue); - EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED, item, index)); - if(item.isNew()) { - DBWriter.markItemPlayed(context, FeedItem.UNPLAYED, item.getId()); - } + return dbExec.submit(() -> { + final PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + final List queue = DBReader.getQueue(adapter); + FeedItem item; + + if (queue != null) { + if (!itemListContains(queue, itemId)) { + item = DBReader.getFeedItem(itemId); + if (item != null) { + queue.add(index, item); + adapter.setQueue(queue); + EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED, item, index)); + if (item.isNew()) { + DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId()); } } } + } - adapter.close(); - if (performAutoDownload) { - DBTasks.autodownloadUndownloadedItems(context); - } - + adapter.close(); + if (performAutoDownload) { + DBTasks.autodownloadUndownloadedItems(context); } + }); } @@ -397,50 +349,46 @@ public class DBWriter { */ public static Future addQueueItem(final Context context, final boolean performAutoDownload, final long... itemIds) { - return dbExec.submit(new Runnable() { + return dbExec.submit(() -> { + if (itemIds.length > 0) { + final PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + final List queue = DBReader.getQueue(adapter); - @Override - public void run() { - if (itemIds.length > 0) { - final PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - final List queue = DBReader.getQueue(context, adapter); - - if (queue != null) { - boolean queueModified = false; - LongList markAsUnplayedIds = new LongList(); - for (int i = 0; i < itemIds.length; i++) { - if (!itemListContains(queue, itemIds[i])) { - final FeedItem item = DBReader.getFeedItem(context, itemIds[i]); - - if (item != null) { - // add item to either front ot back of queue - boolean addToFront = UserPreferences.enqueueAtFront(); - if (addToFront) { - queue.add(0 + i, item); - } else { - queue.add(item); - } - queueModified = true; - if(item.isNew()) { - markAsUnplayedIds.add(item.getId()); - } + if (queue != null) { + boolean queueModified = false; + LongList markAsUnplayedIds = new LongList(); + for (int i = 0; i < itemIds.length; i++) { + if (!itemListContains(queue, itemIds[i])) { + final FeedItem item = DBReader.getFeedItem(itemIds[i]); + + if (item != null) { + // add item to either front ot back of queue + boolean addToFront = UserPreferences.enqueueAtFront(); + if (addToFront) { + queue.add(0 + i, item); + } else { + queue.add(item); + } + queueModified = true; + if(item.isNew()) { + markAsUnplayedIds.add(item.getId()); } - } - } - if (queueModified) { - adapter.setQueue(queue); - EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED_ITEMS, queue)); - if(markAsUnplayedIds.size() > 0) { - DBWriter.markItemPlayed(context, FeedItem.UNPLAYED, markAsUnplayedIds.toArray()); } } } - adapter.close(); - if (performAutoDownload) { - DBTasks.autodownloadUndownloadedItems(context); + if (queueModified) { + adapter.setQueue(queue); + EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED_ITEMS, queue)); + if(markAsUnplayedIds.size() > 0) { + DBWriter.markItemPlayed(FeedItem.UNPLAYED, markAsUnplayedIds.toArray()); + } } } + adapter.close(); + if (performAutoDownload) { + DBTasks.autodownloadUndownloadedItems(context); + } } }); } @@ -448,20 +396,15 @@ public class DBWriter { /** * Removes all FeedItem objects from the queue. * - * @param context A context that is used for opening a database connection. */ - public static Future clearQueue(final Context context) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.clearQueue(); - adapter.close(); + public static Future clearQueue() { + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.clearQueue(); + adapter.close(); - EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.CLEARED)); - } + EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.CLEARED)); }); } @@ -474,30 +417,26 @@ public class DBWriter { */ public static Future removeQueueItem(final Context context, final FeedItem item, final boolean performAutoDownload) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - final PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - final List queue = DBReader.getQueue(context, adapter); + return dbExec.submit(() -> { + final PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + final List queue = DBReader.getQueue(adapter); - if (queue != null) { - int position = queue.indexOf(item); - if(position >= 0) { - queue.remove(position); - adapter.setQueue(queue); - EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.REMOVED, item, position)); - } else { - Log.w(TAG, "Queue was not modified by call to removeQueueItem"); - } + if (queue != null) { + int position = queue.indexOf(item); + if(position >= 0) { + queue.remove(position); + adapter.setQueue(queue); + EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.REMOVED, item, position)); } else { - Log.e(TAG, "removeQueueItem: Could not load queue"); - } - adapter.close(); - if (performAutoDownload) { - DBTasks.autodownloadUndownloadedItems(context); + Log.w(TAG, "Queue was not modified by call to removeQueueItem"); } + } else { + Log.e(TAG, "removeQueueItem: Could not load queue"); + } + adapter.close(); + if (performAutoDownload) { + DBTasks.autodownloadUndownloadedItems(context); } }); @@ -505,48 +444,36 @@ public class DBWriter { /** * Moves the specified item to the top of the queue. - * - * @param context A context that is used for opening a database connection. - * @param itemId The item to move to the top of the queue + * @param itemId The item to move to the top of the queue * @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to - * false if the caller wants to avoid unexpected updates of the GUI. */ - public static Future moveQueueItemToTop(final Context context, final long itemId, final boolean broadcastUpdate) { - return dbExec.submit(new Runnable() { - @Override - public void run() { - LongList queueIdList = DBReader.getQueueIDList(context); - int index = queueIdList.indexOf(itemId); - if (index >=0) { - moveQueueItemHelper(context, index, 0, broadcastUpdate); - } else { - Log.e(TAG, "moveQueueItemToTop: item not found"); - } + public static Future moveQueueItemToTop(final long itemId, final boolean broadcastUpdate) { + return dbExec.submit(() -> { + LongList queueIdList = DBReader.getQueueIDList(); + int index = queueIdList.indexOf(itemId); + if (index >=0) { + moveQueueItemHelper(index, 0, broadcastUpdate); + } else { + Log.e(TAG, "moveQueueItemToTop: item not found"); } }); } /** * Moves the specified item to the bottom of the queue. - * - * @param context A context that is used for opening a database connection. - * @param itemId The item to move to the bottom of the queue + * @param itemId The item to move to the bottom of the queue * @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to - * false if the caller wants to avoid unexpected updates of the GUI. */ - public static Future moveQueueItemToBottom(final Context context, final long itemId, + public static Future moveQueueItemToBottom(final long itemId, final boolean broadcastUpdate) { - return dbExec.submit(new Runnable() { - @Override - public void run() { - LongList queueIdList = DBReader.getQueueIDList(context); - int index = queueIdList.indexOf(itemId); - if(index >= 0) { - moveQueueItemHelper(context, index, queueIdList.size() - 1, - broadcastUpdate); - } else { - Log.e(TAG, "moveQueueItemToBottom: item not found"); - } + return dbExec.submit(() -> { + LongList queueIdList = DBReader.getQueueIDList(); + int index = queueIdList.indexOf(itemId); + if(index >= 0) { + moveQueueItemHelper(index, queueIdList.size() - 1, + broadcastUpdate); + } else { + Log.e(TAG, "moveQueueItemToBottom: item not found"); } }); } @@ -554,21 +481,16 @@ public class DBWriter { /** * Changes the position of a FeedItem in the queue. * - * @param context A context that is used for opening a database connection. * @param from Source index. Must be in range 0..queue.size()-1. * @param to Destination index. Must be in range 0..queue.size()-1. * @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to * false if the caller wants to avoid unexpected updates of the GUI. * @throws IndexOutOfBoundsException if (to < 0 || to >= queue.size()) || (from < 0 || from >= queue.size()) */ - public static Future moveQueueItem(final Context context, final int from, + public static Future moveQueueItem(final int from, final int to, final boolean broadcastUpdate) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - moveQueueItemHelper(context, from, to, broadcastUpdate); - } + return dbExec.submit(() -> { + moveQueueItemHelper(from, to, broadcastUpdate); }); } @@ -577,24 +499,20 @@ public class DBWriter { *

* This function must be run using the ExecutorService (dbExec). * - * @param context A context that is used for opening a database connection. * @param from Source index. Must be in range 0..queue.size()-1. * @param to Destination index. Must be in range 0..queue.size()-1. * @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to * false if the caller wants to avoid unexpected updates of the GUI. * @throws IndexOutOfBoundsException if (to < 0 || to >= queue.size()) || (from < 0 || from >= queue.size()) */ - private static void moveQueueItemHelper(final Context context, final int from, + private static void moveQueueItemHelper(final int from, final int to, final boolean broadcastUpdate) { - final PodDBAdapter adapter = new PodDBAdapter(context); + final PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); - final List queue = DBReader - .getQueue(context, adapter); + final List queue = DBReader.getQueue(adapter); if (queue != null) { - if (from >= 0 && from < queue.size() && to >= 0 - && to < queue.size()) { - + if (from >= 0 && from < queue.size() && to >= 0 && to < queue.size()) { final FeedItem item = queue.remove(from); queue.add(to, item); @@ -602,7 +520,6 @@ public class DBWriter { if (broadcastUpdate) { EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.MOVED, item, to)); } - } } else { Log.e(TAG, "moveQueueItemHelper: Could not load queue"); @@ -618,9 +535,9 @@ public class DBWriter { * FeedItem.UNPLAYED * @param itemIds IDs of the FeedItems. */ - public static Future markItemPlayed(final Context context, final int played, final long... itemIds) { + public static Future markItemPlayed(final int played, final long... itemIds) { return dbExec.submit(() -> { - final PodDBAdapter adapter = new PodDBAdapter(context); + final PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); adapter.setFeedItemRead(played, itemIds); adapter.close(); @@ -631,24 +548,22 @@ public class DBWriter { /** * Sets the 'read'-attribute of a FeedItem to the specified value. - * - * @param context A context that is used for opening a database connection. - * @param item The FeedItem object + * @param item The FeedItem object * @param played New value of the 'read'-attribute one of FeedItem.PLAYED, * FeedItem.NEW, FeedItem.UNPLAYED * @param resetMediaPosition true if this method should also reset the position of the FeedItem's FeedMedia object. - * If the FeedItem has no FeedMedia object, this parameter will be ignored. */ - public static Future markItemPlayed(Context context, FeedItem item, int played, boolean resetMediaPosition) { + public static Future markItemPlayed(FeedItem item, int played, boolean resetMediaPosition) { long mediaId = (item.hasMedia()) ? item.getMedia().getId() : 0; - return markItemPlayed(context, item.getId(), played, mediaId, resetMediaPosition); + return markItemPlayed(item.getId(), played, mediaId, resetMediaPosition); } - private static Future markItemPlayed(final Context context, final long itemId, - final int played, final long mediaId, + private static Future markItemPlayed(final long itemId, + final int played, + final long mediaId, final boolean resetMediaPosition) { return dbExec.submit(() -> { - final PodDBAdapter adapter = new PodDBAdapter(context); + final PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); adapter.setFeedItemRead(played, itemId, mediaId, resetMediaPosition); @@ -661,163 +576,129 @@ public class DBWriter { /** * Sets the 'read'-attribute of all FeedItems of a specific Feed to true. * - * @param context A context that is used for opening a database connection. * @param feedId ID of the Feed. */ - public static Future markFeedSeen(final Context context, final long feedId) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - final PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - Cursor itemCursor = adapter.getNewItemsIdsCursor(feedId); - long[] ids = new long[itemCursor.getCount()]; - itemCursor.moveToFirst(); - for (int i = 0; i < ids.length; i++) { - ids[i] = itemCursor.getLong(0); - itemCursor.moveToNext(); - } - itemCursor.close(); - adapter.setFeedItemRead(FeedItem.UNPLAYED, ids); - adapter.close(); + public static Future markFeedSeen(final long feedId) { + return dbExec.submit(() -> { + final PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + Cursor itemCursor = adapter.getNewItemsIdsCursor(feedId); + long[] ids = new long[itemCursor.getCount()]; + itemCursor.moveToFirst(); + for (int i = 0; i < ids.length; i++) { + ids[i] = itemCursor.getLong(0); + itemCursor.moveToNext(); + } + itemCursor.close(); + adapter.setFeedItemRead(FeedItem.UNPLAYED, ids); + adapter.close(); - EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); - } + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); }); } /** * Sets the 'read'-attribute of all FeedItems of a specific Feed to true. * - * @param context A context that is used for opening a database connection. * @param feedId ID of the Feed. */ - public static Future markFeedRead(final Context context, final long feedId) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - final PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - Cursor itemCursor = adapter.getAllItemsOfFeedCursor(feedId); - long[] itemIds = new long[itemCursor.getCount()]; - itemCursor.moveToFirst(); - for (int i = 0; i < itemIds.length; i++) { - itemIds[i] = itemCursor.getLong(PodDBAdapter.KEY_ID_INDEX); - itemCursor.moveToNext(); - } - itemCursor.close(); - adapter.setFeedItemRead(FeedItem.PLAYED, itemIds); - adapter.close(); + public static Future markFeedRead(final long feedId) { + return dbExec.submit(() -> { + final PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + Cursor itemCursor = adapter.getAllItemsOfFeedCursor(feedId); + long[] itemIds = new long[itemCursor.getCount()]; + itemCursor.moveToFirst(); + for (int i = 0; i < itemIds.length; i++) { + int indexId = itemCursor.getColumnIndex(PodDBAdapter.KEY_ID); + itemIds[i] = itemCursor.getLong(indexId); + itemCursor.moveToNext(); + } + itemCursor.close(); + adapter.setFeedItemRead(FeedItem.PLAYED, itemIds); + adapter.close(); - EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); - } + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); }); } /** * Sets the 'read'-attribute of all FeedItems to true. - * - * @param context A context that is used for opening a database connection. */ - public static Future markAllItemsRead(final Context context) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - final PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - Cursor itemCursor = adapter.getUnreadItemsCursor(); - long[] itemIds = new long[itemCursor.getCount()]; - itemCursor.moveToFirst(); - for (int i = 0; i < itemIds.length; i++) { - itemIds[i] = itemCursor.getLong(PodDBAdapter.KEY_ID_INDEX); - itemCursor.moveToNext(); - } - itemCursor.close(); - adapter.setFeedItemRead(FeedItem.PLAYED, itemIds); - adapter.close(); + public static Future markAllItemsRead() { + return dbExec.submit(() -> { + final PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + Cursor itemCursor = adapter.getUnreadItemsCursor(); + long[] itemIds = new long[itemCursor.getCount()]; + itemCursor.moveToFirst(); + for (int i = 0; i < itemIds.length; i++) { + int indexId = itemCursor.getColumnIndex(PodDBAdapter.KEY_ID); + itemIds[i] = itemCursor.getLong(indexId); + itemCursor.moveToNext(); + } + itemCursor.close(); + adapter.setFeedItemRead(FeedItem.PLAYED, itemIds); + adapter.close(); - EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); - } + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); }); } static Future addNewFeed(final Context context, final Feed... feeds) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - final PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setCompleteFeed(feeds); - adapter.close(); + return dbExec.submit(() -> { + final PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setCompleteFeed(feeds); + adapter.close(); - if (ClientConfig.gpodnetCallbacks.gpodnetEnabled()) { - for (Feed feed : feeds) { - GpodnetPreferences.addAddedFeed(feed.getDownload_url()); - } + if (ClientConfig.gpodnetCallbacks.gpodnetEnabled()) { + for (Feed feed : feeds) { + GpodnetPreferences.addAddedFeed(feed.getDownload_url()); } - - BackupManager backupManager = new BackupManager(context); - backupManager.dataChanged(); } + + BackupManager backupManager = new BackupManager(context); + backupManager.dataChanged(); }); } - static Future setCompleteFeed(final Context context, final Feed... feeds) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setCompleteFeed(feeds); - adapter.close(); - - } + static Future setCompleteFeed(final Feed... feeds) { + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setCompleteFeed(feeds); + adapter.close(); }); - } /** * Saves a FeedMedia object in the database. This method will save all attributes of the FeedMedia object. The * contents of FeedComponent-attributes (e.g. the FeedMedia's 'item'-attribute) will not be saved. * - * @param context A context that is used for opening a database connection. * @param media The FeedMedia object. */ - public static Future setFeedMedia(final Context context, - final FeedMedia media) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setMedia(media); - adapter.close(); - } + public static Future setFeedMedia(final FeedMedia media) { + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setMedia(media); + adapter.close(); }); } /** * Saves the 'position' and 'duration' attributes of a FeedMedia object * - * @param context A context that is used for opening a database connection. * @param media The FeedMedia object. */ - public static Future setFeedMediaPlaybackInformation(final Context context, final FeedMedia media) { - return dbExec.submit(new Runnable() { - @Override - public void run() { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setFeedMediaPlaybackInformation(media); - adapter.close(); - } + public static Future setFeedMediaPlaybackInformation(final FeedMedia media) { + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setFeedMediaPlaybackInformation(media); + adapter.close(); }); } @@ -825,20 +706,14 @@ public class DBWriter { * Saves a FeedItem object in the database. This method will save all attributes of the FeedItem object including * the content of FeedComponent-attributes. * - * @param context A context that is used for opening a database connection. * @param item The FeedItem object. */ - public static Future setFeedItem(final Context context, - final FeedItem item) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setSingleFeedItem(item); - adapter.close(); - } + public static Future setFeedItem(final FeedItem item) { + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setSingleFeedItem(item); + adapter.close(); }); } @@ -846,20 +721,14 @@ public class DBWriter { * Saves a FeedImage object in the database. This method will save all attributes of the FeedImage object. The * contents of FeedComponent-attributes (e.g. the FeedImages's 'feed'-attribute) will not be saved. * - * @param context A context that is used for opening a database connection. * @param image The FeedImage object. */ - public static Future setFeedImage(final Context context, - final FeedImage image) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setImage(image); - adapter.close(); - } + public static Future setFeedImage(final FeedImage image) { + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setImage(image); + adapter.close(); }); } @@ -867,39 +736,32 @@ public class DBWriter { * Updates download URLs of feeds from a given Map. The key of the Map is the original URL of the feed * and the value is the updated URL */ - public static Future updateFeedDownloadURLs(final Context context, final Map urls) { - return dbExec.submit(new Runnable() { - @Override - public void run() { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - for (String key : urls.keySet()) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Replacing URL " + key + " with url " + urls.get(key)); + public static Future updateFeedDownloadURLs(final Map urls) { + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + for (String key : urls.keySet()) { + if (BuildConfig.DEBUG) + Log.d(TAG, "Replacing URL " + key + " with url " + urls.get(key)); - adapter.setFeedDownloadUrl(key, urls.get(key)); - } - adapter.close(); + adapter.setFeedDownloadUrl(key, urls.get(key)); } + adapter.close(); }); } /** * Saves a FeedPreferences object in the database. The Feed ID of the FeedPreferences-object MUST NOT be 0. * - * @param context Used for opening a database connection. * @param preferences The FeedPreferences object. */ - public static Future setFeedPreferences(final Context context, final FeedPreferences preferences) { - return dbExec.submit(new Runnable() { - @Override - public void run() { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setFeedPreferences(preferences); - adapter.close(); - EventDistributor.getInstance().sendFeedUpdateBroadcast(); - } + public static Future setFeedPreferences(final FeedPreferences preferences) { + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setFeedPreferences(preferences); + adapter.close(); + EventDistributor.getInstance().sendFeedUpdateBroadcast(); }); } @@ -920,17 +782,13 @@ public class DBWriter { public static Future setFeedItemFlattrStatus(final Context context, final FeedItem item, final boolean startFlattrClickWorker) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setFeedItemFlattrStatus(item); - adapter.close(); - if (startFlattrClickWorker) { - new FlattrClickWorker(context).executeAsync(); - } + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setFeedItemFlattrStatus(item); + adapter.close(); + if (startFlattrClickWorker) { + new FlattrClickWorker(context).executeAsync(); } }); } @@ -943,17 +801,13 @@ public class DBWriter { private static Future setFeedFlattrStatus(final Context context, final Feed feed, final boolean startFlattrClickWorker) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setFeedFlattrStatus(feed); - adapter.close(); - if (startFlattrClickWorker) { - new FlattrClickWorker(context).executeAsync(); - } + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setFeedFlattrStatus(feed); + adapter.close(); + if (startFlattrClickWorker) { + new FlattrClickWorker(context).executeAsync(); } }); } @@ -963,18 +817,13 @@ public class DBWriter { * * @param lastUpdateFailed true if last update failed */ - public static Future setFeedLastUpdateFailed(final Context context, - final long feedId, - final boolean lastUpdateFailed) { - return dbExec.submit(new Runnable() { - - @Override - public void run() { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setFeedLastUpdateFailed(feedId, lastUpdateFailed); - adapter.close(); - } + public static Future setFeedLastUpdateFailed(final long feedId, + final boolean lastUpdateFailed) { + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setFeedLastUpdateFailed(feedId, lastUpdateFailed); + adapter.close(); }); } @@ -1002,14 +851,15 @@ public class DBWriter { */ public static Future setFlattredStatus(Context context, FlattrThing thing, boolean startFlattrClickWorker) { // must propagate this to back db - if (thing instanceof FeedItem) + if (thing instanceof FeedItem) { return setFeedItemFlattrStatus(context, (FeedItem) thing, startFlattrClickWorker); - else if (thing instanceof Feed) + } else if (thing instanceof Feed) { return setFeedFlattrStatus(context, (Feed) thing, startFlattrClickWorker); - else if (thing instanceof SimpleFlattrThing) { - } // SimpleFlattrThings are generated on the fly and do not have DB backing - else + } else if (thing instanceof SimpleFlattrThing) { + // SimpleFlattrThings are generated on the fly and do not have DB backing + } else { Log.e(TAG, "flattrQueue processing - thing is neither FeedItem nor Feed nor SimpleFlattrThing"); + } return null; } @@ -1017,16 +867,13 @@ public class DBWriter { /** * Reset flattr status to unflattrd for all items */ - public static Future clearAllFlattrStatus(final Context context) { + public static Future clearAllFlattrStatus() { Log.d(TAG, "clearAllFlattrStatus()"); - return dbExec.submit(new Runnable() { - @Override - public void run() { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.clearAllFlattrStatus(); - adapter.close(); - } + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.clearAllFlattrStatus(); + adapter.close(); }); } @@ -1034,124 +881,95 @@ public class DBWriter { * Set flattr status of the feeds/feeditems in flattrList to flattred at the given timestamp, * where the information has been retrieved from the flattr API */ - public static Future setFlattredStatus(final Context context, final List flattrList) { + public static Future setFlattredStatus(final List flattrList) { Log.d(TAG, "setFlattredStatus to status retrieved from flattr api running with " + flattrList.size() + " items"); // clear flattr status in db - clearAllFlattrStatus(context); + clearAllFlattrStatus(); // submit list with flattred things having normalized URLs to db - return dbExec.submit(new Runnable() { - @Override - public void run() { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - for (Flattr flattr : flattrList) { - adapter.setItemFlattrStatus(formatURIForQuery(flattr.getThing().getUrl()), new FlattrStatus(flattr.getCreated().getTime())); - } - adapter.close(); + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + for (Flattr flattr : flattrList) { + adapter.setItemFlattrStatus(formatURIForQuery(flattr.getThing().getUrl()), new FlattrStatus(flattr.getCreated().getTime())); } + adapter.close(); }); } /** * Sort the FeedItems in the queue with the given Comparator. - * - * @param context A context that is used for opening a database connection. * @param comparator FeedItem comparator * @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to - * false if the caller wants to avoid unexpected updates of the GUI. */ - public static Future sortQueue(final Context context, final Comparator comparator, final boolean broadcastUpdate) { - return dbExec.submit(new Runnable() { - @Override - public void run() { - final PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - final List queue = DBReader.getQueue(context, adapter); + public static Future sortQueue(final Comparator comparator, final boolean broadcastUpdate) { + return dbExec.submit(() -> { + final PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + final List queue = DBReader.getQueue(adapter); - if (queue != null) { - Collections.sort(queue, comparator); - adapter.setQueue(queue); - if (broadcastUpdate) { - EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.SORTED)); - } - } else { - Log.e(TAG, "sortQueue: Could not load queue"); + if (queue != null) { + Collections.sort(queue, comparator); + adapter.setQueue(queue); + if (broadcastUpdate) { + EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.SORTED)); } - adapter.close(); + } else { + Log.e(TAG, "sortQueue: Could not load queue"); } + adapter.close(); }); } /** * Sets the 'auto_download'-attribute of specific FeedItem. * - * @param context A context that is used for opening a database connection. * @param feedItem FeedItem. */ - public static Future setFeedItemAutoDownload(final Context context, final FeedItem feedItem, + public static Future setFeedItemAutoDownload(final FeedItem feedItem, final boolean autoDownload) { Log.d(TAG, "FeedItem[id=" + feedItem.getId() + "] SET auto_download " + autoDownload); - return dbExec.submit(new Runnable() { - - @Override - public void run() { - final PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setFeedItemAutoDownload(feedItem, autoDownload); - adapter.close(); - - EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); - } + return dbExec.submit(() -> { + final PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setFeedItemAutoDownload(feedItem, autoDownload); + adapter.close(); + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); }); } /** * Sets the 'auto_download'-attribute of specific FeedItem. - * - * @param context A context that is used for opening a database connection. - * @param feed This feed's episodes will be processed. + * @param feed This feed's episodes will be processed. * @param autoDownload If true, auto download will be enabled for the feed's episodes. Else, - * it will be disabled. */ - public static Future setFeedsItemsAutoDownload(final Context context, final Feed feed, - final boolean autoDownload) { + public static Future setFeedsItemsAutoDownload(final Feed feed, + final boolean autoDownload) { Log.d(TAG, (autoDownload ? "Enabling" : "Disabling") + " auto download for items of feed " + feed.getId()); - return dbExec.submit(new Runnable() { - - @Override - public void run() { - final PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setFeedsItemsAutoDownload(feed, autoDownload); - adapter.close(); - - EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); - } + return dbExec.submit(() -> { + final PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setFeedsItemsAutoDownload(feed, autoDownload); + adapter.close(); + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); }); } /** * Set filter of the feed - * - * @param context Used for opening a database connection. - * @param feedId The feed's ID + * @param feedId The feed's ID * @param filterValues Values that represent properties to filter by */ - public static Future setFeedItemsFilter(final Context context, final long feedId, + public static Future setFeedItemsFilter(final long feedId, final List filterValues) { Log.d(TAG, "setFeedFilter"); - - return dbExec.submit(new Runnable() { - @Override - public void run() { - PodDBAdapter adapter = new PodDBAdapter(context); - adapter.open(); - adapter.setFeedItemFilter(feedId, filterValues); - adapter.close(); - EventBus.getDefault().post(new FeedEvent(FeedEvent.Action.FILTER_CHANGED, feedId)); - } + return dbExec.submit(() -> { + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setFeedItemFilter(feedId, filterValues); + adapter.close(); + EventBus.getDefault().post(new FeedEvent(FeedEvent.Action.FILTER_CHANGED, feedId)); }); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/EpisodeCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/EpisodeCleanupAlgorithm.java index 6a8b4a441..91f221f39 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/EpisodeCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/EpisodeCleanupAlgorithm.java @@ -24,7 +24,7 @@ public interface EpisodeCleanupAlgorithm { * space to free to satisfy the episode cache conditions. If the conditions are already satisfied, this * method should not have any effects. */ - public T getDefaultCleanupParameter(Context context); + public T getDefaultCleanupParameter(); /** * Returns a parameter for performCleanup. @@ -32,5 +32,5 @@ public interface EpisodeCleanupAlgorithm { * @param items A list of FeedItems that are about to be downloaded. The implementation of this interface * should decide how much space to free to satisfy the episode cache conditions. */ - public T getPerformCleanupParameter(Context context, List items); + public T getPerformCleanupParameter(List items); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedItemStatistics.java b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedItemStatistics.java index f6a59836b..09949b87e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/FeedItemStatistics.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/FeedItemStatistics.java @@ -1,5 +1,7 @@ package de.danoeh.antennapod.core.storage; +import android.database.Cursor; + import java.util.Date; /** @@ -36,6 +38,15 @@ public class FeedItemStatistics { } } + public static FeedItemStatistics fromCursor(Cursor cursor) { + return new FeedItemStatistics( + cursor.getLong(0), + cursor.getInt(1), + cursor.getInt(2), + cursor.getInt(4), + new Date(cursor.getLong(3))); + } + public long getFeedID() { return feedID; } 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 4714f4880..73037d771 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 @@ -17,8 +17,8 @@ import org.apache.commons.lang3.Validate; import java.util.Arrays; import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; -import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.event.ProgressEvent; import de.danoeh.antennapod.core.feed.Chapter; @@ -40,6 +40,7 @@ import de.greenrobot.event.EventBus; * Implements methods for accessing the database */ public class PodDBAdapter { + private static final String TAG = "PodDBAdapter"; public static final String DATABASE_NAME = "Antennapod.db"; @@ -53,63 +54,6 @@ public class PodDBAdapter { */ public static final int SEARCH_LIMIT = 30; - // ----------- Column indices - // ----------- General indices - public static final int KEY_ID_INDEX = 0; - public static final int KEY_TITLE_INDEX = 1; - public static final int KEY_FILE_URL_INDEX = 2; - public static final int KEY_DOWNLOAD_URL_INDEX = 3; - public static final int KEY_DOWNLOADED_INDEX = 4; - public static final int KEY_LINK_INDEX = 5; - public static final int KEY_DESCRIPTION_INDEX = 6; - public static final int KEY_PAYMENT_LINK_INDEX = 7; - // ----------- Feed indices - public static final int KEY_LAST_UPDATE_INDEX = 8; - public static final int KEY_LANGUAGE_INDEX = 9; - public static final int KEY_AUTHOR_INDEX = 10; - public static final int KEY_IMAGE_INDEX = 11; - public static final int KEY_TYPE_INDEX = 12; - public static final int KEY_FEED_IDENTIFIER_INDEX = 13; - public static final int KEY_FEED_FLATTR_STATUS_INDEX = 14; - public static final int KEY_FEED_USERNAME_INDEX = 15; - public static final int KEY_FEED_PASSWORD_INDEX = 16; - public static final int KEY_IS_PAGED_INDEX = 17; - public static final int KEY_LOAD_ALL_PAGES_INDEX = 18; - public static final int KEY_NEXT_PAGE_LINK_INDEX = 19; - // ----------- FeedItem indices - public static final int KEY_CONTENT_ENCODED_INDEX = 2; - public static final int KEY_PUBDATE_INDEX = 3; - public static final int KEY_READ_INDEX = 4; - public static final int KEY_MEDIA_INDEX = 8; - public static final int KEY_FEED_INDEX = 9; - public static final int KEY_HAS_SIMPLECHAPTERS_INDEX = 10; - public static final int KEY_ITEM_IDENTIFIER_INDEX = 11; - public static final int KEY_ITEM_FLATTR_STATUS_INDEX = 12; - // ---------- FeedMedia indices - public static final int KEY_DURATION_INDEX = 1; - public static final int KEY_POSITION_INDEX = 5; - public static final int KEY_SIZE_INDEX = 6; - public static final int KEY_MIME_TYPE_INDEX = 7; - public static final int KEY_PLAYBACK_COMPLETION_DATE_INDEX = 8; - public static final int KEY_MEDIA_FEEDITEM_INDEX = 9; - public static final int KEY_PLAYED_DURATION_INDEX = 10; - // --------- Download log indices - public static final int KEY_FEEDFILE_INDEX = 1; - public static final int KEY_FEEDFILETYPE_INDEX = 2; - public static final int KEY_REASON_INDEX = 3; - public static final int KEY_SUCCESSFUL_INDEX = 4; - public static final int KEY_COMPLETION_DATE_INDEX = 5; - public static final int KEY_REASON_DETAILED_INDEX = 6; - public static final int KEY_DOWNLOADSTATUS_TITLE_INDEX = 7; - // --------- Queue indices - public static final int KEY_FEEDITEM_INDEX = 1; - public static final int KEY_QUEUE_FEED_INDEX = 2; - // --------- Chapters indices - public static final int KEY_CHAPTER_START_INDEX = 2; - public static final int KEY_CHAPTER_FEEDITEM_INDEX = 3; - public static final int KEY_CHAPTER_LINK_INDEX = 4; - public static final int KEY_CHAPTER_TYPE_INDEX = 5; - // Key-constants public static final String KEY_ID = "id"; public static final String KEY_TITLE = "title"; @@ -253,12 +197,7 @@ public class PodDBAdapter { public static final String CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM = "CREATE INDEX " + TABLE_NAME_SIMPLECHAPTERS + "_" + KEY_FEEDITEM + " ON " + TABLE_NAME_SIMPLECHAPTERS + " (" + KEY_FEEDITEM + ")"; - - - private SQLiteDatabase db; - private final Context context; - private PodDBHelper helper; - + /** * Select all columns from the feed-table */ @@ -287,30 +226,7 @@ public class PodDBAdapter { TABLE_NAME_FEEDS + "." + KEY_LAST_UPDATE_FAILED, TABLE_NAME_FEEDS + "." + KEY_AUTO_DELETE_ACTION, }; - - // column indices for FEED_SEL_STD - public static final int IDX_FEED_SEL_STD_ID = 0; - public static final int IDX_FEED_SEL_STD_TITLE = 1; - public static final int IDX_FEED_SEL_STD_FILE_URL = 2; - public static final int IDX_FEED_SEL_STD_DOWNLOAD_URL = 3; - public static final int IDX_FEED_SEL_STD_DOWNLOADED = 4; - public static final int IDX_FEED_SEL_STD_LINK = 5; - public static final int IDX_FEED_SEL_STD_DESCRIPTION = 6; - public static final int IDX_FEED_SEL_STD_PAYMENT_LINK = 7; - public static final int IDX_FEED_SEL_STD_LASTUPDATE = 8; - public static final int IDX_FEED_SEL_STD_LANGUAGE = 9; - public static final int IDX_FEED_SEL_STD_AUTHOR = 10; - public static final int IDX_FEED_SEL_STD_IMAGE = 11; - public static final int IDX_FEED_SEL_STD_TYPE = 12; - public static final int IDX_FEED_SEL_STD_FEED_IDENTIFIER = 13; - public static final int IDX_FEED_SEL_PREFERENCES_AUTO_DOWNLOAD = 14; - public static final int IDX_FEED_SEL_STD_FLATTR_STATUS = 15; - public static final int IDX_FEED_SEL_STD_IS_PAGED = 16; - public static final int IDX_FEED_SEL_STD_NEXT_PAGE_LINK = 17; - public static final int IDX_FEED_SEL_PREFERENCES_USERNAME = 18; - public static final int IDX_FEED_SEL_PREFERENCES_PASSWORD = 19; - public static final int IDX_FEED_SEL_PREFERENCES_AUTO_DELETE_ACTION = 22; - + /** * Select all columns from the feeditems-table except description and * content-encoded. @@ -321,7 +237,8 @@ public class PodDBAdapter { TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE, TABLE_NAME_FEED_ITEMS + "." + KEY_READ, TABLE_NAME_FEED_ITEMS + "." + KEY_LINK, - TABLE_NAME_FEED_ITEMS + "." + KEY_PAYMENT_LINK, KEY_MEDIA, + TABLE_NAME_FEED_ITEMS + "." + KEY_PAYMENT_LINK, + TABLE_NAME_FEED_ITEMS + "." + KEY_MEDIA, TABLE_NAME_FEED_ITEMS + "." + KEY_FEED, TABLE_NAME_FEED_ITEMS + "." + KEY_HAS_CHAPTERS, TABLE_NAME_FEED_ITEMS + "." + KEY_ITEM_IDENTIFIER, @@ -340,73 +257,59 @@ public class PodDBAdapter { SEL_FI_SMALL_STR = selFiSmall.substring(1, selFiSmall.length() - 1); } - // column indices for FEEDITEM_SEL_FI_SMALL - - public static final int IDX_FI_SMALL_ID = 0; - public static final int IDX_FI_SMALL_TITLE = 1; - public static final int IDX_FI_SMALL_PUBDATE = 2; - public static final int IDX_FI_SMALL_READ = 3; - public static final int IDX_FI_SMALL_LINK = 4; - public static final int IDX_FI_SMALL_PAYMENT_LINK = 5; - public static final int IDX_FI_SMALL_MEDIA = 6; - public static final int IDX_FI_SMALL_FEED = 7; - public static final int IDX_FI_SMALL_HAS_CHAPTERS = 8; - public static final int IDX_FI_SMALL_ITEM_IDENTIFIER = 9; - public static final int IDX_FI_SMALL_FLATTR_STATUS = 10; - public static final int IDX_FI_SMALL_IMAGE = 11; - /** * Select id, description and content-encoded column from feeditems. */ private static final String[] SEL_FI_EXTRA = {KEY_ID, KEY_DESCRIPTION, KEY_CONTENT_ENCODED, KEY_FEED}; - // column indices for SEL_FI_EXTRA - public static final int IDX_FI_EXTRA_ID = 0; - public static final int IDX_FI_EXTRA_DESCRIPTION = 1; - public static final int IDX_FI_EXTRA_CONTENT_ENCODED = 2; - public static final int IDX_FI_EXTRA_FEED = 3; + private SQLiteDatabase db; + private static Context context; + private static PodDBHelper dbHelper; + private static AtomicInteger counter = new AtomicInteger(0); - static PodDBHelper dbHelperSingleton; + public static void init(Context context) { + PodDBAdapter.context = context.getApplicationContext(); + } - private static synchronized PodDBHelper getDbHelperSingleton(Context appContext) { - if (dbHelperSingleton == null) { - dbHelperSingleton = new PodDBHelper(appContext, DATABASE_NAME, null); + public static synchronized PodDBAdapter getInstance() { + if(dbHelper == null) { + dbHelper = new PodDBHelper(PodDBAdapter.context, DATABASE_NAME, null); } - return dbHelperSingleton; + return new PodDBAdapter(); } - public PodDBAdapter(Context c) { - this.context = c; - helper = getDbHelperSingleton(c.getApplicationContext()); - } + private PodDBAdapter() {} public PodDBAdapter open() { + counter.incrementAndGet(); if (db == null || !db.isOpen() || db.isReadOnly()) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Opening DB"); + Log.v(TAG, "Opening DB"); try { - db = helper.getWritableDatabase(); + db = dbHelper.getWritableDatabase(); } catch (SQLException ex) { - ex.printStackTrace(); - db = helper.getReadableDatabase(); + Log.e(TAG, Log.getStackTraceString(ex)); + db = dbHelper.getReadableDatabase(); } } return this; } public void close() { - if (BuildConfig.DEBUG) - Log.d(TAG, "Closing DB"); - //db.close(); + if(counter.decrementAndGet() == 0) { + Log.v(TAG, "Closing DB"); + db.close(); + } + db = null; } - public static boolean deleteDatabase(Context context) { - Log.w(TAG, "Deleting database"); - dbHelperSingleton.close(); - dbHelperSingleton = null; - return context.deleteDatabase(DATABASE_NAME); + public static boolean deleteDatabase() { + if(dbHelper != null) { + dbHelper.close(); + dbHelper = null; + } + return context.deleteDatabase(PodDBAdapter.DATABASE_NAME); } /** @@ -484,7 +387,12 @@ public class PodDBAdapter { * @return the id of the entry */ public long setImage(FeedImage image) { - db.beginTransaction(); + boolean startedTransaction = false; + if(false == db.inTransaction()) { + db.beginTransaction(); + startedTransaction = true; + } + ContentValues values = new ContentValues(); values.put(KEY_TITLE, image.getTitle()); values.put(KEY_DOWNLOAD_URL, image.getDownload_url()); @@ -505,8 +413,10 @@ public class PodDBAdapter { db.update(TABLE_NAME_FEEDS, values, KEY_ID + "=?", new String[]{String.valueOf(image.getOwner().getId())}); } } - db.setTransactionSuccessful(); - db.endTransaction(); + if(startedTransaction) { + db.setTransactionSuccessful(); + db.endTransaction(); + } return image.getId(); } @@ -527,8 +437,7 @@ public class PodDBAdapter { values.put(KEY_HAS_EMBEDDED_PICTURE, media.hasEmbeddedPicture()); if (media.getPlaybackCompletionDate() != null) { - values.put(KEY_PLAYBACK_COMPLETION_DATE, media - .getPlaybackCompletionDate().getTime()); + values.put(KEY_PLAYBACK_COMPLETION_DATE, media.getPlaybackCompletionDate().getTime()); } else { values.put(KEY_PLAYBACK_COMPLETION_DATE, 0); } @@ -822,8 +731,7 @@ public class PodDBAdapter { values.put(KEY_LINK, chapter.getLink()); values.put(KEY_CHAPTER_TYPE, chapter.getChapterType()); if (chapter.getId() == 0) { - chapter.setId(db - .insert(TABLE_NAME_SIMPLECHAPTERS, null, values)); + chapter.setId(db.insert(TABLE_NAME_SIMPLECHAPTERS, null, values)); } else { db.update(TABLE_NAME_SIMPLECHAPTERS, values, KEY_ID + "=?", new String[]{String.valueOf(chapter.getId())}); @@ -884,14 +792,6 @@ public class PodDBAdapter { return count; } - public void removeDownloadLogItems(long count) { - if (count > 0) { - final String sql = String.format("DELETE FROM %s WHERE %s in (SELECT %s from %s ORDER BY %s ASC LIMIT %d)", - TABLE_NAME_DOWNLOAD_LOG, KEY_ID, KEY_ID, TABLE_NAME_DOWNLOAD_LOG, KEY_COMPLETION_DATE, count); - db.execSQL(sql, null); - } - } - public void setQueue(List queue) { ContentValues values = new ContentValues(); db.beginTransaction(); @@ -963,11 +863,6 @@ public class PodDBAdapter { db.endTransaction(); } - public void removeDownloadStatus(DownloadStatus remove) { - db.delete(TABLE_NAME_DOWNLOAD_LOG, KEY_ID + "=?", - new String[]{String.valueOf(remove.getId())}); - } - public void clearPlaybackHistory() { ContentValues values = new ContentValues(); values.put(KEY_PLAYBACK_COMPLETION_DATE, 0); @@ -1075,21 +970,14 @@ public class PodDBAdapter { * cursor uses the FEEDITEM_SEL_FI_SMALL selection. */ public final Cursor getQueueCursor() { - Object[] args = (Object[]) new String[]{ - SEL_FI_SMALL_STR + "," + TABLE_NAME_QUEUE + "." + KEY_ID, + Object[] args = new String[] { + SEL_FI_SMALL_STR, TABLE_NAME_FEED_ITEMS, TABLE_NAME_QUEUE, TABLE_NAME_FEED_ITEMS + "." + KEY_ID, TABLE_NAME_QUEUE + "." + KEY_FEEDITEM, - TABLE_NAME_QUEUE + "." + KEY_ID}; - String query = String.format( - "SELECT %s FROM %s INNER JOIN %s ON %s=%s ORDER BY %s", args); + TABLE_NAME_QUEUE + "." + KEY_ID }; + String query = String.format("SELECT %s FROM %s INNER JOIN %s ON %s=%s ORDER BY %s", args); Cursor c = db.rawQuery(query, null); - /* - * Cursor c = db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL, - * "INNER JOIN ? ON ?=?", new String[] { TABLE_NAME_QUEUE, - * TABLE_NAME_FEED_ITEMS + "." + KEY_ID, TABLE_NAME_QUEUE + "." + - * KEY_FEEDITEM }, null, null, TABLE_NAME_QUEUE + "." + KEY_FEEDITEM); - */ return c; } 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 f6486163c..c2cd273b8 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 @@ -148,7 +148,7 @@ public class NetworkUtils { } subscriber.onNext(size); subscriber.onCompleted(); - DBWriter.setFeedMedia(context, media); + DBWriter.setFeedMedia(media); } }) .subscribeOn(Schedulers.newThread()) diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java b/core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java index 9a1496b75..71d6040ba 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/QueueSorter.java @@ -83,7 +83,7 @@ public class QueueSorter { } if (comparator != null) { - DBWriter.sortQueue(context, comparator, broadcastUpdate); + DBWriter.sortQueue(comparator, broadcastUpdate); } } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java index 3b9e6120c..f37933876 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java @@ -167,7 +167,7 @@ public class FlattrUtils { deleteToken(); FlattrServiceCreator.deleteFlattrService(); showRevokeDialog(context); - DBWriter.clearAllFlattrStatus(context); + DBWriter.clearAllFlattrStatus(); } // ------------------------------------------------ DIALOGS diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/gui/UndoBarController.java b/core/src/main/java/de/danoeh/antennapod/core/util/gui/UndoBarController.java index 26c712af3..5eaff6069 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/gui/UndoBarController.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/gui/UndoBarController.java @@ -89,7 +89,9 @@ public class UndoBarController { public void close() { hideUndoBar(true); - mUndoListener.onHide(mUndoToken); + if(mUndoListener != null) { + mUndoListener.onHide(mUndoToken); + } } public void hideUndoBar(boolean immediate) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java index 752e95985..6e306d30a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java @@ -164,7 +164,7 @@ public interface Playable extends Parcelable, case FeedMedia.PLAYABLE_TYPE_FEEDMEDIA: long mediaId = pref.getLong(FeedMedia.PREF_MEDIA_ID, -1); if (mediaId != -1) { - return DBReader.getFeedMedia(context, mediaId); + return DBReader.getFeedMedia(mediaId); } break; case ExternalMedia.PLAYABLE_TYPE_EXTERNAL_MEDIA: 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 42aa3b713..efeba888b 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 @@ -56,7 +56,7 @@ public abstract class PlaybackController { private final Activity activity; private PlaybackService playbackService; - private Playable media; + protected Playable media; private PlayerStatus status; private ScheduledThreadPoolExecutor schedExecutor; @@ -479,8 +479,10 @@ public abstract class PlaybackController { private void updatePlayButtonAppearance(int resource, CharSequence contentDescription) { ImageButton butPlay = getPlayButton(); - butPlay.setImageResource(resource); - butPlay.setContentDescription(contentDescription); + if(butPlay != null) { + butPlay.setImageResource(resource); + butPlay.setContentDescription(contentDescription); + } } public abstract ImageButton getPlayButton(); -- cgit v1.2.3 From 8efb73a39e14b780cd7486d47502e7e3370fbd2a Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Mon, 14 Sep 2015 21:49:43 +0200 Subject: Set lockscreen background, set media session and playback state --- .../core/preferences/UserPreferences.java | 10 +++ .../playback/MediaButtonIntentReceiver.java | 5 +- .../playback/PlaybackServiceMediaPlayer.java | 71 ++++++++++++++++++---- core/src/main/res/values/strings.xml | 5 +- 4 files changed, 75 insertions(+), 16 deletions(-) (limited to 'core/src/main') 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 08328536d..1fcfdce67 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 @@ -47,6 +47,7 @@ public class UserPreferences { public static final String PREF_DRAWER_FEED_COUNTER = "prefDrawerFeedIndicator"; public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify"; public static final String PREF_PERSISTENT_NOTIFICATION = "prefPersistNotify"; + public static final String PREF_LOCKSCREEN_BACKGROUND = "prefLockscreenBackground"; public static final String PREF_SHOW_DOWNLOAD_REPORT = "prefShowDownloadReport"; // Queue @@ -171,6 +172,15 @@ public class UserPreferences { return prefs.getBoolean(PREF_PERSISTENT_NOTIFICATION, false); } + /** + * Returns true if notifications are persistent + * + * @return {@code true} if notifications are persistent, {@code false} otherwise + */ + public static boolean setLockscreenBackground() { + return prefs.getBoolean(PREF_LOCKSCREEN_BACKGROUND, false); + } + /** * Returns true if download reports are shown * diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/MediaButtonIntentReceiver.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/MediaButtonIntentReceiver.java index 3e401b5ea..7d06390f2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/MediaButtonIntentReceiver.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/MediaButtonIntentReceiver.java @@ -4,11 +4,10 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; -import android.view.KeyEvent; public class MediaButtonIntentReceiver extends BroadcastReceiver { - private static final String TAG = "MediaButtonIntentReceiver"; + private static final String TAG = "MediaButtonIntentRcver"; private static PlaybackServiceMediaPlayer mMediaPlayer; @@ -20,7 +19,7 @@ public class MediaButtonIntentReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { Log.d(TAG, "onReceive(Context, " + intent.toString() +")"); if (mMediaPlayer != null && Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) { - mMediaPlayer.handleMediaKey((KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT)); + mMediaPlayer.handleMediaKey(intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT)); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 2012549fc..6a7271cd3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -4,9 +4,12 @@ import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; +import android.graphics.Bitmap; import android.media.AudioManager; import android.net.wifi.WifiManager; import android.os.PowerManager; +import android.preference.PreferenceManager; import android.support.v4.media.MediaMetadataCompat; import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; @@ -16,6 +19,9 @@ import android.util.Pair; import android.view.KeyEvent; import android.view.SurfaceHolder; +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.target.Target; + import org.apache.commons.lang3.Validate; import java.io.IOException; @@ -30,6 +36,7 @@ import de.danoeh.antennapod.core.feed.Chapter; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.MediaType; +import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.playback.AudioPlayer; @@ -40,7 +47,7 @@ import de.danoeh.antennapod.core.util.playback.VideoPlayer; /** * Manages the MediaPlayer object of the PlaybackService. */ -public class PlaybackServiceMediaPlayer { +public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPreferenceChangeListener { public static final String TAG = "PlaybackSvcMediaPlayer"; /** @@ -103,7 +110,7 @@ public class PlaybackServiceMediaPlayer { ComponentName eventReceiver = new ComponentName(context.getPackageName(), MediaButtonIntentReceiver.class.getName()); Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); mediaButtonIntent.setComponent(eventReceiver); - PendingIntent buttonReceiverIntent = PendingIntent.getBroadcast(context, 0, mediaButtonIntent, 0); + PendingIntent buttonReceiverIntent = PendingIntent.getBroadcast(context, 0, mediaButtonIntent, PendingIntent.FLAG_UPDATE_CURRENT); mediaSession = new MediaSessionCompat(context, TAG, eventReceiver, buttonReceiverIntent); mediaSession.setCallback(sessionCallback); @@ -116,6 +123,16 @@ public class PlaybackServiceMediaPlayer { mediaType = MediaType.UNKNOWN; playerStatus = PlayerStatus.STOPPED; videoSize = null; + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + prefs.registerOnSharedPreferenceChangeListener(this); + } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if(key.equals(UserPreferences.PREF_LOCKSCREEN_BACKGROUND)) { + updateMediaSessionMetadata(); + } } /** @@ -224,7 +241,7 @@ public class PlaybackServiceMediaPlayer { setPlayerStatus(PlayerStatus.INITIALIZING, media); try { media.loadMetadata(); - mediaSession.setMetadata(getMediaSessionMetadata(media)); + updateMediaSessionMetadata(); if (stream) { mediaPlayer.setDataSource(media.getStreamUrl()); } else { @@ -255,13 +272,33 @@ public class PlaybackServiceMediaPlayer { } } - private MediaMetadataCompat getMediaSessionMetadata(Playable p) { - MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder(); - builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, p.getFeedTitle()); - builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, p.getEpisodeTitle()); - builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, p.getEpisodeTitle()); - builder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, p.getFeedTitle()); - return builder.build(); + private void updateMediaSessionMetadata() { + executor.execute(() -> { + Playable p = this.media; + MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder(); + builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, p.getFeedTitle()); + builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, p.getEpisodeTitle()); + builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, p.getDuration()); + builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, p.getEpisodeTitle()); + builder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, p.getFeedTitle()); + if (p.getImageUri() != null) { + if (UserPreferences.setLockscreenBackground()) { + builder.putString(MediaMetadataCompat.METADATA_KEY_ART_URI, p.getImageUri().toString()); + try { + Bitmap art = Glide.with(context) + .load(p.getImageUri()) + .asBitmap() + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) + .get(); + builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, art); + } catch (Exception e) { + Log.e(TAG, Log.getStackTraceString(e)); + } + } + } + mediaSession.setMetadata(builder.build()); + }); } @@ -812,7 +849,12 @@ public class PlaybackServiceMediaPlayer { } else { state = PlaybackStateCompat.STATE_NONE; } - sessionState.setState(state, PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN, getPlaybackSpeed()); + sessionState.setState(state, getPosition(), getPlaybackSpeed()); + sessionState.setActions(PlaybackStateCompat.ACTION_PLAY_PAUSE + | PlaybackStateCompat.ACTION_REWIND + | PlaybackStateCompat.ACTION_FAST_FORWARD + | PlaybackStateCompat.ACTION_SKIP_TO_NEXT); + mediaSession.setPlaybackState(sessionState.build()); callback.statusChanged(new PSMPInfo(playerStatus, media)); } @@ -1218,7 +1260,14 @@ public class PlaybackServiceMediaPlayer { stop(); return true; } + case KeyEvent.KEYCODE_MEDIA_NEXT: + { + Log.d(TAG, "Received next event from RemoteControlClient"); + endPlayback(); + return true; + } default: + Log.d(TAG, "Unhandled key code: " + event.getKeyCode()); break; } } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 3682d4307..7c38374a9 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -1,8 +1,7 @@ + tools:ignore="MissingTranslation"> AntennaPod @@ -335,6 +334,8 @@ Always expand the notification to show playback buttons. Persistent Playback Controls Keep notification and lockscreen controls when playback is paused. + Lockscreen Background + Set the lockscreen background to the current episode\'s image. Show Download Report If downloads fail, generate a report that shows the details of the failure. Android versions before 4.1 do not support expanded notifications. -- cgit v1.2.3 From 17c87d9bfc1b3af594befa8356b40535267d9d0d Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Wed, 16 Sep 2015 01:44:45 +0200 Subject: Lockscreen background defaults to true, more detailed description, NPE fixed --- .../antennapod/core/service/playback/PlaybackServiceMediaPlayer.java | 3 +++ core/src/main/res/values/strings.xml | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 6a7271cd3..4704bb207 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -273,6 +273,9 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre } private void updateMediaSessionMetadata() { + if(this.media == null) { + return; + } executor.execute(() -> { Playable p = this.media; MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder(); diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 7c38374a9..68c5150e5 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -334,8 +334,8 @@ Always expand the notification to show playback buttons. Persistent Playback Controls Keep notification and lockscreen controls when playback is paused. - Lockscreen Background - Set the lockscreen background to the current episode\'s image. + Set Lockscreen Background + Set the lockscreen background to the current episode\'s image. As a side effect, this will also show the image in third party apps. Show Download Report If downloads fail, generate a report that shows the details of the failure. Android versions before 4.1 do not support expanded notifications. -- cgit v1.2.3 From 96132d0da9eccd2794f23d5fc0e5e32572a068ef Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 17 Sep 2015 23:18:08 +0200 Subject: NP check in executor run code --- .../core/service/playback/PlaybackServiceMediaPlayer.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 4704bb207..757b2e980 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -273,11 +273,11 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre } private void updateMediaSessionMetadata() { - if(this.media == null) { - return; - } executor.execute(() -> { - Playable p = this.media; + final Playable p = this.media; + if(p == null) { + return; + } MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder(); builder.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, p.getFeedTitle()); builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, p.getEpisodeTitle()); -- cgit v1.2.3 From c34a2779bb0d9a1cd9faa285a1f3f8409255d9c7 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 18 Sep 2015 00:52:21 +0200 Subject: Change default --- .../java/de/danoeh/antennapod/core/preferences/UserPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') 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 1fcfdce67..c0d44dff3 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 @@ -178,7 +178,7 @@ public class UserPreferences { * @return {@code true} if notifications are persistent, {@code false} otherwise */ public static boolean setLockscreenBackground() { - return prefs.getBoolean(PREF_LOCKSCREEN_BACKGROUND, false); + return prefs.getBoolean(PREF_LOCKSCREEN_BACKGROUND, true); } /** -- cgit v1.2.3 From dbdd18523cb458d0afd322d111a78c33262d44be Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 18 Sep 2015 10:58:25 +0200 Subject: Allow only alphanumeric and a few other characters in media filenames --- .../main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java index bc34523cc..b13f7a0cb 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DownloadRequester.java @@ -351,7 +351,7 @@ public class DownloadRequester { if (media.getItem() != null && media.getItem().getTitle() != null) { String title = media.getItem().getTitle(); // Delete reserved characters - titleBaseFilename = title.replaceAll("[\\\\/%\\?\\*:|<>\"\\p{Cntrl}]", ""); + titleBaseFilename = title.replaceAll("[^a-zA-Z0-9 ._()-]", ""); titleBaseFilename = titleBaseFilename.trim(); } -- cgit v1.2.3 From 7b23dfeb506b9e62ea245671e61bf2c3be71d15c Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 19 Sep 2015 01:36:52 +0200 Subject: Move audio player classes to external library --- .../aocate/presto/service/IDeathCallback_0_8.aidl | 18 - .../IOnBufferingUpdateListenerCallback_0_8.aidl | 19 - .../service/IOnCompletionListenerCallback_0_8.aidl | 19 - .../service/IOnErrorListenerCallback_0_8.aidl | 19 - .../service/IOnInfoListenerCallback_0_8.aidl | 19 - ...stmentAvailableChangedListenerCallback_0_8.aidl | 19 - .../service/IOnPreparedListenerCallback_0_8.aidl | 19 - .../IOnSeekCompleteListenerCallback_0_8.aidl | 19 - ...stmentAvailableChangedListenerCallback_0_8.aidl | 19 - .../com/aocate/presto/service/IPlayMedia_0_8.aidl | 75 -- .../java/com/aocate/media/AndroidMediaPlayer.java | 470 ------- .../main/java/com/aocate/media/MediaPlayer.java | 1310 -------------------- .../java/com/aocate/media/MediaPlayerImpl.java | 118 -- .../com/aocate/media/ServiceBackedMediaPlayer.java | 1203 ------------------ .../com/aocate/media/SpeedAdjustmentAlgorithm.java | 31 - .../core/preferences/UserPreferences.java | 7 + .../playback/PlaybackServiceMediaPlayer.java | 20 +- .../antennapod/core/util/playback/AudioPlayer.java | 10 +- core/src/main/res/values/strings.xml | 3 + 19 files changed, 28 insertions(+), 3389 deletions(-) delete mode 100644 core/src/main/aidl/com/aocate/presto/service/IDeathCallback_0_8.aidl delete mode 100644 core/src/main/aidl/com/aocate/presto/service/IOnBufferingUpdateListenerCallback_0_8.aidl delete mode 100644 core/src/main/aidl/com/aocate/presto/service/IOnCompletionListenerCallback_0_8.aidl delete mode 100644 core/src/main/aidl/com/aocate/presto/service/IOnErrorListenerCallback_0_8.aidl delete mode 100644 core/src/main/aidl/com/aocate/presto/service/IOnInfoListenerCallback_0_8.aidl delete mode 100644 core/src/main/aidl/com/aocate/presto/service/IOnPitchAdjustmentAvailableChangedListenerCallback_0_8.aidl delete mode 100644 core/src/main/aidl/com/aocate/presto/service/IOnPreparedListenerCallback_0_8.aidl delete mode 100644 core/src/main/aidl/com/aocate/presto/service/IOnSeekCompleteListenerCallback_0_8.aidl delete mode 100644 core/src/main/aidl/com/aocate/presto/service/IOnSpeedAdjustmentAvailableChangedListenerCallback_0_8.aidl delete mode 100644 core/src/main/aidl/com/aocate/presto/service/IPlayMedia_0_8.aidl delete mode 100644 core/src/main/java/com/aocate/media/AndroidMediaPlayer.java delete mode 100644 core/src/main/java/com/aocate/media/MediaPlayer.java delete mode 100644 core/src/main/java/com/aocate/media/MediaPlayerImpl.java delete mode 100644 core/src/main/java/com/aocate/media/ServiceBackedMediaPlayer.java delete mode 100644 core/src/main/java/com/aocate/media/SpeedAdjustmentAlgorithm.java (limited to 'core/src/main') diff --git a/core/src/main/aidl/com/aocate/presto/service/IDeathCallback_0_8.aidl b/core/src/main/aidl/com/aocate/presto/service/IDeathCallback_0_8.aidl deleted file mode 100644 index 6bdc76801..000000000 --- a/core/src/main/aidl/com/aocate/presto/service/IDeathCallback_0_8.aidl +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2011, Aocate, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.aocate.presto.service; - -oneway interface IDeathCallback_0_8 { -} \ No newline at end of file diff --git a/core/src/main/aidl/com/aocate/presto/service/IOnBufferingUpdateListenerCallback_0_8.aidl b/core/src/main/aidl/com/aocate/presto/service/IOnBufferingUpdateListenerCallback_0_8.aidl deleted file mode 100644 index 7357e402e..000000000 --- a/core/src/main/aidl/com/aocate/presto/service/IOnBufferingUpdateListenerCallback_0_8.aidl +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2011, Aocate, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.aocate.presto.service; - -interface IOnBufferingUpdateListenerCallback_0_8 { - void onBufferingUpdate(int percent); -} \ No newline at end of file diff --git a/core/src/main/aidl/com/aocate/presto/service/IOnCompletionListenerCallback_0_8.aidl b/core/src/main/aidl/com/aocate/presto/service/IOnCompletionListenerCallback_0_8.aidl deleted file mode 100644 index d5edea729..000000000 --- a/core/src/main/aidl/com/aocate/presto/service/IOnCompletionListenerCallback_0_8.aidl +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2011, Aocate, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.aocate.presto.service; - -interface IOnCompletionListenerCallback_0_8 { - void onCompletion(); -} \ No newline at end of file diff --git a/core/src/main/aidl/com/aocate/presto/service/IOnErrorListenerCallback_0_8.aidl b/core/src/main/aidl/com/aocate/presto/service/IOnErrorListenerCallback_0_8.aidl deleted file mode 100644 index 2c4f2df3e..000000000 --- a/core/src/main/aidl/com/aocate/presto/service/IOnErrorListenerCallback_0_8.aidl +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2011, Aocate, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.aocate.presto.service; - -interface IOnErrorListenerCallback_0_8 { - boolean onError(int what, int extra); -} diff --git a/core/src/main/aidl/com/aocate/presto/service/IOnInfoListenerCallback_0_8.aidl b/core/src/main/aidl/com/aocate/presto/service/IOnInfoListenerCallback_0_8.aidl deleted file mode 100644 index 9dbd1d260..000000000 --- a/core/src/main/aidl/com/aocate/presto/service/IOnInfoListenerCallback_0_8.aidl +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2011, Aocate, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.aocate.presto.service; - -interface IOnInfoListenerCallback_0_8 { - boolean onInfo(int what, int extra); -} \ No newline at end of file diff --git a/core/src/main/aidl/com/aocate/presto/service/IOnPitchAdjustmentAvailableChangedListenerCallback_0_8.aidl b/core/src/main/aidl/com/aocate/presto/service/IOnPitchAdjustmentAvailableChangedListenerCallback_0_8.aidl deleted file mode 100644 index 41223a97b..000000000 --- a/core/src/main/aidl/com/aocate/presto/service/IOnPitchAdjustmentAvailableChangedListenerCallback_0_8.aidl +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2011, Aocate, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.aocate.presto.service; - -interface IOnPitchAdjustmentAvailableChangedListenerCallback_0_8 { - void onPitchAdjustmentAvailableChanged(boolean pitchAdjustmentAvailable); -} \ No newline at end of file diff --git a/core/src/main/aidl/com/aocate/presto/service/IOnPreparedListenerCallback_0_8.aidl b/core/src/main/aidl/com/aocate/presto/service/IOnPreparedListenerCallback_0_8.aidl deleted file mode 100644 index 7be8f1237..000000000 --- a/core/src/main/aidl/com/aocate/presto/service/IOnPreparedListenerCallback_0_8.aidl +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2011, Aocate, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.aocate.presto.service; - -interface IOnPreparedListenerCallback_0_8 { - void onPrepared(); -} \ No newline at end of file diff --git a/core/src/main/aidl/com/aocate/presto/service/IOnSeekCompleteListenerCallback_0_8.aidl b/core/src/main/aidl/com/aocate/presto/service/IOnSeekCompleteListenerCallback_0_8.aidl deleted file mode 100644 index 5bdda98b6..000000000 --- a/core/src/main/aidl/com/aocate/presto/service/IOnSeekCompleteListenerCallback_0_8.aidl +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2011, Aocate, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.aocate.presto.service; - -interface IOnSeekCompleteListenerCallback_0_8 { - void onSeekComplete(); -} \ No newline at end of file diff --git a/core/src/main/aidl/com/aocate/presto/service/IOnSpeedAdjustmentAvailableChangedListenerCallback_0_8.aidl b/core/src/main/aidl/com/aocate/presto/service/IOnSpeedAdjustmentAvailableChangedListenerCallback_0_8.aidl deleted file mode 100644 index a69c1cf34..000000000 --- a/core/src/main/aidl/com/aocate/presto/service/IOnSpeedAdjustmentAvailableChangedListenerCallback_0_8.aidl +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2011, Aocate, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.aocate.presto.service; - -interface IOnSpeedAdjustmentAvailableChangedListenerCallback_0_8 { - void onSpeedAdjustmentAvailableChanged(boolean speedAdjustmentAvailable); -} \ No newline at end of file diff --git a/core/src/main/aidl/com/aocate/presto/service/IPlayMedia_0_8.aidl b/core/src/main/aidl/com/aocate/presto/service/IPlayMedia_0_8.aidl deleted file mode 100644 index 12a6047de..000000000 --- a/core/src/main/aidl/com/aocate/presto/service/IPlayMedia_0_8.aidl +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2011, Aocate, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.aocate.presto.service; - -import com.aocate.presto.service.IDeathCallback_0_8; -import com.aocate.presto.service.IOnBufferingUpdateListenerCallback_0_8; -import com.aocate.presto.service.IOnCompletionListenerCallback_0_8; -import com.aocate.presto.service.IOnErrorListenerCallback_0_8; -import com.aocate.presto.service.IOnPitchAdjustmentAvailableChangedListenerCallback_0_8; -import com.aocate.presto.service.IOnPreparedListenerCallback_0_8; -import com.aocate.presto.service.IOnSeekCompleteListenerCallback_0_8; -import com.aocate.presto.service.IOnSpeedAdjustmentAvailableChangedListenerCallback_0_8; -import com.aocate.presto.service.IOnInfoListenerCallback_0_8; - -interface IPlayMedia_0_8 { - boolean canSetPitch(long sessionId); - boolean canSetSpeed(long sessionId); - float getCurrentPitchStepsAdjustment(long sessionId); - int getCurrentPosition(long sessionId); - float getCurrentSpeedMultiplier(long sessionId); - int getDuration(long sessionId); - float getMaxSpeedMultiplier(long sessionId); - float getMinSpeedMultiplier(long sessionId); - int getVersionCode(); - String getVersionName(); - boolean isLooping(long sessionId); - boolean isPlaying(long sessionId); - void pause(long sessionId); - void prepare(long sessionId); - void prepareAsync(long sessionId); - void registerOnBufferingUpdateCallback(long sessionId, IOnBufferingUpdateListenerCallback_0_8 cb); - void registerOnCompletionCallback(long sessionId, IOnCompletionListenerCallback_0_8 cb); - void registerOnErrorCallback(long sessionId, IOnErrorListenerCallback_0_8 cb); - void registerOnInfoCallback(long sessionId, IOnInfoListenerCallback_0_8 cb); - void registerOnPitchAdjustmentAvailableChangedCallback(long sessionId, IOnPitchAdjustmentAvailableChangedListenerCallback_0_8 cb); - void registerOnPreparedCallback(long sessionId, IOnPreparedListenerCallback_0_8 cb); - void registerOnSeekCompleteCallback(long sessionId, IOnSeekCompleteListenerCallback_0_8 cb); - void registerOnSpeedAdjustmentAvailableChangedCallback(long sessionId, IOnSpeedAdjustmentAvailableChangedListenerCallback_0_8 cb); - void release(long sessionId); - void reset(long sessionId); - void seekTo(long sessionId, int msec); - void setAudioStreamType(long sessionId, int streamtype); - void setDataSourceString(long sessionId, String path); - void setDataSourceUri(long sessionId, in Uri uri); - void setEnableSpeedAdjustment(long sessionId, boolean enableSpeedAdjustment); - void setLooping(long sessionId, boolean looping); - void setPitchStepsAdjustment(long sessionId, float pitchSteps); - void setPlaybackPitch(long sessionId, float f); - void setPlaybackSpeed(long sessionId, float f); - void setSpeedAdjustmentAlgorithm(long sessionId, int algorithm); - void setVolume(long sessionId, float left, float right); - void start(long sessionId); - long startSession(IDeathCallback_0_8 cb); - void stop(long sessionId); - void unregisterOnBufferingUpdateCallback(long sessionId, IOnBufferingUpdateListenerCallback_0_8 cb); - void unregisterOnCompletionCallback(long sessionId, IOnCompletionListenerCallback_0_8 cb); - void unregisterOnErrorCallback(long sessionId, IOnErrorListenerCallback_0_8 cb); - void unregisterOnInfoCallback(long sessionId, IOnInfoListenerCallback_0_8 cb); - void unregisterOnPitchAdjustmentAvailableChangedCallback(long sessionId, IOnPitchAdjustmentAvailableChangedListenerCallback_0_8 cb); - void unregisterOnPreparedCallback(long sessionId, IOnPreparedListenerCallback_0_8 cb); - void unregisterOnSeekCompleteCallback(long sessionId, IOnSeekCompleteListenerCallback_0_8 cb); - void unregisterOnSpeedAdjustmentAvailableChangedCallback(long sessionId, IOnSpeedAdjustmentAvailableChangedListenerCallback_0_8 cb); -} \ No newline at end of file diff --git a/core/src/main/java/com/aocate/media/AndroidMediaPlayer.java b/core/src/main/java/com/aocate/media/AndroidMediaPlayer.java deleted file mode 100644 index 7c2ea3d61..000000000 --- a/core/src/main/java/com/aocate/media/AndroidMediaPlayer.java +++ /dev/null @@ -1,470 +0,0 @@ -// Copyright 2011, Aocate, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.aocate.media; - -import android.content.Context; -import android.media.MediaPlayer; -import android.net.Uri; -import android.util.Log; - -import java.io.IOException; - -public class AndroidMediaPlayer extends MediaPlayerImpl { - private final static String AMP_TAG = "AocateAndroidMediaPlayer"; - - // private static final long TIMEOUT_DURATION_MS = 500; - - android.media.MediaPlayer mp = null; - - private android.media.MediaPlayer.OnBufferingUpdateListener onBufferingUpdateListener = new android.media.MediaPlayer.OnBufferingUpdateListener() { - public void onBufferingUpdate(android.media.MediaPlayer mp, int percent) { - if (owningMediaPlayer != null) { - owningMediaPlayer.lock.lock(); - try { - if ((owningMediaPlayer.onBufferingUpdateListener != null) - && (owningMediaPlayer.mpi == AndroidMediaPlayer.this)) { - owningMediaPlayer.onBufferingUpdateListener.onBufferingUpdate(owningMediaPlayer, percent); - } - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - } - }; - - private android.media.MediaPlayer.OnCompletionListener onCompletionListener = new android.media.MediaPlayer.OnCompletionListener() { - public void onCompletion(android.media.MediaPlayer mp) { - Log.d(AMP_TAG, "onCompletionListener being called"); - if (owningMediaPlayer != null) { - owningMediaPlayer.lock.lock(); - try { - if (owningMediaPlayer.onCompletionListener != null) { - owningMediaPlayer.onCompletionListener.onCompletion(owningMediaPlayer); - } - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - } - }; - - private android.media.MediaPlayer.OnErrorListener onErrorListener = new android.media.MediaPlayer.OnErrorListener() { - public boolean onError(android.media.MediaPlayer mp, int what, int extra) { - // Once we're in errored state, any received messages are going to be junked - if (owningMediaPlayer != null) { - owningMediaPlayer.lock.lock(); - try { - if (owningMediaPlayer.onErrorListener != null) { - return owningMediaPlayer.onErrorListener.onError(owningMediaPlayer, what, extra); - } - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - return false; - } - }; - - private android.media.MediaPlayer.OnInfoListener onInfoListener = new android.media.MediaPlayer.OnInfoListener() { - public boolean onInfo(android.media.MediaPlayer mp, int what, int extra) { - if (owningMediaPlayer != null) { - owningMediaPlayer.lock.lock(); - try { - if ((owningMediaPlayer.onInfoListener != null) - && (owningMediaPlayer.mpi == AndroidMediaPlayer.this)) { - return owningMediaPlayer.onInfoListener.onInfo(owningMediaPlayer, what, extra); - } - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - return false; - } - }; - - // We have to assign this.onPreparedListener because the - // onPreparedListener in owningMediaPlayer sets the state - // to PREPARED. Due to prepareAsync, that's the only - // reasonable place to do it - // The others it just didn't make sense to have a setOnXListener that didn't use the parameter - private android.media.MediaPlayer.OnPreparedListener onPreparedListener = new android.media.MediaPlayer.OnPreparedListener() { - public void onPrepared(android.media.MediaPlayer mp) { - Log.d(AMP_TAG, "Calling onPreparedListener.onPrepared()"); - if (AndroidMediaPlayer.this.owningMediaPlayer != null) { - AndroidMediaPlayer.this.lockMuteOnPreparedCount.lock(); - try { - if (AndroidMediaPlayer.this.muteOnPreparedCount > 0) { - AndroidMediaPlayer.this.muteOnPreparedCount--; - } - else { - AndroidMediaPlayer.this.muteOnPreparedCount = 0; - if (AndroidMediaPlayer.this.owningMediaPlayer.onPreparedListener != null) { - Log.d(AMP_TAG, "Invoking AndroidMediaPlayer.this.owningMediaPlayer.onPreparedListener.onPrepared"); - AndroidMediaPlayer.this.owningMediaPlayer.onPreparedListener.onPrepared(AndroidMediaPlayer.this.owningMediaPlayer); - } - } - } - finally { - AndroidMediaPlayer.this.lockMuteOnPreparedCount.unlock(); - } - if (owningMediaPlayer.mpi != AndroidMediaPlayer.this) { - Log.d(AMP_TAG, "owningMediaPlayer has changed implementation"); - } - } - } - }; - - private android.media.MediaPlayer.OnSeekCompleteListener onSeekCompleteListener = new android.media.MediaPlayer.OnSeekCompleteListener() { - public void onSeekComplete(android.media.MediaPlayer mp) { - if (owningMediaPlayer != null) { - owningMediaPlayer.lock.lock(); - try { - lockMuteOnSeekCount.lock(); - try { - if (AndroidMediaPlayer.this.muteOnSeekCount > 0) { - AndroidMediaPlayer.this.muteOnSeekCount--; - } - else { - AndroidMediaPlayer.this.muteOnSeekCount = 0; - if (AndroidMediaPlayer.this.owningMediaPlayer.onSeekCompleteListener != null) { - owningMediaPlayer.onSeekCompleteListener.onSeekComplete(owningMediaPlayer); - } - } - } - finally { - lockMuteOnSeekCount.unlock(); - } - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - } - }; - - public AndroidMediaPlayer(com.aocate.media.MediaPlayer owningMediaPlayer, Context context) { - super(owningMediaPlayer, context); - - mp = new MediaPlayer(); - -// final ReentrantLock lock = new ReentrantLock(); -// Handler handler = new Handler(Looper.getMainLooper()) { -// @Override -// public void handleMessage(Message msg) { -// Log.d(AMP_TAG, "Instantiating new AndroidMediaPlayer from Handler"); -// lock.lock(); -// if (mp == null) { -// mp = new MediaPlayer(); -// } -// lock.unlock(); -// } -// }; -// -// long endTime = System.currentTimeMillis() + TIMEOUT_DURATION_MS; -// -// while (true) { -// // Retry messages until mp isn't null or it's time to give up -// handler.sendMessage(handler.obtainMessage()); -// if ((mp != null) -// || (endTime < System.currentTimeMillis())) { -// break; -// } -// try { -// Thread.sleep(50); -// } catch (InterruptedException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } -// } - - if (mp == null) { - throw new IllegalStateException("Did not instantiate android.media.MediaPlayer successfully"); - } - - mp.setOnBufferingUpdateListener(this.onBufferingUpdateListener); - mp.setOnCompletionListener(this.onCompletionListener); - mp.setOnErrorListener(this.onErrorListener); - mp.setOnInfoListener(this.onInfoListener); - Log.d(AMP_TAG, " ++++++++++++++++++++++++++++++++ Setting prepared listener to this.onPreparedListener"); - mp.setOnPreparedListener(this.onPreparedListener); - mp.setOnSeekCompleteListener(this.onSeekCompleteListener); - } - - @Override - public boolean canSetPitch() { - return false; - } - - @Override - public boolean canSetSpeed() { - return false; - } - - @Override - public float getCurrentPitchStepsAdjustment() { - return 0; - } - - @Override - public int getCurrentPosition() { - owningMediaPlayer.lock.lock(); - try { - return mp.getCurrentPosition(); - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - @Override - public float getCurrentSpeedMultiplier() { - return 1f; - } - - @Override - public int getDuration() { - owningMediaPlayer.lock.lock(); - try { - return mp.getDuration(); - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - @Override - public float getMaxSpeedMultiplier() { - return 1f; - } - - @Override - public float getMinSpeedMultiplier() { - return 1f; - } - - @Override - public boolean isLooping() { - owningMediaPlayer.lock.lock(); - try { - return mp.isLooping(); - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - @Override - public boolean isPlaying() { - owningMediaPlayer.lock.lock(); - try { - return mp.isPlaying(); - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - @Override - public void pause() { - owningMediaPlayer.lock.lock(); - try { - mp.pause(); - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - @Override - public void prepare() throws IllegalStateException, IOException { - owningMediaPlayer.lock.lock(); - Log.d(AMP_TAG, "prepare()"); - try { - mp.prepare(); - Log.d(AMP_TAG, "Finish prepare()"); - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - @Override - public void prepareAsync() { - mp.prepareAsync(); - } - - @Override - public void release() { - owningMediaPlayer.lock.lock(); - try { - if (mp != null) { - Log.d(AMP_TAG, "mp.release()"); - mp.release(); - } - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - @Override - public void reset() { - owningMediaPlayer.lock.lock(); - try { - mp.reset(); - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - @Override - public void seekTo(int msec) throws IllegalStateException { - owningMediaPlayer.lock.lock(); - try { - mp.setOnSeekCompleteListener(this.onSeekCompleteListener); - mp.seekTo(msec); - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - @Override - public void setAudioStreamType(int streamtype) { - owningMediaPlayer.lock.lock(); - try { - mp.setAudioStreamType(streamtype); - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - @Override - public void setDataSource(Context context, Uri uri) - throws IllegalArgumentException, IllegalStateException, IOException { - owningMediaPlayer.lock.lock(); - try { - Log.d(AMP_TAG, "setDataSource(context, " + uri.toString() + ")"); - mp.setDataSource(context, uri); - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - @Override - public void setDataSource(String path) throws IllegalArgumentException, - IllegalStateException, IOException { - owningMediaPlayer.lock.lock(); - try { - Log.d(AMP_TAG, "setDataSource(" + path + ")"); - mp.setDataSource(path); - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - @Override - public void setEnableSpeedAdjustment(boolean enableSpeedAdjustment) { - // Can't! - } - - @Override - public void setLooping(boolean loop) { - owningMediaPlayer.lock.lock(); - try { - mp.setLooping(loop); - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - @Override - public void setPitchStepsAdjustment(float pitchSteps) { - // Can't! - } - - @Override - public void setPlaybackPitch(float f) { - // Can't! - } - - @Override - public void setPlaybackSpeed(float f) { - // Can't! - Log.d(AMP_TAG, "setPlaybackSpeed(" + f + ")"); - } - - @Override - public void setSpeedAdjustmentAlgorithm(int algorithm) { - // Can't! - Log.d(AMP_TAG, "setSpeedAdjustmentAlgorithm(" + algorithm + ")"); - } - - @Override - public void setVolume(float leftVolume, float rightVolume) { - owningMediaPlayer.lock.lock(); - try { - mp.setVolume(leftVolume, rightVolume); - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - @Override - public void setWakeMode(Context context, int mode) { - owningMediaPlayer.lock.lock(); - try { - if (mode != 0) { - mp.setWakeMode(context, mode); - } - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - @Override - public void start() { - owningMediaPlayer.lock.lock(); - try { - mp.start(); - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - @Override - public void stop() { - owningMediaPlayer.lock.lock(); - try { - mp.stop(); - } - finally { - owningMediaPlayer.lock.unlock(); - } - } -} diff --git a/core/src/main/java/com/aocate/media/MediaPlayer.java b/core/src/main/java/com/aocate/media/MediaPlayer.java deleted file mode 100644 index 79e63d03d..000000000 --- a/core/src/main/java/com/aocate/media/MediaPlayer.java +++ /dev/null @@ -1,1310 +0,0 @@ -// Copyright 2011, Aocate, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.aocate.media; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.media.AudioManager; -import android.net.Uri; -import android.os.Handler; -import android.os.Handler.Callback; -import android.os.IBinder; -import android.os.Message; -import android.util.Log; - -import java.io.IOException; -import java.util.List; -import java.util.concurrent.locks.ReentrantLock; - -import de.danoeh.antennapod.core.BuildConfig; - -public class MediaPlayer { - public static final String TAG = "com.aocate.media.MediaPlayer"; - - public interface OnBufferingUpdateListener { - public abstract void onBufferingUpdate(MediaPlayer arg0, int percent); - } - - public interface OnCompletionListener { - public abstract void onCompletion(MediaPlayer arg0); - } - - public interface OnErrorListener { - public abstract boolean onError(MediaPlayer arg0, int what, int extra); - } - - public interface OnInfoListener { - public abstract boolean onInfo(MediaPlayer arg0, int what, int extra); - } - - public interface OnPitchAdjustmentAvailableChangedListener { - /** - * @param arg0 The owning media player - * @param pitchAdjustmentAvailable True if pitch adjustment is available, false if not - */ - public abstract void onPitchAdjustmentAvailableChanged( - MediaPlayer arg0, boolean pitchAdjustmentAvailable); - } - - public interface OnPreparedListener { - public abstract void onPrepared(MediaPlayer arg0); - } - - public interface OnSeekCompleteListener { - public abstract void onSeekComplete(MediaPlayer arg0); - } - - public interface OnSpeedAdjustmentAvailableChangedListener { - /** - * @param arg0 The owning media player - * @param speedAdjustmentAvailable True if speed adjustment is available, false if not - */ - public abstract void onSpeedAdjustmentAvailableChanged( - MediaPlayer arg0, boolean speedAdjustmentAvailable); - } - - public enum State { - IDLE, INITIALIZED, PREPARED, STARTED, PAUSED, STOPPED, PREPARING, PLAYBACK_COMPLETED, END, ERROR - } - - private static Uri SPEED_ADJUSTMENT_MARKET_URI = Uri - .parse("market://details?id=com.aocate.presto"); - - private static Intent prestoMarketIntent = null; - - public static final int MEDIA_ERROR_SERVER_DIED = android.media.MediaPlayer.MEDIA_ERROR_SERVER_DIED; - public static final int MEDIA_ERROR_UNKNOWN = android.media.MediaPlayer.MEDIA_ERROR_UNKNOWN; - public static final int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = android.media.MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK; - - /** - * Indicates whether the specified action can be used as an intent. This - * method queries the package manager for installed packages that can - * respond to an intent with the specified action. If no suitable package is - * found, this method returns false. - * - * @param context The application's environment. - * @param action The Intent action to check for availability. - * @return True if an Intent with the specified action can be sent and - * responded to, false otherwise. - */ - public static boolean isIntentAvailable(Context context, String action) { - final PackageManager packageManager = context.getPackageManager(); - final Intent intent = new Intent(action); - List list = packageManager.queryIntentServices(intent, - PackageManager.MATCH_DEFAULT_ONLY); - return list.size() > 0; - } - - /** - * Returns an explicit Intent for a service that accepts the given Intent - * or null if no such service was found. - * - * @param context The application's environment. - * @param action The Intent action to check for availability. - * @return The explicit service Intent or null if no service was found. - */ - public static Intent getPrestoServiceIntent(Context context, String action) { - final PackageManager packageManager = context.getPackageManager(); - final Intent actionIntent = new Intent(action); - List list = packageManager.queryIntentServices(actionIntent, - PackageManager.MATCH_DEFAULT_ONLY); - if (list.size() > 0) { - ResolveInfo first = list.get(0); - if (first.serviceInfo != null) { - Intent intent = new Intent(); - intent.setComponent(new ComponentName(first.serviceInfo.packageName, - first.serviceInfo.name)); - Log.i(TAG, "Returning intent:" + intent.toString()); - return intent; - } else { - Log.e(TAG, "Found service that accepts " + action + ", but serviceInfo was null"); - return null; - } - } else { - return null; - } - } - - /** - * Indicates whether the Presto library is installed - * - * @param context The context to use to query the package manager. - * @return True if the Presto library is installed, false if not. - */ - public static boolean isPrestoLibraryInstalled(Context context) { - return isIntentAvailable(context, ServiceBackedMediaPlayer.INTENT_NAME); - } - - /** - * Return an Intent that opens the Android Market page for the speed - * alteration library - * - * @return The Intent for the Presto library on the Android Market - */ - public static Intent getPrestoMarketIntent() { - if (prestoMarketIntent == null) { - prestoMarketIntent = new Intent(Intent.ACTION_VIEW, - SPEED_ADJUSTMENT_MARKET_URI); - } - return prestoMarketIntent; - } - - /** - * Open the Android Market page for the Presto library - * - * @param context The context from which to open the Android Market page - */ - public static void openPrestoMarketIntent(Context context) { - context.startActivity(getPrestoMarketIntent()); - } - - private static final String MP_TAG = "AocateReplacementMediaPlayer"; - - private static final double PITCH_STEP_CONSTANT = 1.0594630943593; - - private AndroidMediaPlayer amp = null; - // This is whether speed adjustment should be enabled (by the Service) - // To avoid the Service entirely, set useService to false - protected boolean enableSpeedAdjustment = true; - private int lastKnownPosition = 0; - // In some cases, we're going to have to replace the - // android.media.MediaPlayer on the fly, and we don't want to touch the - // wrong media player, so lock it way too much. - ReentrantLock lock = new ReentrantLock(); - private int mAudioStreamType = AudioManager.STREAM_MUSIC; - private Context mContext; - private boolean mIsLooping = false; - private float mLeftVolume = 1f; - private float mPitchStepsAdjustment = 0f; - private float mRightVolume = 1f; - private float mSpeedMultiplier = 1f; - private int mWakeMode = 0; - MediaPlayerImpl mpi = null; - protected boolean pitchAdjustmentAvailable = false; - private ServiceBackedMediaPlayer sbmp = null; - protected boolean speedAdjustmentAvailable = false; - - private Handler mServiceDisconnectedHandler = null; - - // Some parts of state cannot be found by calling MediaPlayerImpl functions, - // so store our own state. This also helps copy state when changing - // implementations - State state = State.INITIALIZED; - String stringDataSource = null; - Uri uriDataSource = null; - private boolean useService = false; - - // Naming Convention for Listeners - // Most listeners can both be set by clients and called by MediaPlayImpls - // There are a few that have to do things in this class as well as calling - // the function. In all cases, onX is what is called by MediaPlayerImpl - // If there is work to be done in this class, then the listener that is - // set by setX is X (with the first letter lowercase). - OnBufferingUpdateListener onBufferingUpdateListener = null; - OnCompletionListener onCompletionListener = null; - OnErrorListener onErrorListener = null; - OnInfoListener onInfoListener = null; - - // Special case. Pitch adjustment ceases to be available when we switch - // to the android.media.MediaPlayer (though it is not guaranteed to be - // available when using the ServiceBackedMediaPlayer) - OnPitchAdjustmentAvailableChangedListener onPitchAdjustmentAvailableChangedListener = new OnPitchAdjustmentAvailableChangedListener() { - public void onPitchAdjustmentAvailableChanged(MediaPlayer arg0, - boolean pitchAdjustmentAvailable) { - lock.lock(); - try { - Log - .d( - MP_TAG, - "onPitchAdjustmentAvailableChangedListener.onPitchAdjustmentAvailableChanged being called"); - if (MediaPlayer.this.pitchAdjustmentAvailable != pitchAdjustmentAvailable) { - Log.d(MP_TAG, "Pitch adjustment state has changed from " - + MediaPlayer.this.pitchAdjustmentAvailable - + " to " + pitchAdjustmentAvailable); - MediaPlayer.this.pitchAdjustmentAvailable = pitchAdjustmentAvailable; - if (MediaPlayer.this.pitchAdjustmentAvailableChangedListener != null) { - MediaPlayer.this.pitchAdjustmentAvailableChangedListener - .onPitchAdjustmentAvailableChanged(arg0, - pitchAdjustmentAvailable); - } - } - } finally { - lock.unlock(); - } - } - }; - OnPitchAdjustmentAvailableChangedListener pitchAdjustmentAvailableChangedListener = null; - - MediaPlayer.OnPreparedListener onPreparedListener = new MediaPlayer.OnPreparedListener() { - public void onPrepared(MediaPlayer arg0) { - Log.d(MP_TAG, "onPreparedListener 242 setting state to PREPARED"); - MediaPlayer.this.state = State.PREPARED; - if (MediaPlayer.this.preparedListener != null) { - Log.d(MP_TAG, "Calling preparedListener"); - MediaPlayer.this.preparedListener.onPrepared(arg0); - } - Log.d(MP_TAG, "Wrap up onPreparedListener"); - } - }; - - OnPreparedListener preparedListener = null; - OnSeekCompleteListener onSeekCompleteListener = null; - - // Special case. Speed adjustment ceases to be available when we switch - // to the android.media.MediaPlayer (though it is not guaranteed to be - // available when using the ServiceBackedMediaPlayer) - OnSpeedAdjustmentAvailableChangedListener onSpeedAdjustmentAvailableChangedListener = new OnSpeedAdjustmentAvailableChangedListener() { - public void onSpeedAdjustmentAvailableChanged(MediaPlayer arg0, - boolean speedAdjustmentAvailable) { - lock.lock(); - try { - Log - .d( - MP_TAG, - "onSpeedAdjustmentAvailableChangedListener.onSpeedAdjustmentAvailableChanged being called"); - if (MediaPlayer.this.speedAdjustmentAvailable != speedAdjustmentAvailable) { - Log.d(MP_TAG, "Speed adjustment state has changed from " - + MediaPlayer.this.speedAdjustmentAvailable - + " to " + speedAdjustmentAvailable); - MediaPlayer.this.speedAdjustmentAvailable = speedAdjustmentAvailable; - if (MediaPlayer.this.speedAdjustmentAvailableChangedListener != null) { - MediaPlayer.this.speedAdjustmentAvailableChangedListener - .onSpeedAdjustmentAvailableChanged(arg0, - speedAdjustmentAvailable); - } - } - } finally { - lock.unlock(); - } - } - }; - OnSpeedAdjustmentAvailableChangedListener speedAdjustmentAvailableChangedListener = null; - - private int speedAdjustmentAlgorithm = SpeedAdjustmentAlgorithm.SONIC; - - public MediaPlayer(final Context context) { - this(context, true); - } - - public MediaPlayer(final Context context, boolean useService) { - this.mContext = context; - this.useService = useService; - - // So here's the major problem - // Sometimes the service won't exist or won't be connected, - // so start with an android.media.MediaPlayer, and when - // the service is connected, use that from then on - this.mpi = this.amp = new AndroidMediaPlayer(this, context); - - // setupMpi will go get the Service, if it can, then bring that - // implementation into sync - Log.d(MP_TAG, "setupMpi"); - setupMpi(context); - } - - private boolean invalidServiceConnectionConfiguration() { - if (!(this.mpi instanceof ServiceBackedMediaPlayer)) { - if (this.useService && isPrestoLibraryInstalled()) { - // In this case, the Presto library has been installed - // or something while playing sound - // We could be using the service, but we're not - Log.d(MP_TAG, "We could be using the service, but we're not 316"); - return true; - } - // If useService is false, then we shouldn't be using the SBMP - // If the Presto library isn't installed, ditto - Log.d(MP_TAG, "this.mpi is not a ServiceBackedMediaPlayer, but we couldn't use it anyway 321"); - return false; - } else { - if (BuildConfig.DEBUG && !(this.mpi instanceof ServiceBackedMediaPlayer)) - throw new AssertionError(); - if (this.useService && isPrestoLibraryInstalled()) { - // We should be using the service, and we are. Great! - Log.d(MP_TAG, "We could be using a ServiceBackedMediaPlayer and we are 327"); - return false; - } - // We're trying to use the service when we shouldn't, - // that's an invalid configuration - Log.d(MP_TAG, "We're trying to use a ServiceBackedMediaPlayer but we shouldn't be 332"); - return true; - } - } - - private void setupMpi(final Context context) { - lock.lock(); - try { - Log.d(MP_TAG, "setupMpi 336"); - // Check if the client wants to use the service at all, - // then if we're already using the right kind of media player - if (this.useService && isPrestoLibraryInstalled()) { - if ((this.mpi != null) - && (this.mpi instanceof ServiceBackedMediaPlayer)) { - Log.d(MP_TAG, "Already using ServiceBackedMediaPlayer"); - return; - } - if (this.sbmp == null) { - Log.d(MP_TAG, "Instantiating new ServiceBackedMediaPlayer 346"); - this.sbmp = new ServiceBackedMediaPlayer(this, context, - new ServiceConnection() { - public void onServiceConnected( - ComponentName className, - final IBinder service) { - Thread t = new Thread(new Runnable() { - public void run() { - // This lock probably isn't granular - // enough - MediaPlayer.this.lock.lock(); - Log.d(MP_TAG, - "onServiceConnected 257"); - try { - MediaPlayer.this - .switchMediaPlayerImpl( - MediaPlayer.this.amp, - MediaPlayer.this.sbmp); - Log.d(MP_TAG, "End onServiceConnected 362"); - } finally { - MediaPlayer.this.lock.unlock(); - } - } - }); - t.start(); - } - - public void onServiceDisconnected( - ComponentName className) { - MediaPlayer.this.lock.lock(); - try { - // Can't get any more useful information - // out of sbmp - if (MediaPlayer.this.sbmp != null) { - MediaPlayer.this.sbmp.release(); - } - // Unlike most other cases, sbmp gets set - // to null since there's nothing useful - // backing it now - MediaPlayer.this.sbmp = null; - - if (mServiceDisconnectedHandler == null) { - mServiceDisconnectedHandler = new Handler(new Callback() { - public boolean handleMessage(Message msg) { - // switchMediaPlayerImpl won't try to - // clone anything from null - lock.lock(); - try { - if (MediaPlayer.this.amp == null) { - // This should never be in this state - MediaPlayer.this.amp = new AndroidMediaPlayer( - MediaPlayer.this, - MediaPlayer.this.mContext); - } - // Use sbmp instead of null in case by some miracle it's - // been restored in the meantime - MediaPlayer.this.switchMediaPlayerImpl( - MediaPlayer.this.sbmp, - MediaPlayer.this.amp); - return true; - } finally { - lock.unlock(); - } - } - }); - } - - // This code needs to execute on the - // original thread to instantiate - // the new object in the right place - mServiceDisconnectedHandler - .sendMessage( - mServiceDisconnectedHandler - .obtainMessage()); - // Note that we do NOT want to set - // useService. useService is about - // what the user wants, not what they - // get - } finally { - MediaPlayer.this.lock.unlock(); - } - } - } - ); - } - switchMediaPlayerImpl(this.amp, this.sbmp); - } else { - if ((this.mpi != null) - && (this.mpi instanceof AndroidMediaPlayer)) { - Log.d(MP_TAG, "Already using AndroidMediaPlayer"); - return; - } - if (this.amp == null) { - Log.d(MP_TAG, "Instantiating new AndroidMediaPlayer (this should be impossible)"); - this.amp = new AndroidMediaPlayer(this, context); - } - switchMediaPlayerImpl(this.sbmp, this.amp); - } - } finally { - lock.unlock(); - } - } - - private void switchMediaPlayerImpl(MediaPlayerImpl from, MediaPlayerImpl to) { - lock.lock(); - try { - Log.d(MP_TAG, "switchMediaPlayerImpl"); - if ((from == to) - // Same object, nothing to synchronize - || (to == null) - // Nothing to copy to (maybe this should throw an error?) - || ((to instanceof ServiceBackedMediaPlayer) && !((ServiceBackedMediaPlayer) to).isConnected()) - // ServiceBackedMediaPlayer hasn't yet connected, onServiceConnected will take care of the transition - || (MediaPlayer.this.state == State.END)) { - // State.END is after a release(), no further functions should - // be called on this class and from is likely to have problems - // retrieving state that won't be used anyway - return; - } - // Extract all that we can from the existing implementation - // and copy it to the new implementation - - Log.d(MP_TAG, "switchMediaPlayerImpl(), current state is " - + this.state.toString()); - - to.reset(); - - // Do this first so we don't have to prepare the same - // data file twice - to.setEnableSpeedAdjustment(MediaPlayer.this.enableSpeedAdjustment); - - // This is a reasonable place to set all of these, - // none of them require prepare() or the like first - to.setAudioStreamType(this.mAudioStreamType); - to.setSpeedAdjustmentAlgorithm(this.speedAdjustmentAlgorithm); - to.setLooping(this.mIsLooping); - to.setPitchStepsAdjustment(this.mPitchStepsAdjustment); - Log.d(MP_TAG, "Setting playback speed to " + this.mSpeedMultiplier); - to.setPlaybackSpeed(this.mSpeedMultiplier); - to.setVolume(MediaPlayer.this.mLeftVolume, - MediaPlayer.this.mRightVolume); - to.setWakeMode(this.mContext, this.mWakeMode); - - Log.d(MP_TAG, "asserting at least one data source is null"); - assert ((MediaPlayer.this.stringDataSource == null) || (MediaPlayer.this.uriDataSource == null)); - - if (uriDataSource != null) { - Log.d(MP_TAG, "switchMediaPlayerImpl(): uriDataSource != null"); - try { - to.setDataSource(this.mContext, uriDataSource); - } catch (IllegalArgumentException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IllegalStateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - if (stringDataSource != null) { - Log.d(MP_TAG, - "switchMediaPlayerImpl(): stringDataSource != null"); - try { - to.setDataSource(stringDataSource); - } catch (IllegalArgumentException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IllegalStateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - if ((this.state == State.PREPARED) - || (this.state == State.PREPARING) - || (this.state == State.PAUSED) - || (this.state == State.STOPPED) - || (this.state == State.STARTED) - || (this.state == State.PLAYBACK_COMPLETED)) { - Log.d(MP_TAG, "switchMediaPlayerImpl(): prepare and seek"); - // Use prepare here instead of prepareAsync so that - // we wait for it to be ready before we try to use it - try { - to.muteNextOnPrepare(); - to.prepare(); - } catch (IllegalStateException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - int seekPos = 0; - if (from != null) { - seekPos = from.getCurrentPosition(); - } else if (this.lastKnownPosition < to.getDuration()) { - // This can happen if the Service unexpectedly - // disconnected. Because it would result in too much - // information being passed around, we don't constantly - // poll for the lastKnownPosition, but we'll save it - // when getCurrentPosition is called - seekPos = this.lastKnownPosition; - } - to.muteNextSeek(); - to.seekTo(seekPos); - } - if ((from != null) - && from.isPlaying()) { - from.pause(); - } - if ((this.state == State.STARTED) - || (this.state == State.PAUSED) - || (this.state == State.STOPPED)) { - Log.d(MP_TAG, "switchMediaPlayerImpl(): start"); - if (to != null) { - to.start(); - } - } - - if (this.state == State.PAUSED) { - Log.d(MP_TAG, "switchMediaPlayerImpl(): paused"); - if (to != null) { - to.pause(); - } - } else if (this.state == State.STOPPED) { - Log.d(MP_TAG, "switchMediaPlayerImpl(): stopped"); - if (to != null) { - to.stop(); - } - } - - this.mpi = to; - - // Cheating here by relying on the side effect in - // on(Pitch|Speed)AdjustmentAvailableChanged - if ((to.canSetPitch() != this.pitchAdjustmentAvailable) - && (this.onPitchAdjustmentAvailableChangedListener != null)) { - this.onPitchAdjustmentAvailableChangedListener - .onPitchAdjustmentAvailableChanged(this, to - .canSetPitch()); - } - if ((to.canSetSpeed() != this.speedAdjustmentAvailable) - && (this.onSpeedAdjustmentAvailableChangedListener != null)) { - this.onSpeedAdjustmentAvailableChangedListener - .onSpeedAdjustmentAvailableChanged(this, to - .canSetSpeed()); - } - Log.d(MP_TAG, "switchMediaPlayerImpl() 625 " + this.state.toString()); - } finally { - lock.unlock(); - } - } - - /** - * Returns true if pitch can be changed at this moment - * - * @return True if pitch can be changed - */ - public boolean canSetPitch() { - lock.lock(); - try { - return this.mpi.canSetPitch(); - } finally { - lock.unlock(); - } - } - - /** - * Returns true if speed can be changed at this moment - * - * @return True if speed can be changed - */ - public boolean canSetSpeed() { - lock.lock(); - try { - return this.mpi.canSetSpeed(); - } finally { - lock.unlock(); - } - } - - protected void finalize() throws Throwable { - lock.lock(); - try { - Log.d(MP_TAG, "finalize() 626"); - this.release(); - } finally { - lock.unlock(); - } - } - - /** - * Returns the number of steps (in a musical scale) by which playback is - * currently shifted. When greater than zero, pitch is shifted up. When less - * than zero, pitch is shifted down. - * - * @return The number of steps pitch is currently shifted by - */ - public float getCurrentPitchStepsAdjustment() { - lock.lock(); - try { - return this.mpi.getCurrentPitchStepsAdjustment(); - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.getCurrentPosition() - * Accurate only to frame size of encoded data (26 ms for MP3s) - * - * @return Current position (in milliseconds) - */ - public int getCurrentPosition() { - lock.lock(); - try { - return (this.lastKnownPosition = this.mpi.getCurrentPosition()); - } finally { - lock.unlock(); - } - } - - /** - * Returns the current speed multiplier. Defaults to 1.0 (normal speed) - * - * @return The current speed multiplier - */ - public float getCurrentSpeedMultiplier() { - lock.lock(); - try { - return this.mpi.getCurrentSpeedMultiplier(); - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.getDuration() - * - * @return Length of the track (in milliseconds) - */ - public int getDuration() { - lock.lock(); - try { - return this.mpi.getDuration(); - } finally { - lock.unlock(); - } - } - - /** - * Get the maximum value that can be passed to setPlaybackSpeed - * - * @return The maximum speed multiplier - */ - public float getMaxSpeedMultiplier() { - lock.lock(); - try { - return this.mpi.getMaxSpeedMultiplier(); - } finally { - lock.unlock(); - } - } - - /** - * Get the minimum value that can be passed to setPlaybackSpeed - * - * @return The minimum speed multiplier - */ - public float getMinSpeedMultiplier() { - lock.lock(); - try { - return this.mpi.getMinSpeedMultiplier(); - } finally { - lock.unlock(); - } - } - - /** - * Gets the version code of the backing service - * - * @return -1 if ServiceBackedMediaPlayer is not used, 0 if the service is not - * connected, otherwise the version code retrieved from the service - */ - public int getServiceVersionCode() { - lock.lock(); - try { - if (this.mpi instanceof ServiceBackedMediaPlayer) { - return ((ServiceBackedMediaPlayer) this.mpi).getServiceVersionCode(); - } else { - return -1; - } - } finally { - lock.unlock(); - } - } - - /** - * Gets the version name of the backing service - * - * @return null if ServiceBackedMediaPlayer is not used, empty string if - * the service is not connected, otherwise the version name retrieved from - * the service - */ - public String getServiceVersionName() { - lock.lock(); - try { - if (this.mpi instanceof ServiceBackedMediaPlayer) { - return ((ServiceBackedMediaPlayer) this.mpi).getServiceVersionName(); - } else { - return null; - } - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.isLooping() - * - * @return True if the track is looping - */ - public boolean isLooping() { - lock.lock(); - try { - return this.mpi.isLooping(); - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.isPlaying() - * - * @return True if the track is playing - */ - public boolean isPlaying() { - lock.lock(); - try { - return this.mpi.isPlaying(); - } finally { - lock.unlock(); - } - } - - /** - * Returns true if this MediaPlayer has access to the Presto - * library - * - * @return True if the Presto library is installed - */ - public boolean isPrestoLibraryInstalled() { - if ((this.mpi == null) || (this.mpi.mContext == null)) { - return false; - } - return isPrestoLibraryInstalled(this.mpi.mContext); - } - - /** - * Open the Android Market page in the same context as this MediaPlayer - */ - public void openPrestoMarketIntent() { - if ((this.mpi != null) && (this.mpi.mContext != null)) { - openPrestoMarketIntent(this.mpi.mContext); - } - } - - /** - * Functions identically to android.media.MediaPlayer.pause() Pauses the - * track - */ - public void pause() { - lock.lock(); - try { - if (invalidServiceConnectionConfiguration()) { - setupMpi(this.mpi.mContext); - } - this.state = State.PAUSED; - this.mpi.pause(); - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.prepare() Prepares the - * track. This or prepareAsync must be called before start() - */ - public void prepare() throws IllegalStateException, IOException { - lock.lock(); - try { - Log.d(MP_TAG, "prepare() 746 using " + ((this.mpi == null) ? "null (this shouldn't happen)" : this.mpi.getClass().toString()) + " state " + this.state.toString()); - Log.d(MP_TAG, "onPreparedListener is: " + ((this.onPreparedListener == null) ? "null" : "non-null")); - Log.d(MP_TAG, "preparedListener is: " + ((this.preparedListener == null) ? "null" : "non-null")); - if (invalidServiceConnectionConfiguration()) { - setupMpi(this.mpi.mContext); - } - this.mpi.prepare(); - this.state = State.PREPARED; - Log.d(MP_TAG, "prepare() finished 778"); - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.prepareAsync() - * Prepares the track. This or prepare must be called before start() - */ - public void prepareAsync() { - lock.lock(); - try { - Log.d(MP_TAG, "prepareAsync() 779"); - if (invalidServiceConnectionConfiguration()) { - setupMpi(this.mpi.mContext); - } - this.state = State.PREPARING; - this.mpi.prepareAsync(); - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.release() Releases the - * underlying resources used by the media player. - */ - public void release() { - lock.lock(); - try { - Log.d(MP_TAG, "Releasing MediaPlayer 791"); - - this.state = State.END; - if (this.amp != null) { - this.amp.release(); - } - if (this.sbmp != null) { - this.sbmp.release(); - } - - this.onBufferingUpdateListener = null; - this.onCompletionListener = null; - this.onErrorListener = null; - this.onInfoListener = null; - this.preparedListener = null; - this.onPitchAdjustmentAvailableChangedListener = null; - this.pitchAdjustmentAvailableChangedListener = null; - Log.d(MP_TAG, "Setting onSeekCompleteListener to null 871"); - this.onSeekCompleteListener = null; - this.onSpeedAdjustmentAvailableChangedListener = null; - this.speedAdjustmentAvailableChangedListener = null; - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.reset() Resets the - * track to idle state - */ - public void reset() { - lock.lock(); - try { - this.state = State.IDLE; - this.stringDataSource = null; - this.uriDataSource = null; - this.mpi.reset(); - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.seekTo(int msec) Seeks - * to msec in the track - */ - public void seekTo(int msec) throws IllegalStateException { - lock.lock(); - try { - this.mpi.seekTo(msec); - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.setAudioStreamType(int - * streamtype) Sets the audio stream type. - */ - public void setAudioStreamType(int streamtype) { - lock.lock(); - try { - this.mAudioStreamType = streamtype; - this.mpi.setAudioStreamType(streamtype); - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.setDataSource(Context - * context, Uri uri) Sets uri as data source in the context given - */ - public void setDataSource(Context context, Uri uri) - throws IllegalArgumentException, IllegalStateException, IOException { - lock.lock(); - try { - Log.d(MP_TAG, "In setDataSource(context, " + uri.toString() + "), using " + this.mpi.getClass().toString()); - if (invalidServiceConnectionConfiguration()) { - setupMpi(this.mpi.mContext); - } - this.state = State.INITIALIZED; - this.stringDataSource = null; - this.uriDataSource = uri; - this.mpi.setDataSource(context, uri); - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.setDataSource(String - * path) Sets the data source of the track to a file given. - */ - public void setDataSource(String path) throws IllegalArgumentException, - IllegalStateException, IOException { - lock.lock(); - try { - Log.d(MP_TAG, "In setDataSource(context, " + path + ")"); - if (invalidServiceConnectionConfiguration()) { - setupMpi(this.mpi.mContext); - } - this.state = State.INITIALIZED; - this.stringDataSource = path; - this.uriDataSource = null; - this.mpi.setDataSource(path); - } finally { - lock.unlock(); - } - } - - /** - * Sets whether to use speed adjustment or not. Speed adjustment on is more - * computation-intensive than with it off. - * - * @param enableSpeedAdjustment Whether speed adjustment should be supported. - */ - public void setEnableSpeedAdjustment(boolean enableSpeedAdjustment) { - lock.lock(); - try { - this.enableSpeedAdjustment = enableSpeedAdjustment; - this.mpi.setEnableSpeedAdjustment(enableSpeedAdjustment); - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.setLooping(boolean - * loop) Sets the track to loop infinitely if loop is true, play once if - * loop is false - */ - public void setLooping(boolean loop) { - lock.lock(); - try { - this.mIsLooping = loop; - this.mpi.setLooping(loop); - } finally { - lock.unlock(); - } - } - - /** - * Sets the number of steps (in a musical scale) by which playback is - * currently shifted. When greater than zero, pitch is shifted up. When less - * than zero, pitch is shifted down. - * - * @param pitchSteps The number of steps by which to shift playback - */ - public void setPitchStepsAdjustment(float pitchSteps) { - lock.lock(); - try { - this.mPitchStepsAdjustment = pitchSteps; - this.mpi.setPitchStepsAdjustment(pitchSteps); - } finally { - lock.unlock(); - } - } - - /** - * Set the algorithm to use for changing the speed and pitch of audio - * See SpeedAdjustmentAlgorithm constants for more details - * - * @param algorithm The algorithm to use. - */ - public void setSpeedAdjustmentAlgorithm(int algorithm) { - lock.lock(); - try { - this.speedAdjustmentAlgorithm = algorithm; - if (this.mpi != null) { - this.mpi.setSpeedAdjustmentAlgorithm(algorithm); - } - } finally { - lock.unlock(); - } - } - - private static float getPitchStepsAdjustment(float pitch) { - return (float) (Math.log(pitch) / (2 * Math.log(PITCH_STEP_CONSTANT))); - } - - /** - * Sets the percentage by which pitch is currently shifted. When greater - * than zero, pitch is shifted up. When less than zero, pitch is shifted - * down - * - * @param f The percentage to shift pitch - */ - public void setPlaybackPitch(float pitch) { - lock.lock(); - try { - this.mPitchStepsAdjustment = getPitchStepsAdjustment(pitch); - this.mpi.setPlaybackPitch(pitch); - } finally { - lock.unlock(); - } - } - - /** - * Set playback speed. 1.0 is normal speed, 2.0 is double speed, and so on. - * Speed should never be set to 0 or below. - * - * @param f The speed multiplier to use for further playback - */ - public void setPlaybackSpeed(float f) { - lock.lock(); - try { - this.mSpeedMultiplier = f; - this.mpi.setPlaybackSpeed(f); - } finally { - lock.unlock(); - } - } - - /** - * Sets whether to use speed adjustment or not. Speed adjustment on is more - * computation-intensive than with it off. - * - * @param enableSpeedAdjustment Whether speed adjustment should be supported. - */ - public void setUseService(boolean useService) { - lock.lock(); - try { - this.useService = useService; - setupMpi(this.mpi.mContext); - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.setVolume(float - * leftVolume, float rightVolume) Sets the stereo volume - */ - public void setVolume(float leftVolume, float rightVolume) { - lock.lock(); - try { - this.mLeftVolume = leftVolume; - this.mRightVolume = rightVolume; - this.mpi.setVolume(leftVolume, rightVolume); - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.setWakeMode(Context - * context, int mode) Acquires a wake lock in the context given. You must - * request the appropriate permissions in your AndroidManifest.xml file. - */ - public void setWakeMode(Context context, int mode) { - lock.lock(); - try { - this.mWakeMode = mode; - this.mpi.setWakeMode(context, mode); - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to - * android.media.MediaPlayer.setOnCompletionListener(OnCompletionListener - * listener) Sets a listener to be used when a track completes playing. - */ - public void setOnBufferingUpdateListener(OnBufferingUpdateListener listener) { - lock.lock(); - try { - this.onBufferingUpdateListener = listener; - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to - * android.media.MediaPlayer.setOnCompletionListener(OnCompletionListener - * listener) Sets a listener to be used when a track completes playing. - */ - public void setOnCompletionListener(OnCompletionListener listener) { - lock.lock(); - try { - this.onCompletionListener = listener; - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to - * android.media.MediaPlayer.setOnErrorListener(OnErrorListener listener) - * Sets a listener to be used when a track encounters an error. - */ - public void setOnErrorListener(OnErrorListener listener) { - lock.lock(); - try { - this.onErrorListener = listener; - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to - * android.media.MediaPlayer.setOnInfoListener(OnInfoListener listener) Sets - * a listener to be used when a track has info. - */ - public void setOnInfoListener(OnInfoListener listener) { - lock.lock(); - try { - this.onInfoListener = listener; - } finally { - lock.unlock(); - } - } - - /** - * Sets a listener that will fire when pitch adjustment becomes available or - * stops being available - */ - public void setOnPitchAdjustmentAvailableChangedListener( - OnPitchAdjustmentAvailableChangedListener listener) { - lock.lock(); - try { - this.pitchAdjustmentAvailableChangedListener = listener; - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to - * android.media.MediaPlayer.setOnPreparedListener(OnPreparedListener - * listener) Sets a listener to be used when a track finishes preparing. - */ - public void setOnPreparedListener(OnPreparedListener listener) { - lock.lock(); - Log.d(MP_TAG, " ++++++++++++++++++++++++++++++++++++++++++++ setOnPreparedListener"); - try { - this.preparedListener = listener; - // For this one, we do not explicitly set the MediaPlayer or the - // Service listener. This is because in addition to calling the - // listener provided by the client, it's necessary to change - // state to PREPARED. See prepareAsync for implementation details - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to - * android.media.MediaPlayer.setOnSeekCompleteListener - * (OnSeekCompleteListener listener) Sets a listener to be used when a track - * finishes seeking. - */ - public void setOnSeekCompleteListener(OnSeekCompleteListener listener) { - lock.lock(); - try { - this.onSeekCompleteListener = listener; - } finally { - lock.unlock(); - } - } - - /** - * Sets a listener that will fire when speed adjustment becomes available or - * stops being available - */ - public void setOnSpeedAdjustmentAvailableChangedListener( - OnSpeedAdjustmentAvailableChangedListener listener) { - lock.lock(); - try { - this.speedAdjustmentAvailableChangedListener = listener; - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.start() Starts a track - * playing - */ - public void start() { - lock.lock(); - try { - Log.d(MP_TAG, "start() 1149"); - if (invalidServiceConnectionConfiguration()) { - setupMpi(this.mpi.mContext); - } - this.state = State.STARTED; - Log.d(MP_TAG, "start() 1154"); - this.mpi.start(); - } finally { - lock.unlock(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.stop() Stops a track - * playing and resets its position to the start. - */ - public void stop() { - lock.lock(); - try { - if (invalidServiceConnectionConfiguration()) { - setupMpi(this.mpi.mContext); - } - this.state = State.STOPPED; - this.mpi.stop(); - } finally { - lock.unlock(); - } - } -} \ No newline at end of file diff --git a/core/src/main/java/com/aocate/media/MediaPlayerImpl.java b/core/src/main/java/com/aocate/media/MediaPlayerImpl.java deleted file mode 100644 index 856ab47ce..000000000 --- a/core/src/main/java/com/aocate/media/MediaPlayerImpl.java +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright 2011, Aocate, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.aocate.media; - -import java.io.IOException; -import java.util.concurrent.locks.ReentrantLock; - -import android.content.Context; -import android.net.Uri; -import android.util.Log; - -public abstract class MediaPlayerImpl { - private static final String MPI_TAG = "AocateMediaPlayerImpl"; - protected final MediaPlayer owningMediaPlayer; - protected final Context mContext; - protected int muteOnPreparedCount = 0; - protected int muteOnSeekCount = 0; - - public MediaPlayerImpl(MediaPlayer owningMediaPlayer, Context context) { - this.owningMediaPlayer = owningMediaPlayer; - - this.mContext = context; - } - - public abstract boolean canSetPitch(); - - public abstract boolean canSetSpeed(); - - public abstract float getCurrentPitchStepsAdjustment(); - - public abstract int getCurrentPosition(); - - public abstract float getCurrentSpeedMultiplier(); - - public abstract int getDuration(); - - public abstract float getMaxSpeedMultiplier(); - - public abstract float getMinSpeedMultiplier(); - - public abstract boolean isLooping(); - - public abstract boolean isPlaying(); - - public abstract void pause(); - - public abstract void prepare() throws IllegalStateException, IOException; - - public abstract void prepareAsync(); - - public abstract void release(); - - public abstract void reset(); - - public abstract void seekTo(int msec) throws IllegalStateException; - - public abstract void setAudioStreamType(int streamtype); - - public abstract void setDataSource(Context context, Uri uri) throws IllegalArgumentException, IllegalStateException, IOException; - - public abstract void setDataSource(String path) throws IllegalArgumentException, IllegalStateException, IOException; - - public abstract void setEnableSpeedAdjustment(boolean enableSpeedAdjustment); - - public abstract void setLooping(boolean loop); - - public abstract void setPitchStepsAdjustment(float pitchSteps); - - public abstract void setPlaybackPitch(float f); - - public abstract void setPlaybackSpeed(float f); - - public abstract void setSpeedAdjustmentAlgorithm(int algorithm); - - public abstract void setVolume(float leftVolume, float rightVolume); - - public abstract void setWakeMode(Context context, int mode); - - public abstract void start(); - - public abstract void stop(); - - protected ReentrantLock lockMuteOnPreparedCount = new ReentrantLock(); - public void muteNextOnPrepare() { - lockMuteOnPreparedCount.lock(); - Log.d(MPI_TAG, "muteNextOnPrepare()"); - try { - this.muteOnPreparedCount++; - } - finally { - lockMuteOnPreparedCount.unlock(); - } - } - - protected ReentrantLock lockMuteOnSeekCount = new ReentrantLock(); - public void muteNextSeek() { - lockMuteOnSeekCount.lock(); - Log.d(MPI_TAG, "muteNextOnSeek()"); - try { - this.muteOnSeekCount++; - } - finally { - lockMuteOnSeekCount.unlock(); - } - } -} diff --git a/core/src/main/java/com/aocate/media/ServiceBackedMediaPlayer.java b/core/src/main/java/com/aocate/media/ServiceBackedMediaPlayer.java deleted file mode 100644 index 0e27a8014..000000000 --- a/core/src/main/java/com/aocate/media/ServiceBackedMediaPlayer.java +++ /dev/null @@ -1,1203 +0,0 @@ -// Copyright 2011, Aocate, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// ----------------------------------------------------------------------- -// Compared to the original version, this class been slightly modified so -// that any acquired WakeLocks are only held while the MediaPlayer is -// playing (see the stayAwake method for more details). - - -package com.aocate.media; - -import java.io.IOException; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.media.AudioManager; -import android.net.Uri; -import android.os.IBinder; -import android.os.PowerManager; -import android.os.RemoteException; -import android.os.PowerManager.WakeLock; -import android.util.Log; - -import com.aocate.media.MediaPlayer.State; -import com.aocate.presto.service.IDeathCallback_0_8; -import com.aocate.presto.service.IOnBufferingUpdateListenerCallback_0_8; -import com.aocate.presto.service.IOnCompletionListenerCallback_0_8; -import com.aocate.presto.service.IOnErrorListenerCallback_0_8; -import com.aocate.presto.service.IOnInfoListenerCallback_0_8; -import com.aocate.presto.service.IOnPitchAdjustmentAvailableChangedListenerCallback_0_8; -import com.aocate.presto.service.IOnPreparedListenerCallback_0_8; -import com.aocate.presto.service.IOnSeekCompleteListenerCallback_0_8; -import com.aocate.presto.service.IOnSpeedAdjustmentAvailableChangedListenerCallback_0_8; -import com.aocate.presto.service.IPlayMedia_0_8; - -import de.danoeh.antennapod.core.BuildConfig; - -/** - * Class for connecting to remote speed-altering, media playing Service - * Note that there is unusually high coupling between MediaPlayer and this - * class. This is an unfortunate compromise, since the alternative was to - * track state in two different places in this code (plus the internal state - * of the remote media player). - * @author aocate - * - */ -public class ServiceBackedMediaPlayer extends MediaPlayerImpl { - static final String INTENT_NAME = "com.aocate.intent.PLAY_AUDIO_ADJUST_SPEED_0_8"; - - private static final String SBMP_TAG = "AocateServiceBackedMediaPlayer"; - - private ServiceConnection mPlayMediaServiceConnection = null; - protected IPlayMedia_0_8 pmInterface = null; - private Intent playMediaServiceIntent = null; - // In some cases, we're going to have to replace the - // android.media.MediaPlayer on the fly, and we don't want to touch the - // wrong media player. - - private long sessionId = 0; - private boolean isErroring = false; - private int mAudioStreamType = AudioManager.STREAM_MUSIC; - - private WakeLock mWakeLock = null; - - // So here's the major problem - // Sometimes the service won't exist or won't be connected, - // so start with an android.media.MediaPlayer, and when - // the service is connected, use that from then on - public ServiceBackedMediaPlayer(MediaPlayer owningMediaPlayer, final Context context, final ServiceConnection serviceConnection) { - super(owningMediaPlayer, context); - Log.d(SBMP_TAG, "Instantiating ServiceBackedMediaPlayer 87"); - this.playMediaServiceIntent = - MediaPlayer.getPrestoServiceIntent(context, INTENT_NAME); - this.mPlayMediaServiceConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName name, IBinder service) { - IPlayMedia_0_8 tmpPlayMediaInterface = IPlayMedia_0_8.Stub.asInterface((IBinder) service); - - Log.d(SBMP_TAG, "Setting up pmInterface 94"); - if (ServiceBackedMediaPlayer.this.sessionId == 0) { - try { - // The IDeathCallback isn't a conventional callback. - // It exists so that if the client ceases to exist, - // the Service becomes aware of that and can shut - // down whatever it needs to shut down - ServiceBackedMediaPlayer.this.sessionId = tmpPlayMediaInterface.startSession(new IDeathCallback_0_8.Stub() { - }); - // This is really bad if this fails - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - - Log.d(SBMP_TAG, "Assigning pmInterface"); - - ServiceBackedMediaPlayer.this.setOnBufferingUpdateCallback(tmpPlayMediaInterface); - ServiceBackedMediaPlayer.this.setOnCompletionCallback(tmpPlayMediaInterface); - ServiceBackedMediaPlayer.this.setOnErrorCallback(tmpPlayMediaInterface); - ServiceBackedMediaPlayer.this.setOnInfoCallback(tmpPlayMediaInterface); - ServiceBackedMediaPlayer.this.setOnPitchAdjustmentAvailableChangedListener(tmpPlayMediaInterface); - ServiceBackedMediaPlayer.this.setOnPreparedCallback(tmpPlayMediaInterface); - ServiceBackedMediaPlayer.this.setOnSeekCompleteCallback(tmpPlayMediaInterface); - ServiceBackedMediaPlayer.this.setOnSpeedAdjustmentAvailableChangedCallback(tmpPlayMediaInterface); - - // In order to avoid race conditions from the sessionId or listener not being assigned - pmInterface = tmpPlayMediaInterface; - - Log.d(SBMP_TAG, "Invoking onServiceConnected"); - serviceConnection.onServiceConnected(name, service); - } - - public void onServiceDisconnected(ComponentName name) { - Log.d(SBMP_TAG, "onServiceDisconnected 114"); - - pmInterface = null; - - sessionId = 0; - - serviceConnection.onServiceDisconnected(name); - } - }; - - Log.d(SBMP_TAG, "Connecting PlayMediaService 124"); - if (!ConnectPlayMediaService()) { - Log.e(SBMP_TAG, "bindService failed"); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - - private boolean ConnectPlayMediaService() { - Log.d(SBMP_TAG, "ConnectPlayMediaService()"); - - if (MediaPlayer.isIntentAvailable(mContext, INTENT_NAME)) { - Log.d(SBMP_TAG, INTENT_NAME + " is available"); - if (pmInterface == null) { - try { - Log.d(SBMP_TAG, "Binding service"); - return mContext.bindService(playMediaServiceIntent, mPlayMediaServiceConnection, Context.BIND_AUTO_CREATE); - } catch (Exception e) { - Log.e(SBMP_TAG, "Could not bind with service", e); - return false; - } - } else { - Log.d(SBMP_TAG, "Service already bound"); - return true; - } - } - else { - Log.d(SBMP_TAG, INTENT_NAME + " is not available"); - return false; - } - } - - /** - * Returns true if pitch can be changed at this moment - * @return True if pitch can be changed - */ - @Override - public boolean canSetPitch() { - Log.d(SBMP_TAG, "canSetPitch() 155"); - - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - if (pmInterface != null) { - // Can't set pitch if the service isn't connected - try { - return pmInterface.canSetPitch(ServiceBackedMediaPlayer.this.sessionId); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - return false; - } - - /** - * Returns true if speed can be changed at this moment - * @return True if speed can be changed - */ - @Override - public boolean canSetSpeed() { - Log.d(SBMP_TAG, "canSetSpeed() 180"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - if (pmInterface != null) { - // Can't set speed if the service isn't connected - try { - return pmInterface.canSetSpeed(ServiceBackedMediaPlayer.this.sessionId); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - return false; - } - - void error(int what, int extra) { - owningMediaPlayer.lock.lock(); - Log.e(SBMP_TAG, "error(" + what + ", " + extra + ")"); - stayAwake(false); - try { - if (!this.isErroring) { - this.isErroring = true; - owningMediaPlayer.state = State.ERROR; - if (owningMediaPlayer.onErrorListener != null) { - if (owningMediaPlayer.onErrorListener.onError(owningMediaPlayer, what, extra)) { - return; - } - } - if (owningMediaPlayer.onCompletionListener != null) { - owningMediaPlayer.onCompletionListener.onCompletion(owningMediaPlayer); - } - } - } - finally { - this.isErroring = false; - owningMediaPlayer.lock.unlock(); - } - } - - protected void finalize() throws Throwable { - owningMediaPlayer.lock.lock(); - try { - Log.d(SBMP_TAG, "finalize() 224"); - this.release(); - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - /** - * Returns the number of steps (in a musical scale) by which playback is - * currently shifted. When greater than zero, pitch is shifted up. - * When less than zero, pitch is shifted down. - * @return The number of steps pitch is currently shifted by - */ - @Override - public float getCurrentPitchStepsAdjustment() { - Log.d(SBMP_TAG, "getCurrentPitchStepsAdjustment() 240"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - if (pmInterface != null) { - // Can't set pitch if the service isn't connected - try { - return pmInterface.getCurrentPitchStepsAdjustment( - ServiceBackedMediaPlayer.this.sessionId); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - return 0f; - } - - /** - * Functions identically to android.media.MediaPlayer.getCurrentPosition() - * @return Current position (in milliseconds) - */ - @Override - public int getCurrentPosition() { - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - try { - return pmInterface.getCurrentPosition( - ServiceBackedMediaPlayer.this.sessionId); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - return 0; - } - - /** - * Returns the current speed multiplier. Defaults to 1.0 (normal speed) - * @return The current speed multiplier - */ - @Override - public float getCurrentSpeedMultiplier() { - Log.d(SBMP_TAG, "getCurrentSpeedMultiplier() 286"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - if (pmInterface != null) { - // Can't set speed if the service isn't connected - try { - return pmInterface.getCurrentSpeedMultiplier( - ServiceBackedMediaPlayer.this.sessionId); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - return 1; - } - - /** - * Functions identically to android.media.MediaPlayer.getDuration() - * @return Length of the track (in milliseconds) - */ - @Override - public int getDuration() { - Log.d(SBMP_TAG, "getDuration() 311"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - try { - return pmInterface.getDuration(ServiceBackedMediaPlayer.this.sessionId); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - return 0; - } - - /** - * Get the maximum value that can be passed to setPlaybackSpeed - * @return The maximum speed multiplier - */ - @Override - public float getMaxSpeedMultiplier() { - Log.d(SBMP_TAG, "getMaxSpeedMultiplier() 332"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - if (pmInterface != null) { - // Can't set speed if the Service isn't connected - try { - return pmInterface.getMaxSpeedMultiplier( - ServiceBackedMediaPlayer.this.sessionId); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - return 1f; - } - - /** - * Get the minimum value that can be passed to setPlaybackSpeed - * @return The minimum speed multiplier - */ - @Override - public float getMinSpeedMultiplier() { - Log.d(SBMP_TAG, "getMinSpeedMultiplier() 357"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - if (pmInterface != null) { - // Can't set speed if the Service isn't connected - try { - return pmInterface.getMinSpeedMultiplier( - ServiceBackedMediaPlayer.this.sessionId); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - return 1f; - } - - public int getServiceVersionCode() { - Log.d(SBMP_TAG, "getVersionCode"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - try { - return pmInterface.getVersionCode(); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - return 0; - } - - public String getServiceVersionName() { - Log.d(SBMP_TAG, "getVersionName"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - try { - return pmInterface.getVersionName(); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - return ""; - } - - public boolean isConnected() { - return (pmInterface != null); - } - - /** - * Functions identically to android.media.MediaPlayer.isLooping() - * @return True if the track is looping - */ - @Override - public boolean isLooping() { - Log.d(SBMP_TAG, "isLooping() 382"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - try { - return pmInterface.isLooping(ServiceBackedMediaPlayer.this.sessionId); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - return false; - } - - /** - * Functions identically to android.media.MediaPlayer.isPlaying() - * @return True if the track is playing - */ - @Override - public boolean isPlaying() { - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - if (pmInterface != null) { - try { - return pmInterface.isPlaying(ServiceBackedMediaPlayer.this.sessionId); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - return false; - } - - /** - * Functions identically to android.media.MediaPlayer.pause() - * Pauses the track - */ - @Override - public void pause() { - Log.d(SBMP_TAG, "pause() 424"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - try { - pmInterface.pause(ServiceBackedMediaPlayer.this.sessionId); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - stayAwake(false); - } - - /** - * Functions identically to android.media.MediaPlayer.prepare() - * Prepares the track. This or prepareAsync must be called before start() - */ - @Override - public void prepare() throws IllegalStateException, IOException { - Log.d(SBMP_TAG, "prepare() 444"); - Log.d(SBMP_TAG, "onPreparedCallback is: " + ((this.mOnPreparedCallback == null) ? "null" : "non-null")); - if (pmInterface == null) { - Log.d(SBMP_TAG, "prepare: pmInterface is null"); - if (!ConnectPlayMediaService()) { - Log.d(SBMP_TAG, "prepare: Failed to connect play media service"); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - if (pmInterface != null) { - Log.d(SBMP_TAG, "prepare: pmInterface isn't null"); - try { - Log.d(SBMP_TAG, "prepare: Remote invoke pmInterface.prepare(" + ServiceBackedMediaPlayer.this.sessionId + ")"); - pmInterface.prepare(ServiceBackedMediaPlayer.this.sessionId); - Log.d(SBMP_TAG, "prepare: prepared"); - } catch (RemoteException e) { - Log.d(SBMP_TAG, "prepare: RemoteException"); - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - Log.d(SBMP_TAG, "Done with prepare()"); - } - - /** - * Functions identically to android.media.MediaPlayer.prepareAsync() - * Prepares the track. This or prepare must be called before start() - */ - @Override - public void prepareAsync() { - Log.d(SBMP_TAG, "prepareAsync() 469"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - try { - pmInterface.prepareAsync(ServiceBackedMediaPlayer.this.sessionId); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - - /** - * Functions identically to android.media.MediaPlayer.release() - * Releases the underlying resources used by the media player. - */ - @Override - public void release() { - Log.d(SBMP_TAG, "release() 492"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - if (pmInterface != null) { - Log.d(SBMP_TAG, "release() 500"); - try { - pmInterface.release(ServiceBackedMediaPlayer.this.sessionId); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - mContext.unbindService(this.mPlayMediaServiceConnection); - // Don't try to keep awake (if we were) - this.setWakeMode(mContext, 0); - pmInterface = null; - this.sessionId = 0; - } - - if ((this.mWakeLock != null) && this.mWakeLock.isHeld()) { - Log.d(SBMP_TAG, "Releasing wakelock"); - this.mWakeLock.release(); - } - } - - /** - * Functions identically to android.media.MediaPlayer.reset() - * Resets the track to idle state - */ - @Override - public void reset() { - Log.d(SBMP_TAG, "reset() 523"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - try { - pmInterface.reset(ServiceBackedMediaPlayer.this.sessionId); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - stayAwake(false); - } - - /** - * Functions identically to android.media.MediaPlayer.seekTo(int msec) - * Seeks to msec in the track - */ - @Override - public void seekTo(int msec) throws IllegalStateException { - Log.d(SBMP_TAG, "seekTo(" + msec + ")"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - try { - pmInterface.seekTo(ServiceBackedMediaPlayer.this.sessionId, msec); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - - /** - * Functions identically to android.media.MediaPlayer.setAudioStreamType(int streamtype) - * Sets the audio stream type. - */ - @Override - public void setAudioStreamType(int streamtype) { - Log.d(SBMP_TAG, "setAudioStreamType(" + streamtype + ")"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - try { - pmInterface.setAudioStreamType( - ServiceBackedMediaPlayer.this.sessionId, - this.mAudioStreamType); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - - - /** - * Functions identically to android.media.MediaPlayer.setDataSource(Context context, Uri uri) - * Sets uri as data source in the context given - */ - @Override - public void setDataSource(Context context, Uri uri) throws IllegalArgumentException, IllegalStateException, IOException { - Log.d(SBMP_TAG, "setDataSource(context, uri)"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - try { - pmInterface.setDataSourceUri( - ServiceBackedMediaPlayer.this.sessionId, - uri); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - - /** - * Functions identically to android.media.MediaPlayer.setDataSource(String path) - * Sets the data source of the track to a file given. - */ - @Override - public void setDataSource(String path) throws IllegalArgumentException, IllegalStateException, IOException { - Log.d(SBMP_TAG, "setDataSource(path)"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - if (pmInterface == null) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - else { - try { - pmInterface.setDataSourceString( - ServiceBackedMediaPlayer.this.sessionId, - path); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - } - - /** - * Sets whether to use speed adjustment or not. Speed adjustment on is - * more computation-intensive than with it off. - * @param enableSpeedAdjustment Whether speed adjustment should be supported. - */ - @Override - public void setEnableSpeedAdjustment(boolean enableSpeedAdjustment) { - // TODO: This has no business being here, I think - owningMediaPlayer.lock.lock(); - Log.d(SBMP_TAG, "setEnableSpeedAdjustment(enableSpeedAdjustment)"); - try { - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - if (pmInterface != null) { - // Can't set speed if the Service isn't connected - try { - pmInterface.setEnableSpeedAdjustment( - ServiceBackedMediaPlayer.this.sessionId, - enableSpeedAdjustment); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - - - /** - * Functions identically to android.media.MediaPlayer.setLooping(boolean loop) - * Sets the track to loop infinitely if loop is true, play once if loop is false - */ - @Override - public void setLooping(boolean loop) { - Log.d(SBMP_TAG, "setLooping(" + loop + ")"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - try { - pmInterface.setLooping(ServiceBackedMediaPlayer.this.sessionId, loop); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - - /** - * Sets the number of steps (in a musical scale) by which playback is - * currently shifted. When greater than zero, pitch is shifted up. - * When less than zero, pitch is shifted down. - * - * @param pitchSteps The number of steps by which to shift playback - */ - @Override - public void setPitchStepsAdjustment(float pitchSteps) { - Log.d(SBMP_TAG, "setPitchStepsAdjustment(" + pitchSteps + ")"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - if (pmInterface != null) { - // Can't set speed if the Service isn't connected - try { - pmInterface.setPitchStepsAdjustment( - ServiceBackedMediaPlayer.this.sessionId, - pitchSteps); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - } - - /** - * Sets the percentage by which pitch is currently shifted. When - * greater than zero, pitch is shifted up. When less than zero, pitch - * is shifted down - * @param f The percentage to shift pitch - */ - @Override - public void setPlaybackPitch(float f) { - Log.d(SBMP_TAG, "setPlaybackPitch(" + f + ")"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - if (pmInterface != null) { - // Can't set speed if the Service isn't connected - try { - pmInterface.setPlaybackPitch( - ServiceBackedMediaPlayer.this.sessionId, - f); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - } - - /** - * Set playback speed. 1.0 is normal speed, 2.0 is double speed, and so - * on. Speed should never be set to 0 or below. - * @param f The speed multiplier to use for further playback - */ - @Override - public void setPlaybackSpeed(float f) { - Log.d(SBMP_TAG, "setPlaybackSpeed(" + f + ")"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - if (pmInterface != null) { - // Can't set speed if the Service isn't connected - try { - pmInterface.setPlaybackSpeed( - ServiceBackedMediaPlayer.this.sessionId, - f); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - } - - @Override - public void setSpeedAdjustmentAlgorithm(int algorithm) { - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - try { - pmInterface.setSpeedAdjustmentAlgorithm( - ServiceBackedMediaPlayer.this.sessionId, - algorithm); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - - /** - * Functions identically to android.media.MediaPlayer.setVolume(float leftVolume, float rightVolume) - * Sets the stereo volume - */ - @Override - public void setVolume(float leftVolume, float rightVolume) { - Log.d(SBMP_TAG, "setVolume(" + leftVolume + ", " + rightVolume + ")"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - try { - pmInterface.setVolume( - ServiceBackedMediaPlayer.this.sessionId, - leftVolume, - rightVolume); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - - /** - * Functions identically to android.media.MediaPlayer.setWakeMode(Context context, int mode) - * Acquires a wake lock in the context given. You must request the appropriate permissions - * in your AndroidManifest.xml file. - */ - @Override - // This does not just call .setWakeMode() in the Service because doing so - // would add a permission requirement to the Service. Do it here, and it's - // the client app's responsibility to request that permission - public void setWakeMode(Context context, int mode) { - Log.d(SBMP_TAG, "setWakeMode(context, " + mode + ")"); - if ((this.mWakeLock != null) - && (this.mWakeLock.isHeld())) { - this.mWakeLock.release(); - } - if (mode != 0) { - if (this.mWakeLock == null) { - PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); - // Since mode can't be changed on the fly, we have to allocate a new one - this.mWakeLock = pm.newWakeLock(mode, this.getClass().getName()); - this.mWakeLock.setReferenceCounted(false); - } - - this.mWakeLock.acquire(); - } - } - - /** - * Changes the state of the WakeLock if it has been acquired. - * If no WakeLock has been acquired with setWakeMode, this method does nothing. - * */ - private void stayAwake(boolean awake) { - if (BuildConfig.DEBUG) Log.d(SBMP_TAG, "stayAwake(" + awake + ")"); - if (mWakeLock != null) { - if (awake && !mWakeLock.isHeld()) { - mWakeLock.acquire(); - } else if (!awake && mWakeLock.isHeld()) { - mWakeLock.release(); - } - } - } - - private IOnBufferingUpdateListenerCallback_0_8.Stub mOnBufferingUpdateCallback = null; - private void setOnBufferingUpdateCallback(IPlayMedia_0_8 iface) { - try { - if (this.mOnBufferingUpdateCallback == null) { - mOnBufferingUpdateCallback = new IOnBufferingUpdateListenerCallback_0_8.Stub() { - public void onBufferingUpdate(int percent) - throws RemoteException { - owningMediaPlayer.lock.lock(); - try { - if ((owningMediaPlayer.onBufferingUpdateListener != null) - && (owningMediaPlayer.mpi == ServiceBackedMediaPlayer.this)) { - owningMediaPlayer.onBufferingUpdateListener.onBufferingUpdate(owningMediaPlayer, percent); - } - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - }; - } - iface.registerOnBufferingUpdateCallback( - ServiceBackedMediaPlayer.this.sessionId, - mOnBufferingUpdateCallback); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - - private IOnCompletionListenerCallback_0_8.Stub mOnCompletionCallback = null; - private void setOnCompletionCallback(IPlayMedia_0_8 iface) { - try { - if (this.mOnCompletionCallback == null) { - this.mOnCompletionCallback = new IOnCompletionListenerCallback_0_8.Stub() { - public void onCompletion() throws RemoteException { - owningMediaPlayer.lock.lock(); - Log.d(SBMP_TAG, "onCompletionListener being called"); - stayAwake(false); - try { - if (owningMediaPlayer.onCompletionListener != null) { - owningMediaPlayer.onCompletionListener.onCompletion(owningMediaPlayer); - } - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - }; - } - iface.registerOnCompletionCallback( - ServiceBackedMediaPlayer.this.sessionId, - this.mOnCompletionCallback); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - - private IOnErrorListenerCallback_0_8.Stub mOnErrorCallback = null; - private void setOnErrorCallback(IPlayMedia_0_8 iface) { - try { - if (this.mOnErrorCallback == null) { - this.mOnErrorCallback = new IOnErrorListenerCallback_0_8.Stub() { - public boolean onError(int what, int extra) throws RemoteException { - owningMediaPlayer.lock.lock(); - stayAwake(false); - try { - if (owningMediaPlayer.onErrorListener != null) { - return owningMediaPlayer.onErrorListener.onError(owningMediaPlayer, what, extra); - } - return false; - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - }; - } - iface.registerOnErrorCallback( - ServiceBackedMediaPlayer.this.sessionId, - this.mOnErrorCallback); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - - private IOnInfoListenerCallback_0_8.Stub mOnInfoCallback = null; - private void setOnInfoCallback(IPlayMedia_0_8 iface) { - try { - if (this.mOnInfoCallback == null) { - this.mOnInfoCallback = new IOnInfoListenerCallback_0_8.Stub() { - public boolean onInfo(int what, int extra) throws RemoteException { - owningMediaPlayer.lock.lock(); - try { - if ((owningMediaPlayer.onInfoListener != null) - && (owningMediaPlayer.mpi == ServiceBackedMediaPlayer.this)) { - return owningMediaPlayer.onInfoListener.onInfo(owningMediaPlayer, what, extra); - } - } - finally { - owningMediaPlayer.lock.unlock(); - } - return false; - } - }; - } - iface.registerOnInfoCallback( - ServiceBackedMediaPlayer.this.sessionId, - this.mOnInfoCallback); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - - private IOnPitchAdjustmentAvailableChangedListenerCallback_0_8.Stub mOnPitchAdjustmentAvailableChangedCallback = null; - private void setOnPitchAdjustmentAvailableChangedListener(IPlayMedia_0_8 iface) { - try { - if (this.mOnPitchAdjustmentAvailableChangedCallback == null) { - this.mOnPitchAdjustmentAvailableChangedCallback = new IOnPitchAdjustmentAvailableChangedListenerCallback_0_8.Stub() { - public void onPitchAdjustmentAvailableChanged( - boolean pitchAdjustmentAvailable) - throws RemoteException { - owningMediaPlayer.lock.lock(); - try { - if (owningMediaPlayer.onPitchAdjustmentAvailableChangedListener != null) { - owningMediaPlayer.onPitchAdjustmentAvailableChangedListener.onPitchAdjustmentAvailableChanged(owningMediaPlayer, pitchAdjustmentAvailable); - } - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - }; - } - iface.registerOnPitchAdjustmentAvailableChangedCallback( - ServiceBackedMediaPlayer.this.sessionId, - this.mOnPitchAdjustmentAvailableChangedCallback); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - - private IOnPreparedListenerCallback_0_8.Stub mOnPreparedCallback = null; - private void setOnPreparedCallback(IPlayMedia_0_8 iface) { - try { - if (this.mOnPreparedCallback == null) { - this.mOnPreparedCallback = new IOnPreparedListenerCallback_0_8.Stub() { - public void onPrepared() throws RemoteException { - owningMediaPlayer.lock.lock(); - Log.d(SBMP_TAG, "setOnPreparedCallback.mOnPreparedCallback.onPrepared 1050"); - try { - Log.d(SBMP_TAG, "owningMediaPlayer.onPreparedListener is " + ((owningMediaPlayer.onPreparedListener == null) ? "null" : "non-null")); - Log.d(SBMP_TAG, "owningMediaPlayer.mpi is " + ((owningMediaPlayer.mpi == ServiceBackedMediaPlayer.this) ? "this" : "not this")); - ServiceBackedMediaPlayer.this.lockMuteOnPreparedCount.lock(); - try { - if (ServiceBackedMediaPlayer.this.muteOnPreparedCount > 0) { - ServiceBackedMediaPlayer.this.muteOnPreparedCount--; - } - else { - ServiceBackedMediaPlayer.this.muteOnPreparedCount = 0; - if (ServiceBackedMediaPlayer.this.owningMediaPlayer.onPreparedListener != null) { - owningMediaPlayer.onPreparedListener.onPrepared(owningMediaPlayer); - } - } - } - finally { - ServiceBackedMediaPlayer.this.lockMuteOnPreparedCount.unlock(); - } - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - }; - } - iface.registerOnPreparedCallback( - ServiceBackedMediaPlayer.this.sessionId, - this.mOnPreparedCallback); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - - private IOnSeekCompleteListenerCallback_0_8.Stub mOnSeekCompleteCallback = null; - private void setOnSeekCompleteCallback(IPlayMedia_0_8 iface) { - try { - if (this.mOnSeekCompleteCallback == null) { - this.mOnSeekCompleteCallback = new IOnSeekCompleteListenerCallback_0_8.Stub() { - public void onSeekComplete() throws RemoteException { - Log.d(SBMP_TAG, "onSeekComplete() 941"); - owningMediaPlayer.lock.lock(); - try { - if (ServiceBackedMediaPlayer.this.muteOnSeekCount > 0) { - Log.d(SBMP_TAG, "The next " + ServiceBackedMediaPlayer.this.muteOnSeekCount + " seek events are muted (counting this one)"); - ServiceBackedMediaPlayer.this.muteOnSeekCount--; - } - else { - ServiceBackedMediaPlayer.this.muteOnSeekCount = 0; - Log.d(SBMP_TAG, "Attempting to invoke next seek event"); - if (ServiceBackedMediaPlayer.this.owningMediaPlayer.onSeekCompleteListener != null) { - Log.d(SBMP_TAG, "Invoking onSeekComplete"); - owningMediaPlayer.onSeekCompleteListener.onSeekComplete(owningMediaPlayer); - } - } - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - }; - } - iface.registerOnSeekCompleteCallback( - ServiceBackedMediaPlayer.this.sessionId, - this.mOnSeekCompleteCallback); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - - private IOnSpeedAdjustmentAvailableChangedListenerCallback_0_8.Stub mOnSpeedAdjustmentAvailableChangedCallback = null; - private void setOnSpeedAdjustmentAvailableChangedCallback(IPlayMedia_0_8 iface) { - try { - Log.d(SBMP_TAG, "Setting the service of on speed adjustment available changed"); - if (this.mOnSpeedAdjustmentAvailableChangedCallback == null) { - this.mOnSpeedAdjustmentAvailableChangedCallback = new IOnSpeedAdjustmentAvailableChangedListenerCallback_0_8.Stub() { - public void onSpeedAdjustmentAvailableChanged( - boolean speedAdjustmentAvailable) - throws RemoteException { - owningMediaPlayer.lock.lock(); - try { - if (owningMediaPlayer.onSpeedAdjustmentAvailableChangedListener != null) { - owningMediaPlayer.onSpeedAdjustmentAvailableChangedListener.onSpeedAdjustmentAvailableChanged(owningMediaPlayer, speedAdjustmentAvailable); - } - } - finally { - owningMediaPlayer.lock.unlock(); - } - } - }; - } - iface.registerOnSpeedAdjustmentAvailableChangedCallback( - ServiceBackedMediaPlayer.this.sessionId, - this.mOnSpeedAdjustmentAvailableChangedCallback); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - - /** - * Functions identically to android.media.MediaPlayer.start() - * Starts a track playing - */ - @Override - public void start() { - Log.d(SBMP_TAG, "start()"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - try { - pmInterface.start(ServiceBackedMediaPlayer.this.sessionId); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - stayAwake(true); - } - - /** - * Functions identically to android.media.MediaPlayer.stop() - * Stops a track playing and resets its position to the start. - */ - @Override - public void stop() { - Log.d(SBMP_TAG, "stop()"); - if (pmInterface == null) { - if (!ConnectPlayMediaService()) { - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - } - try { - pmInterface.stop(ServiceBackedMediaPlayer.this.sessionId); - } catch (RemoteException e) { - e.printStackTrace(); - ServiceBackedMediaPlayer.this.error(MediaPlayer.MEDIA_ERROR_UNKNOWN, 0); - } - stayAwake(false); - } -} \ No newline at end of file diff --git a/core/src/main/java/com/aocate/media/SpeedAdjustmentAlgorithm.java b/core/src/main/java/com/aocate/media/SpeedAdjustmentAlgorithm.java deleted file mode 100644 index d337a0452..000000000 --- a/core/src/main/java/com/aocate/media/SpeedAdjustmentAlgorithm.java +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2011, Aocate, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.aocate.media; - -public class SpeedAdjustmentAlgorithm { - /** - * Use this to use the user-specified algorithm - */ - public static int DEFAULT = 0; - - /** - * Better for voice audio - */ - public static int SONIC = 1; - /** - * Better for music audio - */ - public static int WSOLA = 2; -} 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 c0d44dff3..e6a2a2464 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 @@ -89,6 +89,10 @@ public class UserPreferences { public static final String IMAGE_CACHE_DEFAULT_VALUE = "100"; public static final int IMAGE_CACHE_SIZE_MINIMUM = 20; + // Experimental + public static final String PREF_SONIC = "prefSonic"; + public static final String PREF_NORMALIZER = "prefNormalizer"; + // Constants private static int EPISODE_CACHE_SIZE_UNLIMITED = -1; public static int FEED_ORDER_COUNTER = 0; @@ -469,6 +473,9 @@ public class UserPreferences { return selectedSpeeds; } + public static boolean useSonic() { + return prefs.getBoolean(PREF_SONIC, false); + } /** * Return the folder where the app stores all of its data. This method will diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 757b2e980..7cf7eb622 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -1047,9 +1047,9 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre return mp; } - private final com.aocate.media.MediaPlayer.OnCompletionListener audioCompletionListener = new com.aocate.media.MediaPlayer.OnCompletionListener() { + private final org.antennapod.audio.MediaPlayer.OnCompletionListener audioCompletionListener = new org.antennapod.audio.MediaPlayer.OnCompletionListener() { @Override - public void onCompletion(com.aocate.media.MediaPlayer mp) { + public void onCompletion(org.antennapod.audio.MediaPlayer mp) { genericOnCompletion(); } }; @@ -1065,9 +1065,9 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre endPlayback(); } - private final com.aocate.media.MediaPlayer.OnBufferingUpdateListener audioBufferingUpdateListener = new com.aocate.media.MediaPlayer.OnBufferingUpdateListener() { + private final org.antennapod.audio.MediaPlayer.OnBufferingUpdateListener audioBufferingUpdateListener = new org.antennapod.audio.MediaPlayer.OnBufferingUpdateListener() { @Override - public void onBufferingUpdate(com.aocate.media.MediaPlayer mp, + public void onBufferingUpdate(org.antennapod.audio.MediaPlayer mp, int percent) { genericOnBufferingUpdate(percent); } @@ -1084,9 +1084,9 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre callback.onBufferingUpdate(percent); } - private final com.aocate.media.MediaPlayer.OnInfoListener audioInfoListener = new com.aocate.media.MediaPlayer.OnInfoListener() { + private final org.antennapod.audio.MediaPlayer.OnInfoListener audioInfoListener = new org.antennapod.audio.MediaPlayer.OnInfoListener() { @Override - public boolean onInfo(com.aocate.media.MediaPlayer mp, int what, + public boolean onInfo(org.antennapod.audio.MediaPlayer mp, int what, int extra) { return genericInfoListener(what); } @@ -1103,9 +1103,9 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre return callback.onMediaPlayerInfo(what); } - private final com.aocate.media.MediaPlayer.OnErrorListener audioErrorListener = new com.aocate.media.MediaPlayer.OnErrorListener() { + private final org.antennapod.audio.MediaPlayer.OnErrorListener audioErrorListener = new org.antennapod.audio.MediaPlayer.OnErrorListener() { @Override - public boolean onError(com.aocate.media.MediaPlayer mp, int what, + public boolean onError(org.antennapod.audio.MediaPlayer mp, int what, int extra) { return genericOnError(mp, what, extra); } @@ -1122,9 +1122,9 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre return callback.onMediaPlayerError(inObj, what, extra); } - private final com.aocate.media.MediaPlayer.OnSeekCompleteListener audioSeekCompleteListener = new com.aocate.media.MediaPlayer.OnSeekCompleteListener() { + private final org.antennapod.audio.MediaPlayer.OnSeekCompleteListener audioSeekCompleteListener = new org.antennapod.audio.MediaPlayer.OnSeekCompleteListener() { @Override - public void onSeekComplete(com.aocate.media.MediaPlayer mp) { + public void onSeekComplete(org.antennapod.audio.MediaPlayer mp) { genericSeekCompleteListener(); } }; diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java index aafcea307..b6beb5bf1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java @@ -3,7 +3,9 @@ package de.danoeh.antennapod.core.util.playback; import android.content.Context; import android.util.Log; import android.view.SurfaceHolder; -import com.aocate.media.MediaPlayer; +import org.antennapod.audio.MediaPlayer; + +import de.danoeh.antennapod.core.preferences.UserPreferences; public class AudioPlayer extends MediaPlayer implements IPlayer { private static final String TAG = "AudioPlayer"; @@ -16,7 +18,6 @@ public class AudioPlayer extends MediaPlayer implements IPlayer { public void setScreenOnWhilePlaying(boolean screenOn) { Log.e(TAG, "Setting screen on while playing not supported in Audio Player"); throw new UnsupportedOperationException("Setting screen on while playing not supported in Audio Player"); - } @Override @@ -31,4 +32,9 @@ public class AudioPlayer extends MediaPlayer implements IPlayer { public void setVideoScalingMode(int mode) { throw new UnsupportedOperationException("Setting scaling mode is not supported in Audio Player"); } + + @Override + protected boolean useSonic() { + return UserPreferences.useSonic(); + } } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 68c5150e5..ff9891bab 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -344,6 +344,9 @@ Disabled Image Cache Size Size of the disk cache for images. + Experimental + Sonic media player + Use built-in sonic media player as a replacement for Prestissimo Enable automatic flattring -- cgit v1.2.3 From a475bf112fb436e4a700e4499d491b1adabb9d83 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 19 Sep 2015 20:38:45 +0200 Subject: Prevent NPE --- .../main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'core/src/main') 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 73037d771..fa4a5726a 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 @@ -309,7 +309,11 @@ public class PodDBAdapter { dbHelper.close(); dbHelper = null; } - return context.deleteDatabase(PodDBAdapter.DATABASE_NAME); + if(context != null) { // may not have been initialized + return context.deleteDatabase(PodDBAdapter.DATABASE_NAME); + } else { + return false; + } } /** -- cgit v1.2.3 From 5f77c4de50a7ec9ad36fc4c57407b1d9ccd39aef Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 19 Sep 2015 20:39:14 +0200 Subject: Replace some of the most annoying AsyncTasks with RxJava --- core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java index 879b28096..c1d21552e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItemFilter.java @@ -55,7 +55,7 @@ public class FeedItemFilter { } } - public List filter(Context context, List items) { + public List filter(List items) { if(properties.length == 0) { return items; } -- cgit v1.2.3 From 1993f779e8b25507a4096effd72618937c2f4ad0 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 19 Sep 2015 14:40:01 -0400 Subject: basic favorite functionality --- .../antennapod/core/feed/EventDistributor.java | 3 ++ .../danoeh/antennapod/core/storage/DBReader.java | 33 +++++++++++++ .../danoeh/antennapod/core/storage/DBWriter.java | 26 ++++++++-- .../antennapod/core/storage/PodDBAdapter.java | 56 +++++++++++++++++++++- core/src/main/res/values/strings.xml | 4 ++ 5 files changed, 116 insertions(+), 6 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/EventDistributor.java b/core/src/main/java/de/danoeh/antennapod/core/feed/EventDistributor.java index 20a85d43f..50911f74e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/EventDistributor.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/EventDistributor.java @@ -29,6 +29,7 @@ public class EventDistributor extends Observable { public static final int DOWNLOAD_QUEUED = 32; public static final int DOWNLOAD_HANDLED = 64; public static final int PLAYER_STATUS_UPDATE = 128; + public static final int FAVORITE_UPDATE = 256; private Handler handler; private AbstractQueue events; @@ -116,6 +117,8 @@ public class EventDistributor extends Observable { addEvent(PLAYER_STATUS_UPDATE); } + public void sendFavoriteUpdateBroadcast() { addEvent(FAVORITE_UPDATE); } + public static abstract class EventListener implements Observer { @Override diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 4ef4ac067..050af263f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -301,6 +301,22 @@ public final class DBReader { return items; } + /** + * Loads a list of FeedItems in Favorites + * @return + */ + public static List getFavorites() { + Log.d(TAG, "getFavorites"); + + try (PodDBAdapter adapter = PodDBAdapter.getInstance().open()) { + try (Cursor itemListCursor = adapter.getQueueCursor()) { + List items = extractItemlistFromCursor(adapter, itemListCursor); + loadFeedDataOfFeedItemlist(items); + return items; + } + } + } + /** * Loads a list of FeedItems whose episode has been downloaded. * @@ -367,6 +383,23 @@ public final class DBReader { return items; } + public static List getFavoriteItemsList() { + Log.d(TAG, "getFavoriteItemsList()"); + + PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + + Cursor itemlistCursor = adapter.getFavoritesCursor(); + List items = extractItemlistFromCursor(adapter, itemlistCursor); + itemlistCursor.close(); + + loadFeedDataOfFeedItemlist(items); + + adapter.close(); + + return items; + } + /** * Loads a list of FeedItems sorted by pubDate in descending order. * 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 521f960ec..190d032bf 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 @@ -371,7 +371,7 @@ public class DBWriter { queue.add(item); } queueModified = true; - if(item.isNew()) { + if (item.isNew()) { markAsUnplayedIds.add(item.getId()); } } @@ -380,8 +380,8 @@ public class DBWriter { if (queueModified) { adapter.setQueue(queue); EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED_ITEMS, queue)); - if(markAsUnplayedIds.size() > 0) { - DBWriter.markItemPlayed(FeedItem.UNPLAYED, markAsUnplayedIds.toArray()); + if (markAsUnplayedIds.size() > 0) { + DBWriter.markItemPlayed(FeedItem.UNPLAYED, markAsUnplayedIds.toArray()); } } } @@ -424,7 +424,7 @@ public class DBWriter { if (queue != null) { int position = queue.indexOf(item); - if(position >= 0) { + if (position >= 0) { queue.remove(position); adapter.setQueue(queue); EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.REMOVED, item, position)); @@ -442,6 +442,24 @@ public class DBWriter { } + public static Future addFavoriteItem(final FeedItem item) { + return dbExec.submit(() -> { + final PodDBAdapter adapter = PodDBAdapter.getInstance().open(); + adapter.addFavoriteItem(item); + adapter.close(); + EventDistributor.getInstance().sendFavoriteUpdateBroadcast(); + }); + } + + public static Future removeFavoriteItem(final FeedItem item) { + return dbExec.submit(() -> { + final PodDBAdapter adapter = PodDBAdapter.getInstance().open(); + adapter.removeFavoriteItem(item); + adapter.close(); + EventDistributor.getInstance().sendFavoriteUpdateBroadcast(); + }); + } + /** * Moves the specified item to the top of the queue. * @param itemId The item to move to the top of the queue 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 fa4a5726a..8061427be 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.greenrobot.event.EventBus; /** * Implements methods for accessing the database */ -public class PodDBAdapter { +public class PodDBAdapter implements AutoCloseable { private static final String TAG = "PodDBAdapter"; public static final String DATABASE_NAME = "Antennapod.db"; @@ -113,6 +113,7 @@ public class PodDBAdapter { public static final String TABLE_NAME_DOWNLOAD_LOG = "DownloadLog"; public static final String TABLE_NAME_QUEUE = "Queue"; public static final String TABLE_NAME_SIMPLECHAPTERS = "SimpleChapters"; + public static final String TABLE_NAME_FAVORITES = "Favorites"; // SQL Statements for creating new tables private static final String TABLE_PRIMARY_KEY = KEY_ID @@ -197,6 +198,10 @@ public class PodDBAdapter { public static final String CREATE_INDEX_SIMPLECHAPTERS_FEEDITEM = "CREATE INDEX " + TABLE_NAME_SIMPLECHAPTERS + "_" + KEY_FEEDITEM + " ON " + TABLE_NAME_SIMPLECHAPTERS + " (" + KEY_FEEDITEM + ")"; + + public static final String CREATE_TABLE_FAVORITES = "CREATE TABLE " + + TABLE_NAME_FAVORITES + "(" + KEY_ID + " INTEGER PRIMARY KEY," + + KEY_FEEDITEM + " INTEGER," + KEY_FEED + " INTEGER)"; /** * Select all columns from the feed-table @@ -785,6 +790,39 @@ public class PodDBAdapter { db.execSQL(sql); } + /** + * Adds the item to favorites + */ + public void addFavoriteItem(FeedItem item) { + // don't add an item that's already there... + if (isItemInFavorites(item)) { + Log.d(TAG, "item already in favorites"); + return; + } + ContentValues values = new ContentValues(); + values.put(KEY_FEEDITEM, item.getId()); + values.put(KEY_FEED, item.getFeedId()); + db.insert(TABLE_NAME_FAVORITES, null, values); + } + + public void removeFavoriteItem(FeedItem item) { + String deleteClause = String.format("DELETE FROM %s WHERE %s=%s AND %s=%s", + TABLE_NAME_FAVORITES, + KEY_FEEDITEM, item.getId(), + KEY_FEED, item.getFeedId()); + db.execSQL(deleteClause); + } + + public boolean isItemInFavorites(FeedItem item) { + String query = String.format("SELECT %s from %s WHERE %s=%d AND %s=%d", + KEY_ID, TABLE_NAME_FAVORITES, KEY_FEEDITEM, item.getId(), KEY_FEED, + item.getFeedId()); + Cursor c = db.rawQuery(query, null); + int count = c.getCount(); + c.close(); + return count > 0; + } + public long getDownloadLogSize() { final String query = String.format("SELECT COUNT(%s) FROM %s", KEY_ID, TABLE_NAME_DOWNLOAD_LOG); Cursor result = db.rawQuery(query, null); @@ -990,6 +1028,19 @@ public class PodDBAdapter { return c; } + + public final Cursor getFavoritesCursor() { + Object[] args = new String[] { + SEL_FI_SMALL_STR, + TABLE_NAME_FEED_ITEMS, TABLE_NAME_FAVORITES, + TABLE_NAME_FEED_ITEMS + "." + KEY_ID, + TABLE_NAME_FAVORITES + "." + KEY_FEEDITEM, + TABLE_NAME_FAVORITES + "." + KEY_ID }; + String query = String.format("SELECT %s FROM %s INNER JOIN %s ON %s=%s ORDER BY %s", args); + Cursor c = db.rawQuery(query, null); + return c; + } + /** * Returns a cursor which contains all feed items in the unread items list. * The returned cursor uses the FEEDITEM_SEL_FI_SMALL selection. @@ -1374,7 +1425,7 @@ public class PodDBAdapter { */ private static class PodDBHelper extends SQLiteOpenHelper { - private final static int VERSION = 1030002; + private final static int VERSION = 1040000; private Context context; @@ -1400,6 +1451,7 @@ public class PodDBAdapter { db.execSQL(CREATE_TABLE_DOWNLOAD_LOG); db.execSQL(CREATE_TABLE_QUEUE); db.execSQL(CREATE_TABLE_SIMPLECHAPTERS); + db.execSQL(CREATE_TABLE_FAVORITES); db.execSQL(CREATE_INDEX_FEEDITEMS_FEED); db.execSQL(CREATE_INDEX_FEEDITEMS_IMAGE); diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index ff9891bab..b377cbb13 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -12,6 +12,7 @@ New Episodes All Episodes All + Favorites New Waiting List Settings @@ -137,6 +138,8 @@ Add to Queue Added to Queue Remove from Queue + Add to Favorites + Remove from Favorites Visit Website Flattr this Enqueue all @@ -145,6 +148,7 @@ Activate Auto Download Deactivate Auto Download Reset Playback Position + Removed from favorites successful -- cgit v1.2.3 From ed679b8a17b4c140a8cc0fc1c312c7996f12d5d7 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 20 Sep 2015 14:54:54 -0400 Subject: refactored after merging in changes from #1212 --- .../java/de/danoeh/antennapod/core/storage/DBReader.java | 16 ---------------- .../de/danoeh/antennapod/core/storage/PodDBAdapter.java | 5 ++--- 2 files changed, 2 insertions(+), 19 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 050af263f..efa655f8b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -301,22 +301,6 @@ public final class DBReader { return items; } - /** - * Loads a list of FeedItems in Favorites - * @return - */ - public static List getFavorites() { - Log.d(TAG, "getFavorites"); - - try (PodDBAdapter adapter = PodDBAdapter.getInstance().open()) { - try (Cursor itemListCursor = adapter.getQueueCursor()) { - List items = extractItemlistFromCursor(adapter, itemListCursor); - loadFeedDataOfFeedItemlist(items); - return items; - } - } - } - /** * Loads a list of FeedItems whose episode has been downloaded. * 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 8061427be..730b02f1d 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 @@ -814,9 +814,8 @@ public class PodDBAdapter implements AutoCloseable { } public boolean isItemInFavorites(FeedItem item) { - String query = String.format("SELECT %s from %s WHERE %s=%d AND %s=%d", - KEY_ID, TABLE_NAME_FAVORITES, KEY_FEEDITEM, item.getId(), KEY_FEED, - item.getFeedId()); + String query = String.format("SELECT %s from %s WHERE %s=%d", + KEY_ID, TABLE_NAME_FAVORITES, KEY_FEEDITEM, item.getId()); Cursor c = db.rawQuery(query, null); int count = c.getCount(); c.close(); -- cgit v1.2.3 From dfbd878afe937e87f63d7c4e88a09ea669eff069 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 20 Sep 2015 16:11:57 -0400 Subject: Added 'tags' to FeedItem and properly showing/not showing menu items for favorites. --- .../antennapod/core/event/FavoritesEvent.java | 38 ++++++++++++++ .../danoeh/antennapod/core/event/QueueEvent.java | 53 +++++++++++++++++++ .../antennapod/core/feed/EventDistributor.java | 7 +-- .../de/danoeh/antennapod/core/feed/FeedItem.java | 27 ++++++++++ .../de/danoeh/antennapod/core/feed/QueueEvent.java | 51 ------------------ .../core/service/download/DownloadService.java | 2 +- .../playback/PlaybackServiceTaskManager.java | 2 +- .../danoeh/antennapod/core/storage/DBReader.java | 60 ++++++++++++++++++---- .../de/danoeh/antennapod/core/storage/DBTasks.java | 8 +-- .../danoeh/antennapod/core/storage/DBWriter.java | 21 ++++++-- 10 files changed, 190 insertions(+), 79 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/event/FavoritesEvent.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/event/QueueEvent.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/FavoritesEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/FavoritesEvent.java new file mode 100644 index 000000000..d09f6802f --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/event/FavoritesEvent.java @@ -0,0 +1,38 @@ +package de.danoeh.antennapod.core.event; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import de.danoeh.antennapod.core.feed.FeedItem; + +public class FavoritesEvent { + + public enum Action { + ADDED, REMOVED + } + + public final Action action; + public final FeedItem item; + + private FavoritesEvent(Action action, FeedItem item) { + this.action = action; + this.item = item; + } + + public static FavoritesEvent added(FeedItem item) { + return new FavoritesEvent(Action.ADDED, item); + } + + public static FavoritesEvent removed(FeedItem item) { + return new FavoritesEvent(Action.REMOVED, item); + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("action", action) + .append("item", item) + .toString(); + } + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/QueueEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/QueueEvent.java new file mode 100644 index 000000000..4d59d75eb --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/event/QueueEvent.java @@ -0,0 +1,53 @@ +package de.danoeh.antennapod.core.event; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.List; + +import de.danoeh.antennapod.core.feed.FeedItem; + +public class QueueEvent { + + public enum Action { + ADDED, ADDED_ITEMS, REMOVED, IRREVERSIBLE_REMOVED, CLEARED, DELETED_MEDIA, SORTED, MOVED + } + + public final Action action; + public final FeedItem item; + public final int position; + public final List items; + + public QueueEvent(Action action) { + this(action, null, null, -1); + } + + public QueueEvent(Action action, FeedItem item) { + this(action, item, null, -1); + } + + public QueueEvent(Action action, FeedItem item, int position) { + this(action, item, null, position); + } + + public QueueEvent(Action action, List items) { + this(action, null, items, -1); + } + + private QueueEvent(Action action, FeedItem item, List items, int position) { + this.action = action; + this.item = item; + this.items = items; + this.position = position; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("action", action) + .append("item", item) + .append("items", items) + .append("position", position) + .toString(); + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/EventDistributor.java b/core/src/main/java/de/danoeh/antennapod/core/feed/EventDistributor.java index 50911f74e..2667a2e12 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/EventDistributor.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/EventDistributor.java @@ -29,7 +29,6 @@ public class EventDistributor extends Observable { public static final int DOWNLOAD_QUEUED = 32; public static final int DOWNLOAD_HANDLED = 64; public static final int PLAYER_STATUS_UPDATE = 128; - public static final int FAVORITE_UPDATE = 256; private Handler handler; private AbstractQueue events; @@ -113,11 +112,7 @@ public class EventDistributor extends Observable { addEvent(DOWNLOAD_HANDLED); } - public void sendPlayerStatusUpdateBroadcast() { - addEvent(PLAYER_STATUS_UPDATE); - } - - public void sendFavoriteUpdateBroadcast() { addEvent(FAVORITE_UPDATE); } + public void sendPlayerStatusUpdateBroadcast() { addEvent(PLAYER_STATUS_UPDATE); } public static abstract class EventListener implements Observer { diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java index 5c3ed303f..c54cc1d5b 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java @@ -7,7 +7,9 @@ import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import java.util.Date; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.Callable; import de.danoeh.antennapod.core.asynctask.ImageResource; @@ -24,6 +26,11 @@ import de.danoeh.antennapod.core.util.flattr.FlattrThing; */ public class FeedItem extends FeedComponent implements ShownotesProvider, FlattrThing, ImageResource { + /** tag that indicates this item is in the queue */ + public static final String TAG_QUEUE = "Queue"; + /** tag that indicates this item is in favorites */ + public static final String TAG_FAVORITE = "Favorite"; + /** * The id/guid that can be found in the rss/atom feed. Might not be set. */ @@ -70,6 +77,11 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr private boolean autoDownload = true; + /** + * Any tags assigned to this item + */ + private Set tags = new HashSet<>(); + public FeedItem() { this.state = UNPLAYED; this.flattrStatus = new FlattrStatus(); @@ -451,6 +463,21 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr this.getAutoDownload(); } + /** + * @return true if the item has this tag + */ + public boolean isTagged(String tag) { return tags.contains(tag); } + + /** + * @param tag adds this tag to the item. NOTE: does NOT persist to the database + */ + public void addTag(String tag) { tags.add(tag); } + + /** + * @param tag the to remove + */ + public void removeTag(String tag) { tags.remove(tag); } + @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java b/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java deleted file mode 100644 index 97d086e5b..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/QueueEvent.java +++ /dev/null @@ -1,51 +0,0 @@ -package de.danoeh.antennapod.core.feed; - -import org.apache.commons.lang3.builder.ToStringBuilder; -import org.apache.commons.lang3.builder.ToStringStyle; - -import java.util.List; - -public class QueueEvent { - - public enum Action { - ADDED, ADDED_ITEMS, REMOVED, IRREVERSIBLE_REMOVED, CLEARED, DELETED_MEDIA, SORTED, MOVED - } - - public final Action action; - public final FeedItem item; - public final int position; - public final List items; - - public QueueEvent(Action action) { - this(action, null, null, -1); - } - - public QueueEvent(Action action, FeedItem item) { - this(action, item, null, -1); - } - - public QueueEvent(Action action, FeedItem item, int position) { - this(action, item, null, position); - } - - public QueueEvent(Action action, List items) { - this(action, null, items, -1); - } - - private QueueEvent(Action action, FeedItem item, List items, int position) { - this.action = action; - this.item = item; - this.items = items; - this.position = position; - } - - @Override - public String toString() { - return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) - .append("action", action) - .append("item", item) - .append("items", items) - .append("position", position) - .toString(); - } -} 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 36ea1e222..cb050463e 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 @@ -1129,7 +1129,7 @@ public class DownloadService extends Service { DBWriter.setFeedMedia(media).get(); if (!DBTasks.isInQueue(DownloadService.this, item.getId())) { - DBWriter.addQueueItem(DownloadService.this, item.getId()).get(); + DBWriter.addQueueItem(DownloadService.this, item).get(); } } catch (ExecutionException e) { e.printStackTrace(); 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 dba66a36d..19ef6ef09 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,7 +16,7 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import de.danoeh.antennapod.core.feed.FeedItem; -import de.danoeh.antennapod.core.feed.QueueEvent; +import de.danoeh.antennapod.core.event.QueueEvent; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.util.playback.Playable; import de.greenrobot.event.EventBus; diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index efa655f8b..d95e4ff02 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -104,6 +104,30 @@ public final class DBReader { return result; } + + /** + * Loads additional data in to the feed items from other database queries + * @param items the FeedItems who should have other data loaded + */ + public static void loadAdditionalFeedItemListData(List items) { + loadTagsOfFeedItemList(items); + loadFeedDataOfFeedItemList(items); + } + + public static void loadTagsOfFeedItemList(List items) { + LongList favoriteIds = getFavoriteIDList(); + LongList queueIds = getQueueIDList(); + + for (FeedItem item : items) { + if (favoriteIds.contains(item.getId())) { + item.addTag(FeedItem.TAG_FAVORITE); + } + if (queueIds.contains(item.getId())) { + item.addTag(FeedItem.TAG_QUEUE); + } + } + } + /** * Takes a list of FeedItems and loads their corresponding Feed-objects from the database. * The feedID-attribute of a FeedItem must be set to the ID of its feed or the method will @@ -111,7 +135,7 @@ public final class DBReader { * * @param items The FeedItems whose Feed-objects should be loaded. */ - public static void loadFeedDataOfFeedItemlist(List items) { + public static void loadFeedDataOfFeedItemList(List items) { List feeds = getFeedList(); for (FeedItem item : items) { for (Feed feed : feeds) { @@ -251,7 +275,7 @@ public final class DBReader { Cursor itemlistCursor = adapter.getQueueCursor(); List items = extractItemlistFromCursor(adapter, itemlistCursor); itemlistCursor.close(); - loadFeedDataOfFeedItemlist(items); + loadAdditionalFeedItemListData(items); return items; } @@ -316,7 +340,7 @@ public final class DBReader { List items = extractItemlistFromCursor(adapter, itemlistCursor); itemlistCursor.close(); - loadFeedDataOfFeedItemlist(items); + loadAdditionalFeedItemListData(items); Collections.sort(items, new FeedItemPubdateComparator()); adapter.close(); @@ -338,7 +362,7 @@ public final class DBReader { List items = extractItemlistFromCursor(adapter, itemlistCursor); itemlistCursor.close(); - loadFeedDataOfFeedItemlist(items); + loadAdditionalFeedItemListData(items); adapter.close(); @@ -360,7 +384,7 @@ public final class DBReader { List items = extractItemlistFromCursor(adapter, itemlistCursor); itemlistCursor.close(); - loadFeedDataOfFeedItemlist(items); + loadAdditionalFeedItemListData(items); adapter.close(); @@ -377,13 +401,27 @@ public final class DBReader { List items = extractItemlistFromCursor(adapter, itemlistCursor); itemlistCursor.close(); - loadFeedDataOfFeedItemlist(items); + loadAdditionalFeedItemListData(items); adapter.close(); return items; } + static LongList getFavoriteIDList() { + PodDBAdapter adapter = PodDBAdapter.getInstance().open(); + Cursor favoritesCursor = adapter.getFavoritesCursor(); + + LongList favoriteIDs = new LongList(favoritesCursor.getCount()); + if (favoritesCursor.moveToFirst()) { + do { + favoriteIDs.add(favoritesCursor.getLong(0)); + } while (favoritesCursor.moveToNext()); + } + favoritesCursor.close(); + return favoriteIDs; + } + /** * Loads a list of FeedItems sorted by pubDate in descending order. * @@ -399,7 +437,7 @@ public final class DBReader { List items = extractItemlistFromCursor(adapter, itemlistCursor); itemlistCursor.close(); - loadFeedDataOfFeedItemlist(items); + loadAdditionalFeedItemListData(items); adapter.close(); @@ -428,7 +466,7 @@ public final class DBReader { mediaCursor.close(); Cursor itemCursor = adapter.getFeedItemCursor(itemIds); List items = extractItemlistFromCursor(adapter, itemCursor); - loadFeedDataOfFeedItemlist(items); + loadAdditionalFeedItemListData(items); itemCursor.close(); adapter.close(); @@ -550,7 +588,7 @@ public final class DBReader { List list = extractItemlistFromCursor(adapter, itemCursor); if (list.size() > 0) { item = list.get(0); - loadFeedDataOfFeedItemlist(list); + loadAdditionalFeedItemListData(list); if (item.hasChapters()) { loadChaptersOfFeedItem(adapter, item); } @@ -573,7 +611,7 @@ public final class DBReader { Cursor itemCursor = adapter.getFeedItemCursor(ids); if (itemCursor.moveToFirst()) { result = extractItemlistFromCursor(adapter, itemCursor); - loadFeedDataOfFeedItemlist(result); + loadAdditionalFeedItemListData(result); for(FeedItem item : result) { if (item.hasChapters()) { loadChaptersOfFeedItem(adapter, item); @@ -613,7 +651,7 @@ public final class DBReader { List list = extractItemlistFromCursor(adapter, itemCursor); if (list.size() > 0) { item = list.get(0); - loadFeedDataOfFeedItemlist(list); + loadAdditionalFeedItemListData(list); if (item.hasChapters()) { loadChaptersOfFeedItem(adapter, item); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index 96a632d68..3f9cece77 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -601,7 +601,7 @@ public final class DBTasks { Cursor searchResult = adapter.searchItemTitles(feedID, query); List items = DBReader.extractItemlistFromCursor(searchResult); - DBReader.loadFeedDataOfFeedItemlist(items); + DBReader.loadAdditionalFeedItemListData(items); setResult(items); searchResult.close(); } @@ -625,7 +625,7 @@ public final class DBTasks { Cursor searchResult = adapter.searchItemDescriptions(feedID, query); List items = DBReader.extractItemlistFromCursor(searchResult); - DBReader.loadFeedDataOfFeedItemlist(items); + DBReader.loadAdditionalFeedItemListData(items); setResult(items); searchResult.close(); } @@ -649,7 +649,7 @@ public final class DBTasks { Cursor searchResult = adapter.searchItemContentEncoded(feedID, query); List items = DBReader.extractItemlistFromCursor(searchResult); - DBReader.loadFeedDataOfFeedItemlist(items); + DBReader.loadAdditionalFeedItemListData(items); setResult(items); searchResult.close(); } @@ -672,7 +672,7 @@ public final class DBTasks { Cursor searchResult = adapter.searchItemChapters(feedID, query); List items = DBReader.extractItemlistFromCursor(searchResult); - DBReader.loadFeedDataOfFeedItemlist(items); + DBReader.loadAdditionalFeedItemListData(items); setResult(items); searchResult.close(); } 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 190d032bf..f4f2a1bfa 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 @@ -26,6 +26,7 @@ import java.util.concurrent.Future; import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.asynctask.FlattrClickWorker; +import de.danoeh.antennapod.core.event.FavoritesEvent; import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedEvent; @@ -33,7 +34,7 @@ import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.FeedPreferences; -import de.danoeh.antennapod.core.feed.QueueEvent; +import de.danoeh.antennapod.core.event.QueueEvent; import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeAction; import de.danoeh.antennapod.core.preferences.GpodnetPreferences; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; @@ -317,6 +318,8 @@ public class DBWriter { if (item != null) { queue.add(index, item); adapter.setQueue(queue); + // no need to tag the item here, since we got it right out of the database + // and no one is ever going to see it... EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED, item, index)); if (item.isNew()) { DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId()); @@ -335,8 +338,13 @@ public class DBWriter { } public static Future addQueueItem(final Context context, - final long... itemIds) { - return addQueueItem(context, false, itemIds); + final FeedItem... items) { + LongList itemIds = new LongList(items.length); + for (FeedItem item : items) { + itemIds.add(item.getId()); + item.addTag(FeedItem.TAG_QUEUE); + } + return addQueueItem(context, false, itemIds.toArray()); } /** @@ -427,6 +435,7 @@ public class DBWriter { if (position >= 0) { queue.remove(position); adapter.setQueue(queue); + item.removeTag(FeedItem.TAG_QUEUE); EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.REMOVED, item, position)); } else { Log.w(TAG, "Queue was not modified by call to removeQueueItem"); @@ -447,7 +456,8 @@ public class DBWriter { final PodDBAdapter adapter = PodDBAdapter.getInstance().open(); adapter.addFavoriteItem(item); adapter.close(); - EventDistributor.getInstance().sendFavoriteUpdateBroadcast(); + item.addTag(FeedItem.TAG_FAVORITE); + EventBus.getDefault().post(FavoritesEvent.added(item)); }); } @@ -456,7 +466,8 @@ public class DBWriter { final PodDBAdapter adapter = PodDBAdapter.getInstance().open(); adapter.removeFavoriteItem(item); adapter.close(); - EventDistributor.getInstance().sendFavoriteUpdateBroadcast(); + item.removeTag(FeedItem.TAG_FAVORITE); + EventBus.getDefault().post(FavoritesEvent.removed(item)); }); } -- cgit v1.2.3 From 721bfc064a861f09cd390baba9b986f5a3802e50 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 20 Sep 2015 16:31:44 -0400 Subject: now removing items from favorites by swiping --- core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java | 4 ++++ core/src/main/res/values/strings.xml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'core/src/main') 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 f4f2a1bfa..dbdb24a61 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 @@ -461,6 +461,10 @@ public class DBWriter { }); } + public static Future addFavoriteItemById(final long itemId) { + return addFavoriteItem(DBReader.getFeedItem(itemId)); + } + public static Future removeFavoriteItem(final FeedItem item) { return dbExec.submit(() -> { final PodDBAdapter adapter = PodDBAdapter.getInstance().open(); diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index b377cbb13..951b0b9ba 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -148,7 +148,7 @@ Activate Auto Download Deactivate Auto Download Reset Playback Position - Removed from favorites + Item removed successful -- cgit v1.2.3 From 3638eed2206468d4ea369b15c0e10c5885c52041 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 20 Sep 2015 16:33:57 -0400 Subject: we do need to tag the item in addQueueItemAt --- core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'core/src/main') 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 dbdb24a61..f89099efb 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 @@ -318,8 +318,7 @@ public class DBWriter { if (item != null) { queue.add(index, item); adapter.setQueue(queue); - // no need to tag the item here, since we got it right out of the database - // and no one is ever going to see it... + item.addTag(FeedItem.TAG_QUEUE); EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED, item, index)); if (item.isNew()) { DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId()); -- cgit v1.2.3 From c00b5f4033f6c4e74d5a30efd253482250510477 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 20 Sep 2015 17:03:52 -0400 Subject: we can't delegate here --- .../java/de/danoeh/antennapod/core/storage/DBWriter.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'core/src/main') 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 f89099efb..bae31b52b 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 @@ -461,7 +461,18 @@ public class DBWriter { } public static Future addFavoriteItemById(final long itemId) { - return addFavoriteItem(DBReader.getFeedItem(itemId)); + return dbExec.submit(() -> { + final FeedItem item = DBReader.getFeedItem(itemId); + if (item == null) { + Log.d(TAG, "Can't find item for itemId " + itemId); + return; + } + final PodDBAdapter adapter = PodDBAdapter.getInstance().open(); + adapter.addFavoriteItem(item); + adapter.close(); + item.addTag(FeedItem.TAG_FAVORITE); + EventBus.getDefault().post(FavoritesEvent.added(item)); + }); } public static Future removeFavoriteItem(final FeedItem item) { -- cgit v1.2.3 From 4207950268cd5a87bed443d6ea43f87b3b90bdea Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 20 Sep 2015 19:10:10 -0400 Subject: add skip episode to playback notification --- .../core/service/playback/PlaybackService.java | 25 +++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'core/src/main') 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 9b6d17b98..65ea6a29f 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 @@ -48,6 +48,7 @@ import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.receiver.MediaButtonReceiver; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; +import de.danoeh.antennapod.core.util.IntList; import de.danoeh.antennapod.core.util.QueueAccess; import de.danoeh.antennapod.core.util.flattr.FlattrUtils; import de.danoeh.antennapod.core.util.playback.Playable; @@ -342,6 +343,8 @@ public class PlaybackService extends Service { break; case KeyEvent.KEYCODE_MEDIA_NEXT: + endPlayback(true); + break; case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: mediaPlayer.seekDelta(UserPreferences.getFastFowardSecs() * 1000); break; @@ -852,6 +855,15 @@ public class PlaybackService extends Service { .getService(PlaybackService.this, 2, stopButtonIntent, PendingIntent.FLAG_UPDATE_CURRENT); + Intent skipButtonIntent = new Intent( + PlaybackService.this, PlaybackService.class); + skipButtonIntent.putExtra( + MediaButtonReceiver.EXTRA_KEYCODE, + KeyEvent.KEYCODE_MEDIA_NEXT); + PendingIntent skipButtonPendingIntent = PendingIntent + .getService(PlaybackService.this, 3, + skipButtonIntent, + PendingIntent.FLAG_UPDATE_CURRENT); Notification.Builder notificationBuilder = new Notification.Builder( PlaybackService.this) .setContentTitle(contentTitle) @@ -861,25 +873,36 @@ public class PlaybackService extends Service { .setLargeIcon(icon) .setSmallIcon(smallIcon) .setPriority(UserPreferences.getNotifyPriority()); // set notification priority + IntList actionList = new IntList(); + int actionIndex = 0; if (playerStatus == PlayerStatus.PLAYING) { notificationBuilder.addAction(android.R.drawable.ic_media_pause, //pause action getString(R.string.pause_label), pauseButtonPendingIntent); + actionList.add(actionIndex++); } else { notificationBuilder.addAction(android.R.drawable.ic_media_play, //play action getString(R.string.play_label), playButtonPendingIntent); + actionList.add(actionIndex++); + } + if (UserPreferences.isFollowQueue()) { + notificationBuilder.addAction(android.R.drawable.ic_media_next, + getString(R.string.skip_episode_label), + skipButtonPendingIntent); + actionList.add(actionIndex++); } if (UserPreferences.isPersistNotify()) { notificationBuilder.addAction(android.R.drawable.ic_menu_close_clear_cancel, // stop action getString(R.string.stop_label), stopButtonPendingIntent); + actionList.add(actionIndex++); } if (Build.VERSION.SDK_INT >= 21) { notificationBuilder.setStyle(new Notification.MediaStyle() .setMediaSession((android.media.session.MediaSession.Token) mediaPlayer.getSessionToken().getToken()) - .setShowActionsInCompactView(0)) + .setShowActionsInCompactView(actionList.toArray())) .setVisibility(Notification.VISIBILITY_PUBLIC) .setColor(Notification.COLOR_DEFAULT); } -- cgit v1.2.3 From 73a16b4be824f9660c471fac2abf7976f63b833e Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 20 Sep 2015 19:13:19 -0400 Subject: swap feed and episode titles, get rid of time --- .../de/danoeh/antennapod/core/service/playback/PlaybackService.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'core/src/main') 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 65ea6a29f..a0ac9d591 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 @@ -824,8 +824,8 @@ public class PlaybackService extends Service { final int smallIcon = ClientConfig.playbackServiceCallbacks.getNotificationIconResource(getApplicationContext()); if (!Thread.currentThread().isInterrupted() && started && info.playable != null) { - String contentText = info.playable.getFeedTitle(); - String contentTitle = info.playable.getEpisodeTitle(); + String contentText = info.playable.getEpisodeTitle(); + String contentTitle = info.playable.getFeedTitle(); Notification notification = null; if (android.os.Build.VERSION.SDK_INT >= 16) { Intent pauseButtonIntent = new Intent( // pause button intent @@ -872,6 +872,7 @@ public class PlaybackService extends Service { .setContentIntent(pIntent) .setLargeIcon(icon) .setSmallIcon(smallIcon) + .setWhen(0) // we don't need the time .setPriority(UserPreferences.getNotifyPriority()); // set notification priority IntList actionList = new IntList(); int actionIndex = 0; -- cgit v1.2.3 From f0904fbe49f9b92b850de0bd3460fec286003732 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 20 Sep 2015 20:10:51 -0400 Subject: added preference to not remove items from queue when skipping --- .../danoeh/antennapod/core/preferences/UserPreferences.java | 3 +++ .../antennapod/core/service/playback/PlaybackService.java | 11 +++++------ core/src/main/res/values/strings.xml | 2 ++ 3 files changed, 10 insertions(+), 6 deletions(-) (limited to 'core/src/main') 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 e6a2a2464..ca9fbb1ba 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 @@ -57,6 +57,7 @@ public class UserPreferences { public static final String PREF_PAUSE_ON_HEADSET_DISCONNECT = "prefPauseOnHeadsetDisconnect"; public static final String PREF_UNPAUSE_ON_HEADSET_RECONNECT = "prefUnpauseOnHeadsetReconnect"; public static final String PREF_FOLLOW_QUEUE = "prefFollowQueue"; + public static final String PREF_SKIP_REMOVES = "prefSkipRemovesFromQueue"; public static final String PREF_AUTO_DELETE = "prefAutoDelete"; public static final String PREF_SMART_MARK_AS_PLAYED_SECS = "prefSmartMarkAsPlayedSecs"; public static final String PREF_PLAYBACK_SPEED_ARRAY = "prefPlaybackSpeedArray"; @@ -216,6 +217,8 @@ public class UserPreferences { return prefs.getBoolean(PREF_FOLLOW_QUEUE, false); } + public static boolean isSkipRemoveFromQueue() { return prefs.getBoolean(PREF_SKIP_REMOVES, false); } + public static boolean isAutoDelete() { return prefs.getBoolean(PREF_AUTO_DELETE, false); } 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 a0ac9d591..30c30a5bc 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 @@ -577,7 +577,7 @@ public class PlaybackService extends Service { e.printStackTrace(); // isInQueue remains false } - if (isInQueue) { + if (isInQueue && UserPreferences.isSkipRemoveFromQueue()) { DBWriter.removeQueueItem(PlaybackService.this, item, true); } DBWriter.addItemToPlaybackHistory(media); @@ -875,29 +875,28 @@ public class PlaybackService extends Service { .setWhen(0) // we don't need the time .setPriority(UserPreferences.getNotifyPriority()); // set notification priority IntList actionList = new IntList(); - int actionIndex = 0; if (playerStatus == PlayerStatus.PLAYING) { notificationBuilder.addAction(android.R.drawable.ic_media_pause, //pause action getString(R.string.pause_label), pauseButtonPendingIntent); - actionList.add(actionIndex++); + actionList.add(actionList.size()); } else { notificationBuilder.addAction(android.R.drawable.ic_media_play, //play action getString(R.string.play_label), playButtonPendingIntent); - actionList.add(actionIndex++); + actionList.add(actionList.size()); } if (UserPreferences.isFollowQueue()) { notificationBuilder.addAction(android.R.drawable.ic_media_next, getString(R.string.skip_episode_label), skipButtonPendingIntent); - actionList.add(actionIndex++); + actionList.add(actionList.size()); } if (UserPreferences.isPersistNotify()) { notificationBuilder.addAction(android.R.drawable.ic_menu_close_clear_cancel, // stop action getString(R.string.stop_label), stopButtonPendingIntent); - actionList.add(actionIndex++); + actionList.add(actionList.size()); } if (Build.VERSION.SDK_INT >= 21) { diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index ff9891bab..ffa6a781a 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -268,6 +268,8 @@ Auto Delete Mark episodes as played even if less than a certain amount of seconds of playing time is still left Smart mark as played + Remove episodes from the queue when they are skipped + Skip removes episode Playback Network Update Interval or Time of Day -- cgit v1.2.3 From 6d0465ad13a28de97a445dd4ffcd96db054b893f Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 20 Sep 2015 20:12:39 -0400 Subject: title case --- core/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index ffa6a781a..fd5481748 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -269,7 +269,7 @@ Mark episodes as played even if less than a certain amount of seconds of playing time is still left Smart mark as played Remove episodes from the queue when they are skipped - Skip removes episode + Skip Removes Episode Playback Network Update Interval or Time of Day -- cgit v1.2.3 From 5b6fce427b756ee0675ee0eccf47190e8458bb81 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Mon, 21 Sep 2015 06:48:28 -0400 Subject: if it was skipped we shouldn't remove it, but otherwise we should --- .../core/preferences/UserPreferences.java | 2 +- .../core/service/playback/PlaybackService.java | 14 +++--- .../playback/PlaybackServiceMediaPlayer.java | 53 ++++++++++------------ 3 files changed, 32 insertions(+), 37 deletions(-) (limited to 'core/src/main') 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 ca9fbb1ba..c4c7a9b0b 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 @@ -217,7 +217,7 @@ public class UserPreferences { return prefs.getBoolean(PREF_FOLLOW_QUEUE, false); } - public static boolean isSkipRemoveFromQueue() { return prefs.getBoolean(PREF_SKIP_REMOVES, false); } + public static boolean shouldSkipRemoveFromQueue() { return prefs.getBoolean(PREF_SKIP_REMOVES, false); } public static boolean isAutoDelete() { return prefs.getBoolean(PREF_AUTO_DELETE, false); 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 30c30a5bc..c3934ff01 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 @@ -14,7 +14,6 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.AudioManager; import android.media.MediaPlayer; -import android.media.RemoteControlClient; import android.os.Binder; import android.os.Build; import android.os.IBinder; @@ -164,7 +163,6 @@ public class PlaybackService extends Service { private static final int NOTIFICATION_ID = 1; - private RemoteControlClient remoteControlClient; private PlaybackServiceMediaPlayer mediaPlayer; private PlaybackServiceTaskManager taskManager; @@ -343,7 +341,7 @@ public class PlaybackService extends Service { break; case KeyEvent.KEYCODE_MEDIA_NEXT: - endPlayback(true); + endPlayback(true, true); break; case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: mediaPlayer.seekDelta(UserPreferences.getFastFowardSecs() * 1000); @@ -544,13 +542,13 @@ public class PlaybackService extends Service { } @Override - public boolean endPlayback(boolean playNextEpisode) { - PlaybackService.this.endPlayback(true); + public boolean endPlayback(boolean playNextEpisode, boolean wasSkipped) { + PlaybackService.this.endPlayback(playNextEpisode, wasSkipped); return true; } }; - private void endPlayback(boolean playNextEpisode) { + private void endPlayback(boolean playNextEpisode, boolean wasSkipped) { Log.d(TAG, "Playback ended"); final Playable playable = mediaPlayer.getPlayable(); @@ -577,7 +575,7 @@ public class PlaybackService extends Service { e.printStackTrace(); // isInQueue remains false } - if (isInQueue && UserPreferences.isSkipRemoveFromQueue()) { + if (isInQueue && (!wasSkipped || UserPreferences.shouldSkipRemoveFromQueue())) { DBWriter.removeQueueItem(PlaybackService.this, item, true); } DBWriter.addItemToPlaybackHistory(media); @@ -1094,7 +1092,7 @@ public class PlaybackService extends Service { public void onReceive(Context context, Intent intent) { if (StringUtils.equals(intent.getAction(), ACTION_SKIP_CURRENT_EPISODE)) { Log.d(TAG, "Received SKIP_CURRENT_EPISODE intent"); - mediaPlayer.endPlayback(); + mediaPlayer.endPlayback(true); } } }; diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 7cf7eb622..705cb987a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -275,7 +275,7 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre private void updateMediaSessionMetadata() { executor.execute(() -> { final Playable p = this.media; - if(p == null) { + if (p == null) { return; } MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder(); @@ -930,25 +930,22 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre }; - public void endPlayback() { - executor.submit(new Runnable() { - @Override - public void run() { - playerLock.lock(); - releaseWifiLockIfNecessary(); - - if (playerStatus != PlayerStatus.INDETERMINATE) { - setPlayerStatus(PlayerStatus.INDETERMINATE, media); - } - if (mediaPlayer != null) { - mediaPlayer.reset(); + public void endPlayback(final boolean wasSkipped) { + executor.submit(() -> { + playerLock.lock(); + releaseWifiLockIfNecessary(); - } - audioManager.abandonAudioFocus(audioFocusChangeListener); - callback.endPlayback(true); + if (playerStatus != PlayerStatus.INDETERMINATE) { + setPlayerStatus(PlayerStatus.INDETERMINATE, media); + } + if (mediaPlayer != null) { + mediaPlayer.reset(); - playerLock.unlock(); } + audioManager.abandonAudioFocus(audioFocusChangeListener); + callback.endPlayback(true, wasSkipped); + + playerLock.unlock(); }); } @@ -1006,20 +1003,20 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre } } - public static interface PSMPCallback { - public void statusChanged(PSMPInfo newInfo); + public interface PSMPCallback { + void statusChanged(PSMPInfo newInfo); - public void shouldStop(); + void shouldStop(); - public void playbackSpeedChanged(float s); + void playbackSpeedChanged(float s); - public void onBufferingUpdate(int percent); + void onBufferingUpdate(int percent); - public boolean onMediaPlayerInfo(int code); + boolean onMediaPlayerInfo(int code); - public boolean onMediaPlayerError(Object inObj, int what, int extra); + boolean onMediaPlayerError(Object inObj, int what, int extra); - public boolean endPlayback(boolean playNextEpisode); + boolean endPlayback(boolean playNextEpisode, boolean wasSkipped); } private IPlayer setMediaPlayerListeners(IPlayer mp) { @@ -1062,7 +1059,7 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre }; private void genericOnCompletion() { - endPlayback(); + endPlayback(false); } private final org.antennapod.audio.MediaPlayer.OnBufferingUpdateListener audioBufferingUpdateListener = new org.antennapod.audio.MediaPlayer.OnBufferingUpdateListener() { @@ -1177,7 +1174,7 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre @Override public void onSkipToNext() { super.onSkipToNext(); - endPlayback(); + endPlayback(true); } @Override @@ -1266,7 +1263,7 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre case KeyEvent.KEYCODE_MEDIA_NEXT: { Log.d(TAG, "Received next event from RemoteControlClient"); - endPlayback(); + endPlayback(true); return true; } default: -- cgit v1.2.3 From 118285e8a2f5e6ab7f60cfb41648db67a7f97b22 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 22 Sep 2015 19:15:49 -0400 Subject: using newer appcompat libraries --- .../core/service/playback/PlaybackService.java | 166 ++++++++++----------- 1 file changed, 79 insertions(+), 87 deletions(-) (limited to 'core/src/main') 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 c3934ff01..1e67c7b2b 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 @@ -19,6 +19,7 @@ import android.os.Build; import android.os.IBinder; import android.preference.PreferenceManager; import android.support.v4.app.NotificationCompat; +import android.support.v4.media.session.MediaSessionCompat; import android.util.Log; import android.util.Pair; import android.view.KeyEvent; @@ -825,96 +826,87 @@ public class PlaybackService extends Service { String contentText = info.playable.getEpisodeTitle(); String contentTitle = info.playable.getFeedTitle(); Notification notification = null; - if (android.os.Build.VERSION.SDK_INT >= 16) { - Intent pauseButtonIntent = new Intent( // pause button intent - PlaybackService.this, PlaybackService.class); - pauseButtonIntent.putExtra( - MediaButtonReceiver.EXTRA_KEYCODE, - KeyEvent.KEYCODE_MEDIA_PAUSE); - PendingIntent pauseButtonPendingIntent = PendingIntent - .getService(PlaybackService.this, 0, - pauseButtonIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - Intent playButtonIntent = new Intent( // play button intent - PlaybackService.this, PlaybackService.class); - playButtonIntent.putExtra( - MediaButtonReceiver.EXTRA_KEYCODE, - KeyEvent.KEYCODE_MEDIA_PLAY); - PendingIntent playButtonPendingIntent = PendingIntent - .getService(PlaybackService.this, 1, - playButtonIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - Intent stopButtonIntent = new Intent( // stop button intent - PlaybackService.this, PlaybackService.class); - stopButtonIntent.putExtra( - MediaButtonReceiver.EXTRA_KEYCODE, - KeyEvent.KEYCODE_MEDIA_STOP); - PendingIntent stopButtonPendingIntent = PendingIntent - .getService(PlaybackService.this, 2, - stopButtonIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - Intent skipButtonIntent = new Intent( - PlaybackService.this, PlaybackService.class); - skipButtonIntent.putExtra( - MediaButtonReceiver.EXTRA_KEYCODE, - KeyEvent.KEYCODE_MEDIA_NEXT); - PendingIntent skipButtonPendingIntent = PendingIntent - .getService(PlaybackService.this, 3, - skipButtonIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - Notification.Builder notificationBuilder = new Notification.Builder( - PlaybackService.this) - .setContentTitle(contentTitle) - .setContentText(contentText) - .setOngoing(true) - .setContentIntent(pIntent) - .setLargeIcon(icon) - .setSmallIcon(smallIcon) - .setWhen(0) // we don't need the time - .setPriority(UserPreferences.getNotifyPriority()); // set notification priority - IntList actionList = new IntList(); - if (playerStatus == PlayerStatus.PLAYING) { - notificationBuilder.addAction(android.R.drawable.ic_media_pause, //pause action - getString(R.string.pause_label), - pauseButtonPendingIntent); - actionList.add(actionList.size()); - } else { - notificationBuilder.addAction(android.R.drawable.ic_media_play, //play action - getString(R.string.play_label), - playButtonPendingIntent); - actionList.add(actionList.size()); - } - if (UserPreferences.isFollowQueue()) { - notificationBuilder.addAction(android.R.drawable.ic_media_next, - getString(R.string.skip_episode_label), - skipButtonPendingIntent); - actionList.add(actionList.size()); - } - if (UserPreferences.isPersistNotify()) { - notificationBuilder.addAction(android.R.drawable.ic_menu_close_clear_cancel, // stop action - getString(R.string.stop_label), - stopButtonPendingIntent); - actionList.add(actionList.size()); - } - if (Build.VERSION.SDK_INT >= 21) { - notificationBuilder.setStyle(new Notification.MediaStyle() - .setMediaSession((android.media.session.MediaSession.Token) mediaPlayer.getSessionToken().getToken()) - .setShowActionsInCompactView(actionList.toArray())) - .setVisibility(Notification.VISIBILITY_PUBLIC) - .setColor(Notification.COLOR_DEFAULT); - } - - notification = notificationBuilder.build(); + Intent pauseButtonIntent = new Intent( // pause button intent + PlaybackService.this, PlaybackService.class); + pauseButtonIntent.putExtra( + MediaButtonReceiver.EXTRA_KEYCODE, + KeyEvent.KEYCODE_MEDIA_PAUSE); + PendingIntent pauseButtonPendingIntent = PendingIntent + .getService(PlaybackService.this, 0, + pauseButtonIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + Intent playButtonIntent = new Intent( // play button intent + PlaybackService.this, PlaybackService.class); + playButtonIntent.putExtra( + MediaButtonReceiver.EXTRA_KEYCODE, + KeyEvent.KEYCODE_MEDIA_PLAY); + PendingIntent playButtonPendingIntent = PendingIntent + .getService(PlaybackService.this, 1, + playButtonIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + Intent stopButtonIntent = new Intent( // stop button intent + PlaybackService.this, PlaybackService.class); + stopButtonIntent.putExtra( + MediaButtonReceiver.EXTRA_KEYCODE, + KeyEvent.KEYCODE_MEDIA_STOP); + PendingIntent stopButtonPendingIntent = PendingIntent + .getService(PlaybackService.this, 2, + stopButtonIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + Intent skipButtonIntent = new Intent( + PlaybackService.this, PlaybackService.class); + skipButtonIntent.putExtra( + MediaButtonReceiver.EXTRA_KEYCODE, + KeyEvent.KEYCODE_MEDIA_NEXT); + PendingIntent skipButtonPendingIntent = PendingIntent + .getService(PlaybackService.this, 3, + skipButtonIntent, + PendingIntent.FLAG_UPDATE_CURRENT); + NotificationCompat.Builder notificationBuilder = new android.support.v7.app.NotificationCompat.Builder( + PlaybackService.this) + .setContentTitle(contentTitle) + .setContentText(contentText) + .setOngoing(true) + .setContentIntent(pIntent) + .setLargeIcon(icon) + .setSmallIcon(smallIcon) + .setWhen(0) // we don't need the time + .setPriority(UserPreferences.getNotifyPriority()); // set notification priority + IntList actionList = new IntList(); + if (playerStatus == PlayerStatus.PLAYING) { + notificationBuilder.addAction(android.R.drawable.ic_media_pause, //pause action + getString(R.string.pause_label), + pauseButtonPendingIntent); + actionList.add(actionList.size()); } else { - NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder( - PlaybackService.this) - .setContentTitle(contentTitle) - .setContentText(contentText).setOngoing(true) - .setContentIntent(pIntent).setLargeIcon(icon) - .setSmallIcon(smallIcon); - notification = notificationBuilder.build(); + notificationBuilder.addAction(android.R.drawable.ic_media_play, //play action + getString(R.string.play_label), + playButtonPendingIntent); + actionList.add(actionList.size()); + } + if (UserPreferences.isFollowQueue()) { + notificationBuilder.addAction(android.R.drawable.ic_media_next, + getString(R.string.skip_episode_label), + skipButtonPendingIntent); + actionList.add(actionList.size()); } + if (UserPreferences.isPersistNotify()) { + notificationBuilder.addAction(android.R.drawable.ic_menu_close_clear_cancel, // stop action + getString(R.string.stop_label), + stopButtonPendingIntent); + actionList.add(actionList.size()); + } + + notificationBuilder.setStyle(new android.support.v7.app.NotificationCompat.MediaStyle() + .setMediaSession(mediaPlayer.getSessionToken()) + .setShowActionsInCompactView(actionList.toArray()) + .setShowCancelButton(true)) + .setVisibility(Notification.VISIBILITY_PUBLIC) + .setColor(Notification.COLOR_DEFAULT); + + notification = notificationBuilder.build(); + startForeground(NOTIFICATION_ID, notification); Log.d(TAG, "Notification set up"); } -- cgit v1.2.3 From 754c1f4b373424c56ca2d7b178b78df2b9b02d1a Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Fri, 25 Sep 2015 17:56:11 -0400 Subject: use cancel button and enable swipe on 5.0+ --- .../core/service/playback/PlaybackService.java | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'core/src/main') 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 1e67c7b2b..200ab8054 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 @@ -2,6 +2,7 @@ package de.danoeh.antennapod.core.service.playback; import android.annotation.SuppressLint; import android.app.Notification; +import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.bluetooth.BluetoothA2dp; @@ -867,7 +868,7 @@ public class PlaybackService extends Service { PlaybackService.this) .setContentTitle(contentTitle) .setContentText(contentText) - .setOngoing(true) + .setOngoing(false) .setContentIntent(pIntent) .setLargeIcon(icon) .setSmallIcon(smallIcon) @@ -891,23 +892,26 @@ public class PlaybackService extends Service { skipButtonPendingIntent); actionList.add(actionList.size()); } - if (UserPreferences.isPersistNotify()) { - notificationBuilder.addAction(android.R.drawable.ic_menu_close_clear_cancel, // stop action - getString(R.string.stop_label), - stopButtonPendingIntent); - actionList.add(actionList.size()); - } notificationBuilder.setStyle(new android.support.v7.app.NotificationCompat.MediaStyle() .setMediaSession(mediaPlayer.getSessionToken()) .setShowActionsInCompactView(actionList.toArray()) - .setShowCancelButton(true)) + .setShowCancelButton(true) + .setCancelButtonIntent(stopButtonPendingIntent)) .setVisibility(Notification.VISIBILITY_PUBLIC) .setColor(Notification.COLOR_DEFAULT); notification = notificationBuilder.build(); - startForeground(NOTIFICATION_ID, notification); + if (playerStatus == PlayerStatus.PLAYING || + playerStatus == PlayerStatus.PREPARING || + playerStatus == PlayerStatus.SEEKING) { + startForeground(NOTIFICATION_ID, notification); + } else { + stopForeground(false); + NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + mNotificationManager.notify(NOTIFICATION_ID, notification); + } Log.d(TAG, "Notification set up"); } } -- cgit v1.2.3 From 664944d119000b79cd3574a7fd37bfc6ab2d19de Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Fri, 25 Sep 2015 18:10:49 -0400 Subject: alway follow queue by default --- .../java/de/danoeh/antennapod/core/preferences/UserPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') 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 c4c7a9b0b..0aa9f2876 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 @@ -214,7 +214,7 @@ public class UserPreferences { public static boolean isFollowQueue() { - return prefs.getBoolean(PREF_FOLLOW_QUEUE, false); + return prefs.getBoolean(PREF_FOLLOW_QUEUE, true); } public static boolean shouldSkipRemoveFromQueue() { return prefs.getBoolean(PREF_SKIP_REMOVES, false); } -- cgit v1.2.3 From b090e2bf650e91ee55c2773bcd2c257a412405af Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Fri, 25 Sep 2015 23:59:47 -0400 Subject: end playback the right way --- .../de/danoeh/antennapod/core/service/playback/PlaybackService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') 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 200ab8054..a040ee157 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 @@ -343,7 +343,7 @@ public class PlaybackService extends Service { break; case KeyEvent.KEYCODE_MEDIA_NEXT: - endPlayback(true, true); + mediaPlayer.endPlayback(true); break; case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: mediaPlayer.seekDelta(UserPreferences.getFastFowardSecs() * 1000); -- cgit v1.2.3 From c097b672d628cf893d103b7e582748b1152c937c Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 26 Sep 2015 11:11:48 -0400 Subject: fix bug that caused ExternalPlayerFragment to not always be shown --- .../java/de/danoeh/antennapod/core/util/playback/PlaybackController.java | 1 + 1 file changed, 1 insertion(+) (limited to 'core/src/main') 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 efeba888b..4eb955913 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 @@ -120,6 +120,7 @@ public abstract class PlaybackController { throw new IllegalStateException( "Can't call init() after release() has been called"); } + checkMediaInfoLoaded(); } /** -- cgit v1.2.3 From 8cd644691328d5700effb57dfdb5e042521678a4 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 26 Sep 2015 15:56:10 -0400 Subject: create the favorites table on upgrade --- .../main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'core/src/main') 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 730b02f1d..ff8745a5a 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 @@ -1424,7 +1424,7 @@ public class PodDBAdapter implements AutoCloseable { */ private static class PodDBHelper extends SQLiteOpenHelper { - private final static int VERSION = 1040000; + private final static int VERSION = 1040001; private Context context; @@ -1655,6 +1655,9 @@ public class PodDBAdapter implements AutoCloseable { "(read=1 OR id IN (SELECT feeditem FROM FeedMedia WHERE position>0 OR downloaded=1)) " + "AND id NOT IN (SELECT feeditem FROM Queue)"); } + if(oldVersion < 1040001) { + db.execSQL(CREATE_TABLE_FAVORITES); + } EventBus.getDefault().post(ProgressEvent.end()); } } -- cgit v1.2.3 From 72cf169401082709b1f3c8c6e0c6d352eae3bd32 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 27 Sep 2015 09:08:50 -0400 Subject: AutoCloseable isn't available on all APIs --- core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') 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 ff8745a5a..9e20693a3 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.greenrobot.event.EventBus; /** * Implements methods for accessing the database */ -public class PodDBAdapter implements AutoCloseable { +public class PodDBAdapter { private static final String TAG = "PodDBAdapter"; public static final String DATABASE_NAME = "Antennapod.db"; -- cgit v1.2.3 From d03c54d6fb6463a513aacd265dc3614806974cf9 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 27 Sep 2015 13:55:07 +0200 Subject: Variable Speed Dialog: Install Prestissimo or enable Sonic --- .../java/de/danoeh/antennapod/core/preferences/UserPreferences.java | 6 ++++++ core/src/main/res/values/strings.xml | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'core/src/main') 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 0aa9f2876..c0e53842f 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 @@ -480,6 +480,12 @@ public class UserPreferences { return prefs.getBoolean(PREF_SONIC, false); } + public static void enableSonic(boolean enable) { + prefs.edit() + .putBoolean(PREF_SONIC, enable) + .apply(); + } + /** * Return the folder where the app stores all of its data. This method will * return the standard data folder if none has been set by the user. diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 2881f7c41..ae1381de3 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -252,8 +252,9 @@ Download Plugin Plugin Not Installed - For variable speed playback to work, a third party library must be installed.\n\nTap \'Download Plugin\' to download a free plugin from the Play Store\n\nAny problems found using this plugin are not the responsibility of AntennaPod and should be reported to the plugin owner. + For variable speed playback to work, you have to install a third party library or enable the experimental Sonic player [Android 4.1+].\n\nTap \'Download Plugin\' to download a free plugin from the Play Store.\n\nAny problems found using this plugin are not the responsibility of AntennaPod and should be reported to the plugin owner. Playback Speeds + Enable Sonic There are no items in this list. -- cgit v1.2.3 From d037a8b901e9ed864dc92b8ac453eadaa0c90020 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 27 Sep 2015 13:55:48 +0200 Subject: If media player position makes no sense, get position from media --- .../antennapod/core/service/playback/PlaybackServiceMediaPlayer.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 705cb987a..9d6827ed9 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -584,6 +584,9 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre || playerStatus == PlayerStatus.PREPARED || playerStatus == PlayerStatus.SEEKING) { retVal = mediaPlayer.getCurrentPosition(); + if(retVal <= 0 && media != null && media.getPosition() > 0) { + retVal = media.getPosition(); + } } else if (media != null && media.getPosition() > 0) { retVal = media.getPosition(); } -- cgit v1.2.3 From 057900bc1b69c4fe24ac244a5c5ccb60d336a0a5 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 29 Sep 2015 17:29:26 -0400 Subject: getting preferences setup for different cleanup method --- .../antennapod/core/preferences/UserPreferences.java | 3 +++ core/src/main/res/values/arrays.xml | 19 +++++++++++++++++++ core/src/main/res/values/strings.xml | 8 ++++++++ 3 files changed, 30 insertions(+) (limited to 'core/src/main') 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 c0e53842f..7349423c3 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 @@ -67,6 +67,7 @@ public class UserPreferences { // Network public static final String PREF_UPDATE_INTERVAL = "prefAutoUpdateIntervall"; public static final String PREF_MOBILE_UPDATE = "prefMobileUpdate"; + public static final String PREF_EPISODE_CLEANUP = "prefEpisodeCleanup"; public static final String PREF_PARALLEL_DOWNLOADS = "prefParallelDownloads"; public static final String PREF_EPISODE_CACHE_SIZE = "prefEpisodeCacheSize"; public static final String PREF_ENABLE_AUTODL = "prefEnableAutoDl"; @@ -217,6 +218,8 @@ public class UserPreferences { return prefs.getBoolean(PREF_FOLLOW_QUEUE, true); } + public static int getEpisodeCleanupDays() { return Integer.valueOf(prefs.getString(PREF_EPISODE_CLEANUP, "3")); } + public static boolean shouldSkipRemoveFromQueue() { return prefs.getBoolean(PREF_SKIP_REMOVES, false); } public static boolean isAutoDelete() { diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 20eb79f84..aefcac2e8 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -44,6 +44,7 @@ 100 @string/pref_episode_cache_unlimited + 5 10 @@ -53,6 +54,24 @@ -1 + + @string/episode_cleanup_immediately + 1 + 3 + 5 + 7 + @string/episode_cleanup_never + + + + 0 + 1 + 3 + 5 + 7 + -1 + + 0.5 0.6 diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index ae1381de3..4feef0ecd 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -86,6 +86,8 @@ Always Never Send... + Never + when not in queue Feed URL @@ -266,6 +268,8 @@ Queue Services Flattr + Episode Cleanup + Episodes that aren\'t in the queue and aren\'t favorites should be eligible for removal if space is needed Pause playback when the headphones are disconnected Resume playback when the headphones are reconnected Jump to next queue item when playback completes @@ -417,6 +421,10 @@ %d hours + + 1 day + %d days + CATEGORIES TOP PODCASTS -- cgit v1.2.3 From f5801c218119d5f4f9015e805f9462d02d4b3c16 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 29 Sep 2015 20:29:53 -0400 Subject: Implement cleanup that only removes epiosdes older than a certain number of days Also set the stage for the queue cleanup algorithm. --- .../core/preferences/UserPreferences.java | 19 ++++++-- .../core/storage/APCleanupAlgorithm.java | 50 ++++++++++------------ .../core/storage/APDownloadAlgorithm.java | 22 ++++++++-- .../core/storage/APNullCleanupAlgorithm.java | 19 ++++++++ .../core/storage/APQueueCleanupAlgorithm.java | 19 ++++++++ .../de/danoeh/antennapod/core/storage/DBTasks.java | 2 +- .../core/storage/EpisodeCleanupAlgorithm.java | 12 +----- core/src/main/res/values/arrays.xml | 6 ++- core/src/main/res/values/strings.xml | 11 ++--- 9 files changed, 108 insertions(+), 52 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/storage/APNullCleanupAlgorithm.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java (limited to 'core/src/main') 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 7349423c3..1474180e2 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 @@ -27,6 +27,10 @@ import java.util.concurrent.TimeUnit; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.receiver.FeedUpdateReceiver; +import de.danoeh.antennapod.core.storage.APCleanupAlgorithm; +import de.danoeh.antennapod.core.storage.APNullCleanupAlgorithm; +import de.danoeh.antennapod.core.storage.APQueueCleanupAlgorithm; +import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithm; /** * Provides access to preferences set by the user in the settings screen. A @@ -218,8 +222,6 @@ public class UserPreferences { return prefs.getBoolean(PREF_FOLLOW_QUEUE, true); } - public static int getEpisodeCleanupDays() { return Integer.valueOf(prefs.getString(PREF_EPISODE_CLEANUP, "3")); } - public static boolean shouldSkipRemoveFromQueue() { return prefs.getBoolean(PREF_SKIP_REMOVES, false); } public static boolean isAutoDelete() { @@ -489,6 +491,18 @@ public class UserPreferences { .apply(); } + + public static EpisodeCleanupAlgorithm getEpisodeCleanupAlgorithm() { + int cleanupValue = prefs.getInt(PREF_EPISODE_CLEANUP, -1); + if (cleanupValue == -1) { + return new APQueueCleanupAlgorithm(); + } else if (cleanupValue == -2) { + return new APNullCleanupAlgorithm(); + } else { + return new APCleanupAlgorithm(cleanupValue); + } + } + /** * Return the folder where the app stores all of its data. This method will * return the standard data folder if none has been set by the user. @@ -648,5 +662,4 @@ public class UserPreferences { public static int readEpisodeCacheSize(String valueFromPrefs) { return readEpisodeCacheSizeInternal(valueFromPrefs); } - } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java index 70b3aa90a..e28c902dd 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java @@ -4,12 +4,14 @@ import android.content.Context; import android.util.Log; import java.util.ArrayList; +import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.concurrent.ExecutionException; import de.danoeh.antennapod.core.feed.FeedItem; +import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.util.LongList; @@ -19,19 +21,34 @@ import de.danoeh.antennapod.core.util.LongList; public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm { private static final String TAG = "APCleanupAlgorithm"; + /** the number of days after playback to wait before an item is eligible to be cleaned up */ + private final int numberOfDaysAfterPlayback; + + public APCleanupAlgorithm(int numberOfDaysAfterPlayback) { + this.numberOfDaysAfterPlayback = numberOfDaysAfterPlayback; + } @Override - public int performCleanup(Context context, Integer episodeNumber) { + public int performCleanup(Context context, Integer numberOfEpisodesToDelete) { List candidates = new ArrayList<>(); List downloadedItems = DBReader.getDownloadedItems(); LongList queue = DBReader.getQueueIDList(); List delete; + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.DAY_OF_MONTH, -1 * numberOfDaysAfterPlayback); + Date mostRecentDateForDeletion = cal.getTime(); for (FeedItem item : downloadedItems) { if (item.hasMedia() && item.getMedia().isDownloaded() && !queue.contains(item.getId()) && item.isPlayed()) { - candidates.add(item); + FeedMedia media = item.getMedia(); + // make sure this candidate was played at least the proper amount of days prior + // to now + if (media != null + && media.getPlaybackCompletionDate() != null + && media.getPlaybackCompletionDate().before(mostRecentDateForDeletion)) { + candidates.add(item); + } } - } Collections.sort(candidates, (lhs, rhs) -> { @@ -47,8 +64,8 @@ public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm { return l.compareTo(r); }); - if (candidates.size() > episodeNumber) { - delete = candidates.subList(0, episodeNumber); + if (candidates.size() > numberOfEpisodesToDelete) { + delete = candidates.subList(0, numberOfEpisodesToDelete); } else { delete = candidates; } @@ -66,34 +83,13 @@ public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm { Log.i(TAG, String.format( "Auto-delete deleted %d episodes (%d requested)", counter, - episodeNumber)); + numberOfEpisodesToDelete)); return counter; } @Override public Integer getDefaultCleanupParameter() { - return getPerformAutoCleanupArgs(0); - } - - @Override - public Integer getPerformCleanupParameter(List items) { - return getPerformAutoCleanupArgs(items.size()); - } - - static int getPerformAutoCleanupArgs(final int episodeNumber) { - if (episodeNumber >= 0 - && UserPreferences.getEpisodeCacheSize() != UserPreferences - .getEpisodeCacheSizeUnlimited()) { - int downloadedEpisodes = DBReader - .getNumberOfDownloadedEpisodes(); - if (downloadedEpisodes + episodeNumber >= UserPreferences - .getEpisodeCacheSize()) { - - return downloadedEpisodes + episodeNumber - - UserPreferences.getEpisodeCacheSize(); - } - } return 0; } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java index f2c56ee79..748f842b9 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java @@ -19,8 +19,6 @@ import de.danoeh.antennapod.core.util.PowerUtils; public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm { private static final String TAG = "APDownloadAlgorithm"; - private final APCleanupAlgorithm cleanupAlgorithm = new APCleanupAlgorithm(); - /** * Looks for undownloaded episodes in the queue or list of new items and request a download if * 1. Network is available @@ -72,8 +70,8 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm { int autoDownloadableEpisodes = candidates.size(); int downloadedEpisodes = DBReader.getNumberOfDownloadedEpisodes(); - int deletedEpisodes = cleanupAlgorithm.performCleanup(context, - APCleanupAlgorithm.getPerformAutoCleanupArgs(autoDownloadableEpisodes)); + int deletedEpisodes = UserPreferences.getEpisodeCleanupAlgorithm().performCleanup(context, + getPerformAutoCleanupArgs(autoDownloadableEpisodes)); boolean cacheIsUnlimited = UserPreferences.getEpisodeCacheSize() == UserPreferences .getEpisodeCacheSizeUnlimited(); int episodeCacheSize = UserPreferences.getEpisodeCacheSize(); @@ -102,4 +100,20 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm { }; } + private int getPerformAutoCleanupArgs(final int numberOfEpisodesToDownload) { + if (numberOfEpisodesToDownload >= 0 + && UserPreferences.getEpisodeCacheSize() != UserPreferences + .getEpisodeCacheSizeUnlimited()) { + int downloadedEpisodes = DBReader + .getNumberOfDownloadedEpisodes(); + if (downloadedEpisodes + numberOfEpisodesToDownload >= UserPreferences + .getEpisodeCacheSize()) { + + return downloadedEpisodes + numberOfEpisodesToDownload + - UserPreferences.getEpisodeCacheSize(); + } + } + return 0; + } + } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APNullCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APNullCleanupAlgorithm.java new file mode 100644 index 000000000..27396de4b --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APNullCleanupAlgorithm.java @@ -0,0 +1,19 @@ +package de.danoeh.antennapod.core.storage; + +import android.content.Context; + +/** + * A cleanup algorithm that never removes anything + */ +public class APNullCleanupAlgorithm implements EpisodeCleanupAlgorithm { + @Override + public int performCleanup(Context context, Integer parameter) { + // never clean anything up + return 0; + } + + @Override + public Integer getDefaultCleanupParameter() { + return 0; + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java new file mode 100644 index 000000000..c45f30e62 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java @@ -0,0 +1,19 @@ +package de.danoeh.antennapod.core.storage; + +import android.content.Context; + +/** + * A cleanup algorithm that removes any item that isn't in the queue and isn't a favorite + * but only if space is needed. + */ +public class APQueueCleanupAlgorithm implements EpisodeCleanupAlgorithm { + @Override + public int performCleanup(Context context, Integer parameter) { + return 0; + } + + @Override + public Integer getDefaultCleanupParameter() { + return 0; + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index 3f9cece77..2fc7e52bd 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -334,7 +334,7 @@ public final class DBTasks { ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm() .performCleanup(context, ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm() - .getPerformCleanupParameter(Arrays.asList(items))); + .getPerformCleanupParameter(items.length)); } }.start(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/EpisodeCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/EpisodeCleanupAlgorithm.java index 91f221f39..484263f97 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/EpisodeCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/EpisodeCleanupAlgorithm.java @@ -17,20 +17,12 @@ public interface EpisodeCleanupAlgorithm { * or getPerformCleanupParameter. * @return The number of episodes that were deleted. */ - public int performCleanup(Context context, T parameter); + int performCleanup(Context context, T parameter); /** * Returns a parameter for performCleanup. The implementation of this interface should decide how much * space to free to satisfy the episode cache conditions. If the conditions are already satisfied, this * method should not have any effects. */ - public T getDefaultCleanupParameter(); - - /** - * Returns a parameter for performCleanup. - * - * @param items A list of FeedItems that are about to be downloaded. The implementation of this interface - * should decide how much space to free to satisfy the episode cache conditions. - */ - public T getPerformCleanupParameter(List items); + T getDefaultCleanupParameter(); } diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index aefcac2e8..34339783e 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -55,7 +55,8 @@ - @string/episode_cleanup_immediately + @string/episode_cleanup_queue_removal + 0 1 3 5 @@ -64,12 +65,13 @@ + -1 0 1 3 5 7 - -1 + -2 diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 4feef0ecd..f3a17a8cc 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -87,7 +87,12 @@ Never Send... Never - when not in queue + When not in queue + After listening + + 1 day after listening + %d days after listening + Feed URL @@ -421,10 +426,6 @@ %d hours - - 1 day - %d days - CATEGORIES TOP PODCASTS -- cgit v1.2.3 From 2339fb99e98bb7d5a078aea47095c94df1f88f10 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 29 Sep 2015 20:50:31 -0400 Subject: basic implementation of queue remove. some compile bugs still --- .../core/storage/APDownloadAlgorithm.java | 17 ------ .../core/storage/APNullCleanupAlgorithm.java | 5 ++ .../core/storage/APQueueCleanupAlgorithm.java | 64 +++++++++++++++++++++- 3 files changed, 67 insertions(+), 19 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java index 748f842b9..efc742be2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java @@ -99,21 +99,4 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm { } }; } - - private int getPerformAutoCleanupArgs(final int numberOfEpisodesToDownload) { - if (numberOfEpisodesToDownload >= 0 - && UserPreferences.getEpisodeCacheSize() != UserPreferences - .getEpisodeCacheSizeUnlimited()) { - int downloadedEpisodes = DBReader - .getNumberOfDownloadedEpisodes(); - if (downloadedEpisodes + numberOfEpisodesToDownload >= UserPreferences - .getEpisodeCacheSize()) { - - return downloadedEpisodes + numberOfEpisodesToDownload - - UserPreferences.getEpisodeCacheSize(); - } - } - return 0; - } - } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APNullCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APNullCleanupAlgorithm.java index 27396de4b..b17f9fdee 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APNullCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APNullCleanupAlgorithm.java @@ -1,14 +1,19 @@ package de.danoeh.antennapod.core.storage; import android.content.Context; +import android.util.Log; /** * A cleanup algorithm that never removes anything */ public class APNullCleanupAlgorithm implements EpisodeCleanupAlgorithm { + + private static final String TAG = "APNullCleanupAlgorithm"; + @Override public int performCleanup(Context context, Integer parameter) { // never clean anything up + Log.i(TAG, "performCleanup: Not removing anything"); return 0; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java index c45f30e62..18dd46c7a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java @@ -1,15 +1,75 @@ package de.danoeh.antennapod.core.storage; import android.content.Context; +import android.util.Log; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.concurrent.ExecutionException; + +import de.danoeh.antennapod.core.feed.FeedItem; +import de.danoeh.antennapod.core.feed.FeedMedia; +import de.danoeh.antennapod.core.util.LongList; /** * A cleanup algorithm that removes any item that isn't in the queue and isn't a favorite * but only if space is needed. */ public class APQueueCleanupAlgorithm implements EpisodeCleanupAlgorithm { + + private static final String TAG = "APQueueCleanupAlgorithm"; + @Override - public int performCleanup(Context context, Integer parameter) { - return 0; + public int performCleanup(Context context, Integer numberOfEpisodesToDelete) { + List candidates = new ArrayList<>(); + List downloadedItems = DBReader.getDownloadedItems(); + LongList queue = DBReader.getQueueIDList(); + List delete; + for (FeedItem item : downloadedItems) { + if (!queue.contains(item.getId())) { + candidates.add(item); + } + } + + // in the absence of better data, we'll sort by item publication date + Collections.sort(candidates, (lhs, rhs) -> { + Date l = lhs.getPubDate(); + Date r = rhs.getPubDate(); + + if (l == null) { + l = new Date(); + } + if (r == null) { + r = new Date(); + } + return l.compareTo(r); + }); + + if (candidates.size() > numberOfEpisodesToDelete) { + delete = candidates.subList(0, numberOfEpisodesToDelete); + } else { + delete = candidates; + } + + for (FeedItem item : delete) { + try { + DBWriter.deleteFeedMediaOfItem(context, item.getMedia().getId()).get(); + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + } + + int counter = delete.size(); + + + Log.i(TAG, String.format( + "Auto-delete deleted %d episodes (%d requested)", counter, + numberOfEpisodesToDelete)); + + return counter; } @Override -- cgit v1.2.3 From 60e341cf787eb7fef9c8cf4ce0347117e34771ee Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Wed, 30 Sep 2015 06:33:35 -0400 Subject: resolved compile time issues. refactored some code --- .../core/preferences/UserPreferences.java | 2 +- .../core/storage/APCleanupAlgorithm.java | 6 +-- .../core/storage/APDownloadAlgorithm.java | 4 +- .../core/storage/APNullCleanupAlgorithm.java | 6 +-- .../core/storage/APQueueCleanupAlgorithm.java | 6 +-- .../de/danoeh/antennapod/core/storage/DBTasks.java | 7 +-- .../core/storage/EpisodeCleanupAlgorithm.java | 51 ++++++++++++++++++---- 7 files changed, 56 insertions(+), 26 deletions(-) (limited to 'core/src/main') 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 1474180e2..1d5bd5031 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 @@ -492,7 +492,7 @@ public class UserPreferences { } - public static EpisodeCleanupAlgorithm getEpisodeCleanupAlgorithm() { + public static EpisodeCleanupAlgorithm getEpisodeCleanupAlgorithm() { int cleanupValue = prefs.getInt(PREF_EPISODE_CLEANUP, -1); if (cleanupValue == -1) { return new APQueueCleanupAlgorithm(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java index e28c902dd..ef834921a 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java @@ -18,7 +18,7 @@ import de.danoeh.antennapod.core.util.LongList; /** * Implementation of the EpisodeCleanupAlgorithm interface used by AntennaPod. */ -public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm { +public class APCleanupAlgorithm extends EpisodeCleanupAlgorithm { private static final String TAG = "APCleanupAlgorithm"; /** the number of days after playback to wait before an item is eligible to be cleaned up */ @@ -29,7 +29,7 @@ public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm { } @Override - public int performCleanup(Context context, Integer numberOfEpisodesToDelete) { + public int performCleanup(Context context, int numberOfEpisodesToDelete) { List candidates = new ArrayList<>(); List downloadedItems = DBReader.getDownloadedItems(); LongList queue = DBReader.getQueueIDList(); @@ -89,7 +89,7 @@ public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm { } @Override - public Integer getDefaultCleanupParameter() { + public int getDefaultCleanupParameter() { return 0; } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java index efc742be2..9e21a55f2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APDownloadAlgorithm.java @@ -70,8 +70,8 @@ public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm { int autoDownloadableEpisodes = candidates.size(); int downloadedEpisodes = DBReader.getNumberOfDownloadedEpisodes(); - int deletedEpisodes = UserPreferences.getEpisodeCleanupAlgorithm().performCleanup(context, - getPerformAutoCleanupArgs(autoDownloadableEpisodes)); + int deletedEpisodes = UserPreferences.getEpisodeCleanupAlgorithm() + .makeRoomForEpisodes(context, autoDownloadableEpisodes); boolean cacheIsUnlimited = UserPreferences.getEpisodeCacheSize() == UserPreferences .getEpisodeCacheSizeUnlimited(); int episodeCacheSize = UserPreferences.getEpisodeCacheSize(); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APNullCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APNullCleanupAlgorithm.java index b17f9fdee..132b61853 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APNullCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APNullCleanupAlgorithm.java @@ -6,19 +6,19 @@ import android.util.Log; /** * A cleanup algorithm that never removes anything */ -public class APNullCleanupAlgorithm implements EpisodeCleanupAlgorithm { +public class APNullCleanupAlgorithm extends EpisodeCleanupAlgorithm { private static final String TAG = "APNullCleanupAlgorithm"; @Override - public int performCleanup(Context context, Integer parameter) { + public int performCleanup(Context context, int parameter) { // never clean anything up Log.i(TAG, "performCleanup: Not removing anything"); return 0; } @Override - public Integer getDefaultCleanupParameter() { + public int getDefaultCleanupParameter() { return 0; } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java index 18dd46c7a..ebf8ca4cf 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java @@ -18,12 +18,12 @@ import de.danoeh.antennapod.core.util.LongList; * A cleanup algorithm that removes any item that isn't in the queue and isn't a favorite * but only if space is needed. */ -public class APQueueCleanupAlgorithm implements EpisodeCleanupAlgorithm { +public class APQueueCleanupAlgorithm extends EpisodeCleanupAlgorithm { private static final String TAG = "APQueueCleanupAlgorithm"; @Override - public int performCleanup(Context context, Integer numberOfEpisodesToDelete) { + public int performCleanup(Context context, int numberOfEpisodesToDelete) { List candidates = new ArrayList<>(); List downloadedItems = DBReader.getDownloadedItems(); LongList queue = DBReader.getQueueIDList(); @@ -73,7 +73,7 @@ public class APQueueCleanupAlgorithm implements EpisodeCleanupAlgorithm } @Override - public Integer getDefaultCleanupParameter() { + public int getDefaultCleanupParameter() { return 0; } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index 2fc7e52bd..f54e13471 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -332,9 +332,7 @@ public final class DBTasks { @Override public void run() { ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm() - .performCleanup(context, - ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm() - .getPerformCleanupParameter(items.length)); + .makeRoomForEpisodes(context, items.length); } }.start(); @@ -390,8 +388,7 @@ public final class DBTasks { * @param context Used for accessing the DB. */ public static void performAutoCleanup(final Context context) { - ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm().performCleanup(context, - ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm().getDefaultCleanupParameter()); + ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm().performCleanup(context); } /** diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/EpisodeCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/EpisodeCleanupAlgorithm.java index 484263f97..0f402745c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/EpisodeCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/EpisodeCleanupAlgorithm.java @@ -2,27 +2,60 @@ package de.danoeh.antennapod.core.storage; import android.content.Context; -import java.util.List; +import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.feed.FeedItem; - -public interface EpisodeCleanupAlgorithm { +public abstract class EpisodeCleanupAlgorithm { /** * Deletes downloaded episodes that are no longer needed. What episodes are deleted and how many * of them depends on the implementation. * - * @param context Can be used for accessing the database - * @param parameter An additional parameter. This parameter is either returned by getDefaultCleanupParameter - * or getPerformCleanupParameter. + * @param context Can be used for accessing the database + * @param numToRemove An additional parameter. This parameter is either returned by getDefaultCleanupParameter + * or getPerformCleanupParameter. * @return The number of episodes that were deleted. */ - int performCleanup(Context context, T parameter); + public abstract int performCleanup(Context context, int numToRemove); + + public int performCleanup(Context context) { + return performCleanup(context, getDefaultCleanupParameter()); + } /** * Returns a parameter for performCleanup. The implementation of this interface should decide how much * space to free to satisfy the episode cache conditions. If the conditions are already satisfied, this * method should not have any effects. */ - T getDefaultCleanupParameter(); + public abstract int getDefaultCleanupParameter(); + + /** + * Cleans up just enough episodes to make room for the requested number + * + * @param context Can be used for accessing the database + * @param amountOfRoomNeeded the number of episodes we need space for + * @return The number of epiosdes that were deleted + */ + public int makeRoomForEpisodes(Context context, int amountOfRoomNeeded) { + return performCleanup(context, getNumEpisodesToCleanup(amountOfRoomNeeded)); + } + + /** + * @param amountOfRoomNeeded the number of episodes we want to download + * @return the number of episodes to delete in order to make room + */ + protected int getNumEpisodesToCleanup(final int amountOfRoomNeeded) { + if (amountOfRoomNeeded >= 0 + && UserPreferences.getEpisodeCacheSize() != UserPreferences + .getEpisodeCacheSizeUnlimited()) { + int downloadedEpisodes = DBReader + .getNumberOfDownloadedEpisodes(); + if (downloadedEpisodes + amountOfRoomNeeded >= UserPreferences + .getEpisodeCacheSize()) { + + return downloadedEpisodes + amountOfRoomNeeded + - UserPreferences.getEpisodeCacheSize(); + } + } + return 0; + } } -- cgit v1.2.3 From 40aefe05a60fa8bfbe71c518e838dd12d1b87c49 Mon Sep 17 00:00:00 2001 From: "no.reply" Date: Wed, 30 Sep 2015 21:03:04 -0400 Subject: Make notification text readable (fixes #1233) --- .../core/service/download/DownloadService.java | 80 +++++++++------------- 1 file changed, 31 insertions(+), 49 deletions(-) (limited to 'core/src/main') 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 cb050463e..abde464f2 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 @@ -130,7 +130,6 @@ public class DownloadService extends Service { private NotificationCompat.Builder notificationCompatBuilder; - private Notification.BigTextStyle notificationBuilder; private int NOTIFICATION_ID = 2; private int REPORT_ID = 3; @@ -322,23 +321,16 @@ public class DownloadService extends Service { DBTasks.autodownloadUndownloadedItems(getApplicationContext()); } - @SuppressLint("NewApi") private void setupNotificationBuilders() { Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.stat_notify_sync); - if (android.os.Build.VERSION.SDK_INT >= 16) { - notificationBuilder = new Notification.BigTextStyle( - new Notification.Builder(this).setOngoing(true) - .setContentIntent(ClientConfig.downloadServiceCallbacks.getNotificationContentIntent(this)).setLargeIcon(icon) - .setSmallIcon(R.drawable.stat_notify_sync) - ); - } else { notificationCompatBuilder = new NotificationCompat.Builder(this) - .setOngoing(true).setContentIntent(ClientConfig.downloadServiceCallbacks.getNotificationContentIntent(this)) + .setOngoing(true) + .setContentIntent(ClientConfig.downloadServiceCallbacks.getNotificationContentIntent(this)) .setLargeIcon(icon) .setSmallIcon(R.drawable.stat_notify_sync); - } + Log.d(TAG, "Notification set up"); } @@ -346,58 +338,48 @@ public class DownloadService extends Service { * Updates the contents of the service's notifications. Should be called * before setupNotificationBuilders. */ - @SuppressLint("NewApi") private Notification updateNotifications() { String contentTitle = getString(R.string.download_notification_title); int numDownloads = requester.getNumberOfDownloads(); String downloadsLeft; if (numDownloads > 0) { - downloadsLeft = requester.getNumberOfDownloads() - + getString(R.string.downloads_left); + downloadsLeft = requester.getNumberOfDownloads() + getString(R.string.downloads_left); } else { downloadsLeft = getString(R.string.downloads_processing); } - if (android.os.Build.VERSION.SDK_INT >= 16) { - - if (notificationBuilder != null) { - - StringBuilder bigText = new StringBuilder(""); - for (int i = 0; i < downloads.size(); i++) { - Downloader downloader = downloads.get(i); - final DownloadRequest request = downloader - .getDownloadRequest(); - if (request.getFeedfileType() == Feed.FEEDFILETYPE_FEED) { - if (request.getTitle() != null) { - if (i > 0) { - bigText.append("\n"); - } - bigText.append("\u2022 " + request.getTitle()); + if (notificationCompatBuilder != null) { + + StringBuilder bigText = new StringBuilder(""); + for (int i = 0; i < downloads.size(); i++) { + Downloader downloader = downloads.get(i); + final DownloadRequest request = downloader + .getDownloadRequest(); + if (request.getFeedfileType() == Feed.FEEDFILETYPE_FEED) { + if (request.getTitle() != null) { + if (i > 0) { + bigText.append("\n"); } - } else if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { - if (request.getTitle() != null) { - if (i > 0) { - bigText.append("\n"); - } - bigText.append("\u2022 " + request.getTitle() - + " (" + request.getProgressPercent() - + "%)"); + bigText.append("\u2022 " + request.getTitle()); + } + } else if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { + if (request.getTitle() != null) { + if (i > 0) { + bigText.append("\n"); } + bigText.append("\u2022 " + request.getTitle() + + " (" + request.getProgressPercent() + + "%)"); } - } - notificationBuilder.setSummaryText(downloadsLeft); - notificationBuilder.setBigContentTitle(contentTitle); - if (bigText != null) { - notificationBuilder.bigText(bigText.toString()); - } - return notificationBuilder.build(); + } - } else { - if (notificationCompatBuilder != null) { - notificationCompatBuilder.setContentTitle(contentTitle); - notificationCompatBuilder.setContentText(downloadsLeft); - return notificationCompatBuilder.build(); + notificationCompatBuilder.setContentTitle(contentTitle); + notificationCompatBuilder.setContentText(downloadsLeft); + if (bigText != null) { + notificationCompatBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(bigText.toString())); } + notificationCompatBuilder.setColor(0xff424242); + return notificationCompatBuilder.build(); } return null; } -- cgit v1.2.3 From 0beeeb435153f1fdb11ffe7f89899b76c10f3f3b Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Fri, 2 Oct 2015 07:56:34 -0400 Subject: resolved bug in how we were choosing the default cleanup parameter --- .../de/danoeh/antennapod/core/preferences/UserPreferences.java | 7 +++++-- .../java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java | 2 +- .../de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) (limited to 'core/src/main') 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 1d5bd5031..f706c83ee 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 @@ -98,6 +98,9 @@ public class UserPreferences { // Experimental public static final String PREF_SONIC = "prefSonic"; public static final String PREF_NORMALIZER = "prefNormalizer"; + public static final int EPISODE_CLEANUP_QUEUE = -1; + public static final int EPISODE_CLEANUP_NULL = -2; + public static final int EPISODE_CLEANUP_DEFAULT = 0; // Constants private static int EPISODE_CACHE_SIZE_UNLIMITED = -1; @@ -494,9 +497,9 @@ public class UserPreferences { public static EpisodeCleanupAlgorithm getEpisodeCleanupAlgorithm() { int cleanupValue = prefs.getInt(PREF_EPISODE_CLEANUP, -1); - if (cleanupValue == -1) { + if (cleanupValue == EPISODE_CLEANUP_QUEUE) { return new APQueueCleanupAlgorithm(); - } else if (cleanupValue == -2) { + } else if (cleanupValue == EPISODE_CLEANUP_NULL) { return new APNullCleanupAlgorithm(); } else { return new APCleanupAlgorithm(cleanupValue); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java index ef834921a..b4fbdaea1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java @@ -90,6 +90,6 @@ public class APCleanupAlgorithm extends EpisodeCleanupAlgorithm { @Override public int getDefaultCleanupParameter() { - return 0; + return getNumEpisodesToCleanup(0); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java index ebf8ca4cf..549b4e02c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java @@ -74,6 +74,6 @@ public class APQueueCleanupAlgorithm extends EpisodeCleanupAlgorithm { @Override public int getDefaultCleanupParameter() { - return 0; + return getNumEpisodesToCleanup(0); } } -- cgit v1.2.3 From c9c38a0f5af87b2e6776bd8e61f3f0530f9fbb6c Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Fri, 2 Oct 2015 09:38:11 -0400 Subject: Implemented tests for the various cleanup algorithms. We also don't delete items that are in Favorites. --- .../antennapod/core/storage/APCleanupAlgorithm.java | 8 +++++--- .../antennapod/core/storage/APQueueCleanupAlgorithm.java | 6 ++++-- .../de/danoeh/antennapod/core/storage/PodDBAdapter.java | 15 +++++++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java index b4fbdaea1..2b6a1ac65 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java @@ -32,14 +32,16 @@ public class APCleanupAlgorithm extends EpisodeCleanupAlgorithm { public int performCleanup(Context context, int numberOfEpisodesToDelete) { List candidates = new ArrayList<>(); List downloadedItems = DBReader.getDownloadedItems(); - LongList queue = DBReader.getQueueIDList(); List delete; Calendar cal = Calendar.getInstance(); cal.add(Calendar.DAY_OF_MONTH, -1 * numberOfDaysAfterPlayback); Date mostRecentDateForDeletion = cal.getTime(); for (FeedItem item : downloadedItems) { - if (item.hasMedia() && item.getMedia().isDownloaded() - && !queue.contains(item.getId()) && item.isPlayed()) { + if (item.hasMedia() + && item.getMedia().isDownloaded() + && !item.isTagged(FeedItem.TAG_QUEUE) + && item.isPlayed() + && !item.isTagged(FeedItem.TAG_FAVORITE)) { FeedMedia media = item.getMedia(); // make sure this candidate was played at least the proper amount of days prior // to now diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java index 549b4e02c..234d6162c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APQueueCleanupAlgorithm.java @@ -26,10 +26,12 @@ public class APQueueCleanupAlgorithm extends EpisodeCleanupAlgorithm { public int performCleanup(Context context, int numberOfEpisodesToDelete) { List candidates = new ArrayList<>(); List downloadedItems = DBReader.getDownloadedItems(); - LongList queue = DBReader.getQueueIDList(); List delete; for (FeedItem item : downloadedItems) { - if (!queue.contains(item.getId())) { + if (item.hasMedia() + && item.getMedia().isDownloaded() + && !item.isTagged(FeedItem.TAG_QUEUE) + && !item.isTagged(FeedItem.TAG_FAVORITE)) { candidates.add(item); } } 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 9e20693a3..d55d4c231 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 @@ -790,6 +790,21 @@ public class PodDBAdapter { db.execSQL(sql); } + public void setFavorites(List favorites) { + ContentValues values = new ContentValues(); + db.beginTransaction(); + db.delete(TABLE_NAME_FAVORITES, null, null); + for (int i = 0; i < favorites.size(); i++) { + FeedItem item = favorites.get(i); + values.put(KEY_ID, i); + values.put(KEY_FEEDITEM, item.getId()); + values.put(KEY_FEED, item.getFeed().getId()); + db.insertWithOnConflict(TABLE_NAME_FAVORITES, null, values, SQLiteDatabase.CONFLICT_REPLACE); + } + db.setTransactionSuccessful(); + db.endTransaction(); + } + /** * Adds the item to favorites */ -- cgit v1.2.3 From af5579a30e5fcbb3f3ef0636a9adbbdae33459cb Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Fri, 2 Oct 2015 10:25:01 -0400 Subject: fixed use of preferences --- .../java/de/danoeh/antennapod/core/preferences/UserPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') 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 f706c83ee..5d9400069 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 @@ -496,7 +496,7 @@ public class UserPreferences { public static EpisodeCleanupAlgorithm getEpisodeCleanupAlgorithm() { - int cleanupValue = prefs.getInt(PREF_EPISODE_CLEANUP, -1); + int cleanupValue = Integer.valueOf(prefs.getString(PREF_EPISODE_CLEANUP, "-1")); if (cleanupValue == EPISODE_CLEANUP_QUEUE) { return new APQueueCleanupAlgorithm(); } else if (cleanupValue == EPISODE_CLEANUP_NULL) { -- cgit v1.2.3 From 6f3d748aa0a8d35f43adb68796428c7ae37fe51e Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Fri, 2 Oct 2015 16:50:08 -0400 Subject: episode cleanup preferences tests --- .../main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java index 2b6a1ac65..0dc54fb6e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/APCleanupAlgorithm.java @@ -94,4 +94,6 @@ public class APCleanupAlgorithm extends EpisodeCleanupAlgorithm { public int getDefaultCleanupParameter() { return getNumEpisodesToCleanup(0); } + + public int getNumberOfDaysAfterPlayback() { return numberOfDaysAfterPlayback; } } -- cgit v1.2.3 From 4ce407c4856c9aec2ea2661fd701dc764b2ed427 Mon Sep 17 00:00:00 2001 From: "no.reply" Date: Fri, 2 Oct 2015 18:25:46 -0400 Subject: Revert "Make notification text readable (fixes #1233)" This reverts commit 40aefe05a60fa8bfbe71c518e838dd12d1b87c49. --- .../core/service/download/DownloadService.java | 80 +++++++++++++--------- 1 file changed, 49 insertions(+), 31 deletions(-) (limited to 'core/src/main') 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 abde464f2..cb050463e 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 @@ -130,6 +130,7 @@ public class DownloadService extends Service { private NotificationCompat.Builder notificationCompatBuilder; + private Notification.BigTextStyle notificationBuilder; private int NOTIFICATION_ID = 2; private int REPORT_ID = 3; @@ -321,16 +322,23 @@ public class DownloadService extends Service { DBTasks.autodownloadUndownloadedItems(getApplicationContext()); } + @SuppressLint("NewApi") private void setupNotificationBuilders() { Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.stat_notify_sync); + if (android.os.Build.VERSION.SDK_INT >= 16) { + notificationBuilder = new Notification.BigTextStyle( + new Notification.Builder(this).setOngoing(true) + .setContentIntent(ClientConfig.downloadServiceCallbacks.getNotificationContentIntent(this)).setLargeIcon(icon) + .setSmallIcon(R.drawable.stat_notify_sync) + ); + } else { notificationCompatBuilder = new NotificationCompat.Builder(this) - .setOngoing(true) - .setContentIntent(ClientConfig.downloadServiceCallbacks.getNotificationContentIntent(this)) + .setOngoing(true).setContentIntent(ClientConfig.downloadServiceCallbacks.getNotificationContentIntent(this)) .setLargeIcon(icon) .setSmallIcon(R.drawable.stat_notify_sync); - + } Log.d(TAG, "Notification set up"); } @@ -338,48 +346,58 @@ public class DownloadService extends Service { * Updates the contents of the service's notifications. Should be called * before setupNotificationBuilders. */ + @SuppressLint("NewApi") private Notification updateNotifications() { String contentTitle = getString(R.string.download_notification_title); int numDownloads = requester.getNumberOfDownloads(); String downloadsLeft; if (numDownloads > 0) { - downloadsLeft = requester.getNumberOfDownloads() + getString(R.string.downloads_left); + downloadsLeft = requester.getNumberOfDownloads() + + getString(R.string.downloads_left); } else { downloadsLeft = getString(R.string.downloads_processing); } - if (notificationCompatBuilder != null) { - - StringBuilder bigText = new StringBuilder(""); - for (int i = 0; i < downloads.size(); i++) { - Downloader downloader = downloads.get(i); - final DownloadRequest request = downloader - .getDownloadRequest(); - if (request.getFeedfileType() == Feed.FEEDFILETYPE_FEED) { - if (request.getTitle() != null) { - if (i > 0) { - bigText.append("\n"); + if (android.os.Build.VERSION.SDK_INT >= 16) { + + if (notificationBuilder != null) { + + StringBuilder bigText = new StringBuilder(""); + for (int i = 0; i < downloads.size(); i++) { + Downloader downloader = downloads.get(i); + final DownloadRequest request = downloader + .getDownloadRequest(); + if (request.getFeedfileType() == Feed.FEEDFILETYPE_FEED) { + if (request.getTitle() != null) { + if (i > 0) { + bigText.append("\n"); + } + bigText.append("\u2022 " + request.getTitle()); } - bigText.append("\u2022 " + request.getTitle()); - } - } else if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { - if (request.getTitle() != null) { - if (i > 0) { - bigText.append("\n"); + } else if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { + if (request.getTitle() != null) { + if (i > 0) { + bigText.append("\n"); + } + bigText.append("\u2022 " + request.getTitle() + + " (" + request.getProgressPercent() + + "%)"); } - bigText.append("\u2022 " + request.getTitle() - + " (" + request.getProgressPercent() - + "%)"); } - } + } + notificationBuilder.setSummaryText(downloadsLeft); + notificationBuilder.setBigContentTitle(contentTitle); + if (bigText != null) { + notificationBuilder.bigText(bigText.toString()); + } + return notificationBuilder.build(); } - notificationCompatBuilder.setContentTitle(contentTitle); - notificationCompatBuilder.setContentText(downloadsLeft); - if (bigText != null) { - notificationCompatBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(bigText.toString())); + } else { + if (notificationCompatBuilder != null) { + notificationCompatBuilder.setContentTitle(contentTitle); + notificationCompatBuilder.setContentText(downloadsLeft); + return notificationCompatBuilder.build(); } - notificationCompatBuilder.setColor(0xff424242); - return notificationCompatBuilder.build(); } return null; } -- cgit v1.2.3 From 03761405700a2dede6ba936b09b2f54c3febe619 Mon Sep 17 00:00:00 2001 From: heckler01 Date: Fri, 2 Oct 2015 18:42:25 -0400 Subject: Revert "Revert "Make notification text readable (fixes #1233)"" This reverts commit 4ce407c4856c9aec2ea2661fd701dc764b2ed427. --- .../core/service/download/DownloadService.java | 80 +++++++++------------- 1 file changed, 31 insertions(+), 49 deletions(-) (limited to 'core/src/main') 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 cb050463e..abde464f2 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 @@ -130,7 +130,6 @@ public class DownloadService extends Service { private NotificationCompat.Builder notificationCompatBuilder; - private Notification.BigTextStyle notificationBuilder; private int NOTIFICATION_ID = 2; private int REPORT_ID = 3; @@ -322,23 +321,16 @@ public class DownloadService extends Service { DBTasks.autodownloadUndownloadedItems(getApplicationContext()); } - @SuppressLint("NewApi") private void setupNotificationBuilders() { Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.stat_notify_sync); - if (android.os.Build.VERSION.SDK_INT >= 16) { - notificationBuilder = new Notification.BigTextStyle( - new Notification.Builder(this).setOngoing(true) - .setContentIntent(ClientConfig.downloadServiceCallbacks.getNotificationContentIntent(this)).setLargeIcon(icon) - .setSmallIcon(R.drawable.stat_notify_sync) - ); - } else { notificationCompatBuilder = new NotificationCompat.Builder(this) - .setOngoing(true).setContentIntent(ClientConfig.downloadServiceCallbacks.getNotificationContentIntent(this)) + .setOngoing(true) + .setContentIntent(ClientConfig.downloadServiceCallbacks.getNotificationContentIntent(this)) .setLargeIcon(icon) .setSmallIcon(R.drawable.stat_notify_sync); - } + Log.d(TAG, "Notification set up"); } @@ -346,58 +338,48 @@ public class DownloadService extends Service { * Updates the contents of the service's notifications. Should be called * before setupNotificationBuilders. */ - @SuppressLint("NewApi") private Notification updateNotifications() { String contentTitle = getString(R.string.download_notification_title); int numDownloads = requester.getNumberOfDownloads(); String downloadsLeft; if (numDownloads > 0) { - downloadsLeft = requester.getNumberOfDownloads() - + getString(R.string.downloads_left); + downloadsLeft = requester.getNumberOfDownloads() + getString(R.string.downloads_left); } else { downloadsLeft = getString(R.string.downloads_processing); } - if (android.os.Build.VERSION.SDK_INT >= 16) { - - if (notificationBuilder != null) { - - StringBuilder bigText = new StringBuilder(""); - for (int i = 0; i < downloads.size(); i++) { - Downloader downloader = downloads.get(i); - final DownloadRequest request = downloader - .getDownloadRequest(); - if (request.getFeedfileType() == Feed.FEEDFILETYPE_FEED) { - if (request.getTitle() != null) { - if (i > 0) { - bigText.append("\n"); - } - bigText.append("\u2022 " + request.getTitle()); + if (notificationCompatBuilder != null) { + + StringBuilder bigText = new StringBuilder(""); + for (int i = 0; i < downloads.size(); i++) { + Downloader downloader = downloads.get(i); + final DownloadRequest request = downloader + .getDownloadRequest(); + if (request.getFeedfileType() == Feed.FEEDFILETYPE_FEED) { + if (request.getTitle() != null) { + if (i > 0) { + bigText.append("\n"); } - } else if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { - if (request.getTitle() != null) { - if (i > 0) { - bigText.append("\n"); - } - bigText.append("\u2022 " + request.getTitle() - + " (" + request.getProgressPercent() - + "%)"); + bigText.append("\u2022 " + request.getTitle()); + } + } else if (request.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { + if (request.getTitle() != null) { + if (i > 0) { + bigText.append("\n"); } + bigText.append("\u2022 " + request.getTitle() + + " (" + request.getProgressPercent() + + "%)"); } - } - notificationBuilder.setSummaryText(downloadsLeft); - notificationBuilder.setBigContentTitle(contentTitle); - if (bigText != null) { - notificationBuilder.bigText(bigText.toString()); - } - return notificationBuilder.build(); + } - } else { - if (notificationCompatBuilder != null) { - notificationCompatBuilder.setContentTitle(contentTitle); - notificationCompatBuilder.setContentText(downloadsLeft); - return notificationCompatBuilder.build(); + notificationCompatBuilder.setContentTitle(contentTitle); + notificationCompatBuilder.setContentText(downloadsLeft); + if (bigText != null) { + notificationCompatBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(bigText.toString())); } + notificationCompatBuilder.setColor(0xff424242); + return notificationCompatBuilder.build(); } return null; } -- cgit v1.2.3 From d6278e21d4b6a00362faf4b79252ba36725634b0 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 3 Oct 2015 17:47:53 +0200 Subject: Additional playback speed steps --- core/src/main/res/values/arrays.xml | 3 +++ 1 file changed, 3 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 20eb79f84..875a1c4a8 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -57,8 +57,11 @@ 0.5 0.6 0.7 + 0.75 0.8 + 0.85 0.9 + 0.95 1.0 1.05 1.10 -- cgit v1.2.3 From 844b54f26d6d9dbe33791957acc7f827a3644e4c Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 3 Oct 2015 18:20:59 +0200 Subject: Drawer: Sort feeds by most recent publication date --- .../antennapod/core/preferences/UserPreferences.java | 1 + .../de/danoeh/antennapod/core/storage/DBReader.java | 17 ++++++++++++++++- core/src/main/res/values/arrays.xml | 2 ++ core/src/main/res/values/strings.xml | 1 + 4 files changed, 20 insertions(+), 1 deletion(-) (limited to 'core/src/main') 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 c0e53842f..59f8e29e1 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 @@ -98,6 +98,7 @@ public class UserPreferences { private static int EPISODE_CACHE_SIZE_UNLIMITED = -1; public static int FEED_ORDER_COUNTER = 0; public static int FEED_ORDER_ALPHABETICAL = 1; + public static int FEED_ORDER_LAST_UPDATE = 2; public static int FEED_COUNTER_SHOW_NEW_UNPLAYED_SUM = 0; public static int FEED_COUNTER_SHOW_NEW = 1; public static int FEED_COUNTER_SHOW_UNPLAYED = 2; diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index d95e4ff02..061ce0634 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -8,6 +8,7 @@ import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.Date; import java.util.List; import de.danoeh.antennapod.core.feed.Chapter; @@ -947,13 +948,27 @@ public final class DBReader { return 1; } }; - } else { + } else if(feedOrder == UserPreferences.FEED_ORDER_ALPHABETICAL) { comparator = (lhs, rhs) -> { if(lhs.getTitle() == null) { return 1; } return lhs.getTitle().compareTo(rhs.getTitle()); }; + } else { + comparator = (lhs, rhs) -> { + if(lhs.getItems() == null || lhs.getItems().size() == 0) { + List items = DBReader.getFeedItemList(lhs); + lhs.setItems(items); + } + if(rhs.getItems() == null || rhs.getItems().size() == 0) { + List items = DBReader.getFeedItemList(rhs); + rhs.setItems(items); + } + Date d1 = lhs.getMostRecentItem().getPubDate(); + Date d2 = rhs.getMostRecentItem().getPubDate(); + return d2.compareTo(d1); + }; } Collections.sort(feeds, comparator); diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 20eb79f84..727b2e35a 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -129,10 +129,12 @@ @string/drawer_feed_order_unplayed_episodes @string/drawer_feed_order_alphabetical + @string/drawer_feed_order_last_update 0 1 + 2 diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index ae1381de3..34f3791c4 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -36,6 +36,7 @@ Drawer Preferences Sort by counter Sort alphabetically + Sort by publication date Number of new and unplayed episodes Number of new episodes Number of unplayed episodes -- cgit v1.2.3 From d3f9b2d49f999d444910afaa49c11459313c67a2 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 3 Oct 2015 21:39:25 +0200 Subject: Indent and add line break to exported OPML file --- .../danoeh/antennapod/core/opml/OpmlSymbols.java | 1 + .../de/danoeh/antennapod/core/opml/OpmlWriter.java | 33 ++++++++++++++++++---- 2 files changed, 28 insertions(+), 6 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlSymbols.java b/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlSymbols.java index 2b831ca2a..c973713cb 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlSymbols.java +++ b/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlSymbols.java @@ -13,6 +13,7 @@ public final class OpmlSymbols { public static final String VERSION = "version"; public static final String HEAD = "head"; public static final String TITLE = "title"; + public static final String DATE_CREATED = "dateCreated"; private OpmlSymbols() { diff --git a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlWriter.java b/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlWriter.java index 641190f62..673c602df 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlWriter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/opml/OpmlWriter.java @@ -2,14 +2,17 @@ package de.danoeh.antennapod.core.opml; import android.util.Log; import android.util.Xml; -import de.danoeh.antennapod.core.BuildConfig; -import de.danoeh.antennapod.core.feed.Feed; + import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.io.Writer; +import java.util.Date; import java.util.List; +import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.util.DateUtils; + /** Writes OPML documents. */ public class OpmlWriter { private static final String TAG = "OpmlWriter"; @@ -27,23 +30,38 @@ public class OpmlWriter { */ public void writeDocument(List feeds, Writer writer) throws IllegalArgumentException, IllegalStateException, IOException { - if (BuildConfig.DEBUG) - Log.d(TAG, "Starting to write document"); + Log.d(TAG, "Starting to write document"); XmlSerializer xs = Xml.newSerializer(); xs.setOutput(writer); xs.startDocument(ENCODING, false); + xs.text("\n"); xs.startTag(null, OpmlSymbols.OPML); xs.attribute(null, OpmlSymbols.VERSION, OPML_VERSION); + xs.text("\n"); + xs.text(" "); xs.startTag(null, OpmlSymbols.HEAD); + xs.text("\n"); + xs.text(" "); xs.startTag(null, OpmlSymbols.TITLE); xs.text(OPML_TITLE); xs.endTag(null, OpmlSymbols.TITLE); + xs.text("\n"); + xs.text(" "); + xs.startTag(null, OpmlSymbols.DATE_CREATED); + xs.text(DateUtils.formatRFC822Date(new Date())); + xs.endTag(null, OpmlSymbols.DATE_CREATED); + xs.text("\n"); + xs.text(" "); xs.endTag(null, OpmlSymbols.HEAD); + xs.text("\n"); + xs.text(" "); xs.startTag(null, OpmlSymbols.BODY); + xs.text("\n"); for (Feed feed : feeds) { + xs.text(" "); xs.startTag(null, OpmlSymbols.OUTLINE); xs.attribute(null, OpmlSymbols.TEXT, feed.getTitle()); xs.attribute(null, OpmlSymbols.TITLE, feed.getTitle()); @@ -55,11 +73,14 @@ public class OpmlWriter { xs.attribute(null, OpmlSymbols.HTMLURL, feed.getLink()); } xs.endTag(null, OpmlSymbols.OUTLINE); + xs.text("\n"); } + xs.text(" "); xs.endTag(null, OpmlSymbols.BODY); + xs.text("\n"); xs.endTag(null, OpmlSymbols.OPML); + xs.text("\n"); xs.endDocument(); - if (BuildConfig.DEBUG) - Log.d(TAG, "Finished writing document"); + Log.d(TAG, "Finished writing document"); } } -- cgit v1.2.3 From 91cc0b2527573bc653e8d15b6d4b8f16ae31937f Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 4 Oct 2015 10:28:32 +0200 Subject: Take feeds with no items into account --- .../java/de/danoeh/antennapod/core/storage/DBReader.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 061ce0634..7a8609b04 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -965,9 +965,15 @@ public final class DBReader { List items = DBReader.getFeedItemList(rhs); rhs.setItems(items); } - Date d1 = lhs.getMostRecentItem().getPubDate(); - Date d2 = rhs.getMostRecentItem().getPubDate(); - return d2.compareTo(d1); + if(lhs.getMostRecentItem() == null) { + return 1; + } else if(rhs.getMostRecentItem() == null) { + return -1; + } else { + Date d1 = lhs.getMostRecentItem().getPubDate(); + Date d2 = rhs.getMostRecentItem().getPubDate(); + return d2.compareTo(d1); + } }; } -- cgit v1.2.3 From db633ce305b8fe850514757cb93922e6afce1982 Mon Sep 17 00:00:00 2001 From: heckler01 Date: Sun, 4 Oct 2015 13:37:05 -0400 Subject: Removed notificationCompatBuilder.setColor as it's not necessary and shouldn't have been committed. --- .../java/de/danoeh/antennapod/core/service/download/DownloadService.java | 1 - 1 file changed, 1 deletion(-) (limited to 'core/src/main') 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 abde464f2..0698107a7 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 @@ -378,7 +378,6 @@ public class DownloadService extends Service { if (bigText != null) { notificationCompatBuilder.setStyle(new NotificationCompat.BigTextStyle().bigText(bigText.toString())); } - notificationCompatBuilder.setColor(0xff424242); return notificationCompatBuilder.build(); } return null; -- cgit v1.2.3 From 23f134bb398f5730167dca9cd6a274d8e08019b5 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Thu, 8 Oct 2015 02:53:34 -0400 Subject: Change language related to skipping episodes. Also now keep the episode media if we're going to keep it in the queue. --- .../de/danoeh/antennapod/core/preferences/UserPreferences.java | 4 ++-- .../danoeh/antennapod/core/service/playback/PlaybackService.java | 8 +++++--- core/src/main/res/values/strings.xml | 4 ++-- 3 files changed, 9 insertions(+), 7 deletions(-) (limited to 'core/src/main') 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 4561c9bad..006c48b26 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 @@ -61,7 +61,7 @@ public class UserPreferences { public static final String PREF_PAUSE_ON_HEADSET_DISCONNECT = "prefPauseOnHeadsetDisconnect"; public static final String PREF_UNPAUSE_ON_HEADSET_RECONNECT = "prefUnpauseOnHeadsetReconnect"; public static final String PREF_FOLLOW_QUEUE = "prefFollowQueue"; - public static final String PREF_SKIP_REMOVES = "prefSkipRemovesFromQueue"; + public static final String PREF_SKIP_KEEPS_EPISODE = "prefSkipKeepsEpisode"; public static final String PREF_AUTO_DELETE = "prefAutoDelete"; public static final String PREF_SMART_MARK_AS_PLAYED_SECS = "prefSmartMarkAsPlayedSecs"; public static final String PREF_PLAYBACK_SPEED_ARRAY = "prefPlaybackSpeedArray"; @@ -226,7 +226,7 @@ public class UserPreferences { return prefs.getBoolean(PREF_FOLLOW_QUEUE, true); } - public static boolean shouldSkipRemoveFromQueue() { return prefs.getBoolean(PREF_SKIP_REMOVES, false); } + public static boolean shouldSkipKeepEpisode() { return prefs.getBoolean(PREF_SKIP_KEEPS_EPISODE, true); } public static boolean isAutoDelete() { return prefs.getBoolean(PREF_AUTO_DELETE, false); 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 a040ee157..cdd63ef62 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 @@ -20,7 +20,6 @@ import android.os.Build; import android.os.IBinder; import android.preference.PreferenceManager; import android.support.v4.app.NotificationCompat; -import android.support.v4.media.session.MediaSessionCompat; import android.util.Log; import android.util.Pair; import android.view.KeyEvent; @@ -577,7 +576,10 @@ public class PlaybackService extends Service { e.printStackTrace(); // isInQueue remains false } - if (isInQueue && (!wasSkipped || UserPreferences.shouldSkipRemoveFromQueue())) { + + boolean shouldKeep = wasSkipped && UserPreferences.shouldSkipKeepEpisode(); + + if (isInQueue && !shouldKeep) { DBWriter.removeQueueItem(PlaybackService.this, item, true); } DBWriter.addItemToPlaybackHistory(media); @@ -588,7 +590,7 @@ public class PlaybackService extends Service { } // Delete episode if enabled - if(item.getFeed().getPreferences().getCurrentAutoDelete()) { + if(item.getFeed().getPreferences().getCurrentAutoDelete() && !shouldKeep ) { DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId()); Log.d(TAG, "Episode Deleted"); } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 168477463..d93e4dbc8 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -283,8 +283,8 @@ Auto Delete Mark episodes as played even if less than a certain amount of seconds of playing time is still left Smart mark as played - Remove episodes from the queue when they are skipped - Skip Removes Episode + Keep episodes when they are skipped + Keep Skipped Episodes Playback Network Update Interval or Time of Day -- cgit v1.2.3 From 184e6eb836a22ed5ae8a1d6c82150a0489fed208 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Thu, 8 Oct 2015 03:38:13 -0400 Subject: listening -> finishing --- core/src/main/res/values/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 168477463..937a4080c 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -89,10 +89,10 @@ Send... Never When not in queue - After listening + After finishing - 1 day after listening - %d days after listening + 1 day after finishing + %d days after finishing -- cgit v1.2.3 From f7dabd93351a229d16fba267138cb5cbc508fa57 Mon Sep 17 00:00:00 2001 From: Stefan Mitrik Date: Thu, 15 Oct 2015 00:52:55 +0200 Subject: Rewind after pause feature The playback is rewinded X seconds after the pause and resume. The rewind duration depends on time that elapsed between the pause and resume. --- .../de/danoeh/antennapod/core/feed/FeedMedia.java | 31 ++++++++--- .../core/service/playback/PlaybackService.java | 7 +-- .../playback/PlaybackServiceMediaPlayer.java | 11 ++-- .../danoeh/antennapod/core/storage/DBWriter.java | 2 +- .../antennapod/core/storage/PodDBAdapter.java | 13 +++-- .../core/util/RewindAfterPauseUtils.java | 47 +++++++++++++++++ .../core/util/playback/ExternalMedia.java | 29 ++++++++-- .../antennapod/core/util/playback/Playable.java | 61 ++++++++++++++++------ 8 files changed, 164 insertions(+), 37 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java index 7397dd935..5a345b9d6 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedMedia.java @@ -40,6 +40,7 @@ public class FeedMedia extends FeedFile implements Playable { private int duration; private int position; // Current position in file + private long lastPlayedTime; // Last time this media was played (in ms) private int played_duration; // How many ms of this file have been played (for autoflattring) private long size; // File size in Byte private String mime_type; @@ -62,7 +63,8 @@ public class FeedMedia extends FeedFile implements Playable { public FeedMedia(long id, FeedItem item, int duration, int position, long size, String mime_type, String file_url, String download_url, - boolean downloaded, Date playbackCompletionDate, int played_duration) { + boolean downloaded, Date playbackCompletionDate, int played_duration, + long lastPlayedTime) { super(file_url, download_url, downloaded); this.id = id; this.item = item; @@ -73,14 +75,15 @@ public class FeedMedia extends FeedFile implements Playable { this.mime_type = mime_type; this.playbackCompletionDate = playbackCompletionDate == null ? null : (Date) playbackCompletionDate.clone(); + this.lastPlayedTime = lastPlayedTime; } public FeedMedia(long id, FeedItem item, int duration, int position, long size, String mime_type, String file_url, String download_url, boolean downloaded, Date playbackCompletionDate, int played_duration, - Boolean hasEmbeddedPicture) { + Boolean hasEmbeddedPicture, long lastPlayedTime) { this(id, item, duration, position, size, mime_type, file_url, download_url, downloaded, - playbackCompletionDate, played_duration); + playbackCompletionDate, played_duration, lastPlayedTime); this.hasEmbeddedPicture = hasEmbeddedPicture; } @@ -95,6 +98,7 @@ public class FeedMedia extends FeedFile implements Playable { int indexDownloadUrl = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOAD_URL); int indexDownloaded = cursor.getColumnIndex(PodDBAdapter.KEY_DOWNLOADED); int indexPlayedDuration = cursor.getColumnIndex(PodDBAdapter.KEY_PLAYED_DURATION); + int indexLastPlayedTime = cursor.getColumnIndex(PodDBAdapter.KEY_LAST_PLAYED_TIME); long mediaId = cursor.getLong(indexId); Date playbackCompletionDate = null; @@ -128,7 +132,8 @@ public class FeedMedia extends FeedFile implements Playable { cursor.getInt(indexDownloaded) > 0, playbackCompletionDate, cursor.getInt(indexPlayedDuration), - hasEmbeddedPicture + hasEmbeddedPicture, + cursor.getLong(indexLastPlayedTime) ); } @@ -231,6 +236,11 @@ public class FeedMedia extends FeedFile implements Playable { this.duration = duration; } + @Override + public void setLastPlayedTime(long lastPlayedTime) { + this.lastPlayedTime = lastPlayedTime; + } + public int getPlayedDuration() { return played_duration; } @@ -243,6 +253,11 @@ public class FeedMedia extends FeedFile implements Playable { return position; } + @Override + public long getLastPlayedTime() { + return lastPlayedTime; + } + public void setPosition(int position) { this.position = position; if(position > 0 && item.isNew()) { @@ -336,6 +351,7 @@ public class FeedMedia extends FeedFile implements Playable { dest.writeByte((byte) ((downloaded) ? 1 : 0)); dest.writeLong((playbackCompletionDate != null) ? playbackCompletionDate.getTime() : 0); dest.writeInt(played_duration); + dest.writeLong(lastPlayedTime); } @Override @@ -438,12 +454,13 @@ public class FeedMedia extends FeedFile implements Playable { } @Override - public void saveCurrentPosition(SharedPreferences pref, int newPosition) { - DBWriter.setFeedMediaPlaybackInformation(this); + public void saveCurrentPosition(SharedPreferences pref, int newPosition, long timeStamp) { if(item.isNew()) { DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId()); } setPosition(newPosition); + setLastPlayedTime(timeStamp); + DBWriter.setFeedMediaPlaybackInformation(this); } @Override @@ -488,7 +505,7 @@ public class FeedMedia extends FeedFile implements Playable { final long id = in.readLong(); final long itemID = in.readLong(); FeedMedia result = new FeedMedia(id, null, in.readInt(), in.readInt(), in.readLong(), in.readString(), in.readString(), - in.readString(), in.readByte() != 0, new Date(in.readLong()), in.readInt()); + in.readString(), in.readByte() != 0, new Date(in.readLong()), in.readInt(), in.readLong()); result.itemID = itemID; return result; } 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 cdd63ef62..ab49bad08 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 @@ -923,7 +923,7 @@ public class PlaybackService extends Service { } /** - * Saves the current position of the media file to the DB + * Persists the current position and last played time of the media file. * * @param updatePlayedDuration true if played_duration should be updated. This applies only to FeedMedia objects * @param deltaPlayedDuration value by which played_duration should be increased. @@ -948,8 +948,9 @@ public class PlaybackService extends Service { } } playable.saveCurrentPosition(PreferenceManager - .getDefaultSharedPreferences(getApplicationContext()), - position + .getDefaultSharedPreferences(getApplicationContext()), + position, + System.currentTimeMillis() ); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 9d6827ed9..41a9a08f8 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -39,6 +39,7 @@ import de.danoeh.antennapod.core.feed.MediaType; import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBWriter; +import de.danoeh.antennapod.core.util.RewindAfterPauseUtils; import de.danoeh.antennapod.core.util.playback.AudioPlayer; import de.danoeh.antennapod.core.util.playback.IPlayer; import de.danoeh.antennapod.core.util.playback.Playable; @@ -330,10 +331,14 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre if (focusGained == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { acquireWifiLockIfNecessary(); setSpeed(Float.parseFloat(UserPreferences.getPlaybackSpeed())); - mediaPlayer.start(); - if (playerStatus == PlayerStatus.PREPARED && media.getPosition() > 0) { - mediaPlayer.seekTo(media.getPosition()); + + if (media.getPosition() > 0) { + int newPosition = RewindAfterPauseUtils.calculatePositionWithRewind( + media.getPosition(), + media.getLastPlayedTime()); + mediaPlayer.seekTo(newPosition); } + mediaPlayer.start(); setPlayerStatus(PlayerStatus.PLAYING, media); pausedBecauseOfTransientAudiofocusLoss = false; 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 bae31b52b..73584c40a 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 @@ -732,7 +732,7 @@ public class DBWriter { } /** - * Saves the 'position' and 'duration' attributes of a FeedMedia object + * Saves the 'position', 'duration' and 'last played time' attributes of a FeedMedia object * * @param media The FeedMedia object. */ 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 d55d4c231..7d1afc039 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 @@ -103,7 +103,7 @@ public class PodDBAdapter { public static final String KEY_HIDE = "hide"; public static final String KEY_LAST_UPDATE_FAILED = "last_update_failed"; public static final String KEY_HAS_EMBEDDED_PICTURE = "has_embedded_picture"; - + public static final String KEY_LAST_PLAYED_TIME = "last_played_time"; // Table names public static final String TABLE_NAME_FEEDS = "Feeds"; @@ -160,7 +160,8 @@ public class PodDBAdapter { + KEY_PLAYBACK_COMPLETION_DATE + " INTEGER," + KEY_FEEDITEM + " INTEGER," + KEY_PLAYED_DURATION + " INTEGER," - + KEY_HAS_EMBEDDED_PICTURE + " INTEGER)"; + + KEY_HAS_EMBEDDED_PICTURE + " INTEGER," + + KEY_LAST_PLAYED_TIME + " INTEGER)"; public static final String CREATE_TABLE_DOWNLOAD_LOG = "CREATE TABLE " + TABLE_NAME_DOWNLOAD_LOG + " (" + TABLE_PRIMARY_KEY + KEY_FEEDFILE @@ -444,6 +445,7 @@ public class PodDBAdapter { values.put(KEY_DOWNLOADED, media.isDownloaded()); values.put(KEY_FILE_URL, media.getFile_url()); values.put(KEY_HAS_EMBEDDED_PICTURE, media.hasEmbeddedPicture()); + values.put(KEY_LAST_PLAYED_TIME, media.getLastPlayedTime()); if (media.getPlaybackCompletionDate() != null) { values.put(KEY_PLAYBACK_COMPLETION_DATE, media.getPlaybackCompletionDate().getTime()); @@ -468,6 +470,7 @@ public class PodDBAdapter { values.put(KEY_POSITION, media.getPosition()); values.put(KEY_DURATION, media.getDuration()); values.put(KEY_PLAYED_DURATION, media.getPlayedDuration()); + values.put(KEY_LAST_PLAYED_TIME, media.getLastPlayedTime()); db.update(TABLE_NAME_FEED_MEDIA, values, KEY_ID + "=?", new String[]{String.valueOf(media.getId())}); } else { @@ -1439,7 +1442,7 @@ public class PodDBAdapter { */ private static class PodDBHelper extends SQLiteOpenHelper { - private final static int VERSION = 1040001; + private final static int VERSION = 1040002; private Context context; @@ -1673,6 +1676,10 @@ public class PodDBAdapter { if(oldVersion < 1040001) { db.execSQL(CREATE_TABLE_FAVORITES); } + if (oldVersion < 1040002) { + db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEED_MEDIA + + " ADD COLUMN " + PodDBAdapter.KEY_LAST_PLAYED_TIME + " INTEGER DEFAULT 0"); + } EventBus.getDefault().post(ProgressEvent.end()); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java new file mode 100644 index 000000000..b48c9ac64 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java @@ -0,0 +1,47 @@ +package de.danoeh.antennapod.core.util; + +import java.util.concurrent.TimeUnit; + +/** + * This class calculates the proper rewind time after the pause and resume. + *

+ * User might loose context if he/she pauses and resumes the media after longer time. + * Media file should be "rewinded" x seconds after user resumes the playback. + */ +public class RewindAfterPauseUtils { + + public static final long ELAPSED_TIME_FOR_SHORT_REWIND = TimeUnit.MINUTES.toMillis(3); + public static final long ELAPSED_TIME_FOR_MEDIUM_REWIND = TimeUnit.HOURS.toMillis(1); + public static final long ELAPSED_TIME_FOR_LONG_REWIND = TimeUnit.DAYS.toMillis(1); + + public static final long SHORT_REWIND = TimeUnit.SECONDS.toMillis(2); + public static final long MEDIUM_REWIND = TimeUnit.SECONDS.toMillis(5); + public static final long LONG_REWIND = TimeUnit.SECONDS.toMillis(10); + + /** + * @param currentPosition current position in a media file in ms + * @param lastPlayedTime timestamp when was media paused + * @return new rewinded position for playback in milliseconds + */ + public static int calculatePositionWithRewind(int currentPosition, long lastPlayedTime) { + if (currentPosition > 0 && lastPlayedTime > 0) { + long elapsedTime = System.currentTimeMillis() - lastPlayedTime; + long rewindTime = 0; + + if (elapsedTime > ELAPSED_TIME_FOR_LONG_REWIND) { + rewindTime = LONG_REWIND; + } else if (elapsedTime > ELAPSED_TIME_FOR_MEDIUM_REWIND) { + rewindTime = MEDIUM_REWIND; + } else if (elapsedTime > ELAPSED_TIME_FOR_SHORT_REWIND) { + rewindTime = SHORT_REWIND; + } + + int newPosition = currentPosition - (int) rewindTime; + + return newPosition > 0 ? newPosition : 0; + } + else { + return currentPosition; + } + } +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java index 49769f4f0..ec50dce7c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/ExternalMedia.java @@ -20,6 +20,7 @@ public class ExternalMedia implements Playable { public static final String PREF_SOURCE_URL = "ExternalMedia.PrefSourceUrl"; public static final String PREF_POSITION = "ExternalMedia.PrefPosition"; public static final String PREF_MEDIA_TYPE = "ExternalMedia.PrefMediaType"; + public static final String PREF_LAST_PLAYED_TIME = "ExternalMedia.PrefLastPlayedTime"; private String source; @@ -29,6 +30,7 @@ public class ExternalMedia implements Playable { private List chapters; private int duration; private int position; + private long lastPlayedTime; public ExternalMedia(String source, MediaType mediaType) { super(); @@ -36,9 +38,10 @@ public class ExternalMedia implements Playable { this.mediaType = mediaType; } - public ExternalMedia(String source, MediaType mediaType, int position) { + public ExternalMedia(String source, MediaType mediaType, int position, long lastPlayedTime) { this(source, mediaType); this.position = position; + this.lastPlayedTime = lastPlayedTime; } @Override @@ -51,6 +54,7 @@ public class ExternalMedia implements Playable { dest.writeString(source); dest.writeString(mediaType.toString()); dest.writeInt(position); + dest.writeLong(lastPlayedTime); } @Override @@ -58,6 +62,7 @@ public class ExternalMedia implements Playable { prefEditor.putString(PREF_SOURCE_URL, source); prefEditor.putString(PREF_MEDIA_TYPE, mediaType.toString()); prefEditor.putInt(PREF_POSITION, position); + prefEditor.putLong(PREF_LAST_PLAYED_TIME, lastPlayedTime); } @Override @@ -144,6 +149,11 @@ public class ExternalMedia implements Playable { return position; } + @Override + public long getLastPlayedTime() { + return lastPlayedTime; + } + @Override public MediaType getMediaType() { return mediaType; @@ -170,10 +180,12 @@ public class ExternalMedia implements Playable { } @Override - public void saveCurrentPosition(SharedPreferences pref, int newPosition) { + public void saveCurrentPosition(SharedPreferences pref, int newPosition, long timestamp) { SharedPreferences.Editor editor = pref.edit(); editor.putInt(PREF_POSITION, newPosition); + editor.putLong(PREF_LAST_PLAYED_TIME, timestamp); position = newPosition; + lastPlayedTime = timestamp; editor.commit(); } @@ -187,6 +199,11 @@ public class ExternalMedia implements Playable { duration = newDuration; } + @Override + public void setLastPlayedTime(long lastPlayedTime) { + this.lastPlayedTime = lastPlayedTime; + } + @Override public void onPlaybackStart() { @@ -215,8 +232,12 @@ public class ExternalMedia implements Playable { if (in.dataAvail() > 0) { position = in.readInt(); } - ExternalMedia extMedia = new ExternalMedia(source, type, position); - return extMedia; + long lastPlayedTime = 0; + if (in.dataAvail() > 0) { + lastPlayedTime = in.readLong(); + } + + return new ExternalMedia(source, type, position, lastPlayedTime); } public ExternalMedia[] newArray(int size) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java index 6e306d30a..86ec4fbd0 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Playable.java @@ -81,6 +81,12 @@ public interface Playable extends Parcelable, */ public int getPosition(); + /** + * Returns last time (in ms) when this playable was played or 0 + * if last played time is unknown. + */ + public long getLastPlayedTime(); + /** * Returns the type of media. This method should return the correct value * BEFORE loadMetadata() is called. @@ -115,13 +121,22 @@ public interface Playable extends Parcelable, * Saves the current position of this object. Implementations can use the * provided SharedPreference to save this information and retrieve it later * via PlayableUtils.createInstanceFromPreferences. + * + * @param pref shared prefs that might be used to store this object + * @param newPosition new playback position in ms + * @param timestamp current time in ms */ - public void saveCurrentPosition(SharedPreferences pref, int newPosition); + public void saveCurrentPosition(SharedPreferences pref, int newPosition, long timestamp); public void setPosition(int newPosition); public void setDuration(int newDuration); + /** + * @param lastPlayedTimestamp timestamp in ms + */ + public void setLastPlayedTime(long lastPlayedTimestamp); + /** * Is called by the PlaybackService when playback starts. */ @@ -159,28 +174,42 @@ public interface Playable extends Parcelable, */ public static Playable createInstanceFromPreferences(Context context, int type, SharedPreferences pref) { + Playable result = null; // ADD new Playable types here: switch (type) { case FeedMedia.PLAYABLE_TYPE_FEEDMEDIA: - long mediaId = pref.getLong(FeedMedia.PREF_MEDIA_ID, -1); - if (mediaId != -1) { - return DBReader.getFeedMedia(mediaId); - } + result = createFeedMediaInstance(pref); break; case ExternalMedia.PLAYABLE_TYPE_EXTERNAL_MEDIA: - String source = pref.getString(ExternalMedia.PREF_SOURCE_URL, - null); - String mediaType = pref.getString( - ExternalMedia.PREF_MEDIA_TYPE, null); - if (source != null && mediaType != null) { - int position = pref.getInt(ExternalMedia.PREF_POSITION, 0); - return new ExternalMedia(source, - MediaType.valueOf(mediaType), position); - } + result = createExternalMediaInstance(pref); break; } - Log.e(TAG, "Could not restore Playable object from preferences"); - return null; + if (result == null) { + Log.e(TAG, "Could not restore Playable object from preferences"); + } + return result; + } + + private static Playable createFeedMediaInstance(SharedPreferences pref) { + Playable result = null; + long mediaId = pref.getLong(FeedMedia.PREF_MEDIA_ID, -1); + if (mediaId != -1) { + result = DBReader.getFeedMedia(mediaId); + } + return result; + } + + private static Playable createExternalMediaInstance(SharedPreferences pref) { + Playable result = null; + String source = pref.getString(ExternalMedia.PREF_SOURCE_URL, null); + String mediaType = pref.getString(ExternalMedia.PREF_MEDIA_TYPE, null); + if (source != null && mediaType != null) { + int position = pref.getInt(ExternalMedia.PREF_POSITION, 0); + long lastPlayedTime = pref.getLong(ExternalMedia.PREF_LAST_PLAYED_TIME, 0); + result = new ExternalMedia(source, MediaType.valueOf(mediaType), + position, lastPlayedTime); + } + return result; } } -- cgit v1.2.3 From 75b2dc39c6d79cd09bbfd3e0b92ac0e4b5ff5ea8 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 16 Oct 2015 13:44:02 +0200 Subject: Use HTTP/1.1 when new fancy protocols fail --- .../core/service/download/HttpDownloader.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java index 40b7de170..eda857bd5 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/HttpDownloader.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod.core.service.download; import android.util.Log; import com.squareup.okhttp.OkHttpClient; +import com.squareup.okhttp.Protocol; import com.squareup.okhttp.Request; import com.squareup.okhttp.Response; import com.squareup.okhttp.ResponseBody; @@ -22,6 +23,7 @@ import java.net.HttpURLConnection; import java.net.SocketTimeoutException; import java.net.URI; import java.net.UnknownHostException; +import java.util.Arrays; import java.util.Date; import de.danoeh.antennapod.core.ClientConfig; @@ -93,12 +95,23 @@ public class HttpDownloader extends Downloader { // add range header if necessary if (fileExists) { request.setSoFar(destination.length()); - httpReq.addHeader("Range", - "bytes=" + request.getSoFar() + "-"); + httpReq.addHeader("Range", "bytes=" + request.getSoFar() + "-"); Log.d(TAG, "Adding range header: " + request.getSoFar()); } - Response response = httpClient.newCall(httpReq.build()).execute(); + Response response = null; + try { + response = httpClient.newCall(httpReq.build()).execute(); + } catch(IOException e) { + Log.e(TAG, e.toString()); + if(e.getMessage().contains("PROTOCOL_ERROR")) { + httpClient.setProtocols(Arrays.asList(Protocol.HTTP_1_1)); + response = httpClient.newCall(httpReq.build()).execute(); + } + else { + throw e; + } + } responseBody = response.body(); String contentEncodingHeader = response.header("Content-Encoding"); boolean isGzip = StringUtils.equalsIgnoreCase(contentEncodingHeader, "gzip"); -- cgit v1.2.3 From 87d27a7c0b327b0827c09dfcb6a0b9162266003e Mon Sep 17 00:00:00 2001 From: Stefan Mitrik Date: Sat, 17 Oct 2015 12:00:46 +0200 Subject: Rewind after pause - used less conservative rewind times --- .../de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java index b48c9ac64..ee306a401 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/RewindAfterPauseUtils.java @@ -10,13 +10,13 @@ import java.util.concurrent.TimeUnit; */ public class RewindAfterPauseUtils { - public static final long ELAPSED_TIME_FOR_SHORT_REWIND = TimeUnit.MINUTES.toMillis(3); + public static final long ELAPSED_TIME_FOR_SHORT_REWIND = TimeUnit.MINUTES.toMillis(1); public static final long ELAPSED_TIME_FOR_MEDIUM_REWIND = TimeUnit.HOURS.toMillis(1); public static final long ELAPSED_TIME_FOR_LONG_REWIND = TimeUnit.DAYS.toMillis(1); - public static final long SHORT_REWIND = TimeUnit.SECONDS.toMillis(2); - public static final long MEDIUM_REWIND = TimeUnit.SECONDS.toMillis(5); - public static final long LONG_REWIND = TimeUnit.SECONDS.toMillis(10); + public static final long SHORT_REWIND = TimeUnit.SECONDS.toMillis(3); + public static final long MEDIUM_REWIND = TimeUnit.SECONDS.toMillis(10); + public static final long LONG_REWIND = TimeUnit.SECONDS.toMillis(20); /** * @param currentPosition current position in a media file in ms -- cgit v1.2.3 From 860741a7bbd7a68f8b656c2c0a9a9a6612ccf676 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 16 Oct 2015 15:00:41 +0200 Subject: Wait for seek completion --- .../playback/PlaybackServiceMediaPlayer.java | 47 +++++++++++++--------- 1 file changed, 28 insertions(+), 19 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index 41a9a08f8..ca5c3e8b5 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -25,6 +25,7 @@ import com.bumptech.glide.request.target.Target; import org.apache.commons.lang3.Validate; import java.io.IOException; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadPoolExecutor; @@ -78,6 +79,7 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre * have to wait until these operations have finished. */ private final ReentrantLock playerLock; + private CountDownLatch seekLatch; private final PSMPCallback callback; private final Context context; @@ -290,11 +292,11 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre builder.putString(MediaMetadataCompat.METADATA_KEY_ART_URI, p.getImageUri().toString()); try { Bitmap art = Glide.with(context) - .load(p.getImageUri()) - .asBitmap() - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) - .get(); + .load(p.getImageUri()) + .asBitmap() + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL) + .get(); builder.putBitmap(MediaMetadataCompat.METADATA_KEY_ART, art); } catch (Exception e) { Log.e(TAG, Log.getStackTraceString(e)); @@ -332,11 +334,11 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre acquireWifiLockIfNecessary(); setSpeed(Float.parseFloat(UserPreferences.getPlaybackSpeed())); - if (media.getPosition() > 0) { + if (playerStatus == PlayerStatus.PREPARED && media.getPosition() > 0) { int newPosition = RewindAfterPauseUtils.calculatePositionWithRewind( - media.getPosition(), - media.getLastPlayedTime()); - mediaPlayer.seekTo(newPosition); + media.getPosition(), + media.getLastPlayedTime()); + seekToSync(newPosition); } mediaPlayer.start(); @@ -438,7 +440,7 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre } if (media.getPosition() > 0) { - mediaPlayer.seekTo(media.getPosition()); + seekToSync(media.getPosition()); } if (media.getDuration() == 0) { @@ -498,8 +500,13 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre statusBeforeSeeking = playerStatus; setPlayerStatus(PlayerStatus.SEEKING, media); } + seekLatch = new CountDownLatch(1); mediaPlayer.seekTo(t); - + try { + seekLatch.await(10, TimeUnit.SECONDS); + } catch (InterruptedException e) { + e.printStackTrace(); + } } else if (playerStatus == PlayerStatus.INITIALIZED) { media.setPosition(t); startWhenPrepared.set(false); @@ -1142,16 +1149,18 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre }; private final void genericSeekCompleteListener() { - executor.submit(new Runnable() { - @Override - public void run() { - playerLock.lock(); - if (playerStatus == PlayerStatus.SEEKING) { - setPlayerStatus(statusBeforeSeeking, media); - } - playerLock.unlock(); + Thread t = new Thread(() -> { + Log.d(TAG, "genericSeekCompleteListener"); + if(seekLatch != null) { + seekLatch.countDown(); } + playerLock.lock(); + if (playerStatus == PlayerStatus.SEEKING) { + setPlayerStatus(statusBeforeSeeking, media); + } + playerLock.unlock(); }); + t.start(); } private final MediaSessionCompat.Callback sessionCallback = new MediaSessionCompat.Callback() { -- cgit v1.2.3 From e4bb88f1f21ea9b1f1280837a27560941ca0542c Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 17 Oct 2015 18:20:20 +0200 Subject: If already seeking, wait for current seek to complete --- .../core/service/playback/PlaybackServiceMediaPlayer.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index ca5c3e8b5..f6c71daa7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -500,12 +500,19 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre statusBeforeSeeking = playerStatus; setPlayerStatus(PlayerStatus.SEEKING, media); } + if(seekLatch != null && seekLatch.getCount() > 0) { + try { + seekLatch.await(3, TimeUnit.SECONDS); + } catch (InterruptedException e) { + Log.e(TAG, Log.getStackTraceString(e)); + } + } seekLatch = new CountDownLatch(1); mediaPlayer.seekTo(t); try { - seekLatch.await(10, TimeUnit.SECONDS); + seekLatch.await(3, TimeUnit.SECONDS); } catch (InterruptedException e) { - e.printStackTrace(); + Log.e(TAG, Log.getStackTraceString(e)); } } else if (playerStatus == PlayerStatus.INITIALIZED) { media.setPosition(t); -- cgit v1.2.3 From 91ae7427fc328d7a282d82c21dac5ba71ac46f15 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 17 Oct 2015 14:14:56 -0400 Subject: updated strings --- core/src/main/res/values-az/strings.xml | 1 - core/src/main/res/values-cs-rCZ/strings.xml | 39 ++++- core/src/main/res/values-da/strings.xml | 2 - core/src/main/res/values-de/strings.xml | 34 +++- core/src/main/res/values-es-rES/strings.xml | 1 - core/src/main/res/values-es/strings.xml | 32 +++- core/src/main/res/values-fr/strings.xml | 51 +++++- core/src/main/res/values-hi-rIN/strings.xml | 1 - core/src/main/res/values-it-rIT/strings.xml | 17 +- core/src/main/res/values-iw-rIL/strings.xml | 9 +- core/src/main/res/values-ja/strings.xml | 31 +++- core/src/main/res/values-ko/strings.xml | 3 - core/src/main/res/values-nl/strings.xml | 240 +++++++++++++++++++++++++--- core/src/main/res/values-pl-rPL/strings.xml | 2 - core/src/main/res/values-pt-rBR/strings.xml | 49 +++++- core/src/main/res/values-pt/strings.xml | 48 ++++-- core/src/main/res/values-ro-rRO/strings.xml | 1 - core/src/main/res/values-ru/strings.xml | 2 - core/src/main/res/values-sv-rSE/strings.xml | 3 - core/src/main/res/values-tr/strings.xml | 77 ++++++++- core/src/main/res/values-uk-rUA/strings.xml | 79 ++++++--- core/src/main/res/values-zh-rCN/strings.xml | 107 ++++++++++++- 22 files changed, 730 insertions(+), 99 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values-az/strings.xml b/core/src/main/res/values-az/strings.xml index 3610f837e..623c308b2 100644 --- a/core/src/main/res/values-az/strings.xml +++ b/core/src/main/res/values-az/strings.xml @@ -4,7 +4,6 @@ AntennaPod Kanallar PODKASTLAR - EPIZODLAR Yeni Gözləmədə Parametrlər diff --git a/core/src/main/res/values-cs-rCZ/strings.xml b/core/src/main/res/values-cs-rCZ/strings.xml index 4a89a7d8c..2032c307c 100644 --- a/core/src/main/res/values-cs-rCZ/strings.xml +++ b/core/src/main/res/values-cs-rCZ/strings.xml @@ -5,9 +5,11 @@ Kanály Přidat podcast PODCASTY - EPIZODY + Epizody Nové epizody Všechny epizody + Vše + Oblíbené Nový Seznam nepřečtených Nastavení @@ -29,6 +31,7 @@ Nastavení panelu Řadit dle počtu Řadit abecedně + Řadit dle data zveřejnění Počet nových a nepřehraných epizod Počet nových epizod Počet nepřehraných epizod @@ -70,12 +73,21 @@ Zkusit znovu Zahrnout do automaticky stahovaných Použít na předchozí epizody - Nová funkce auto stahování bude automaticky použita na nové epizody.\nChcete ji také použít na předchozí epizody? + Nové nastavení automatického stahování bude použito pro nové epizody.\nChcete ho použít také na epizody zveřejněné dříve? Automaticky smazat epizodu\n(přeskočit globální nastavení) \u0020paralelních stahování Globální Vždy Nikdy + Odeslat... + Nikdy + Pokud není ve frontě + Po dokončení + + 1 den po dokončení + %d dny po dokončení + %d dnů po dokončení + URL kanálu URL nebo webová stránka kanálu @@ -125,6 +137,8 @@ Přidat do fronty Přidáno do fronty Odebrat z fronty + Přidat k oblíbeným + Odebrat z obíbených Navštívit stránku Flattrovat Vše do fronty @@ -133,6 +147,7 @@ Aktivovat automatické stahování Deaktivovat automatické stahování Vymazat pozici přehrávání + Položka odebrána úspěšné selhalo @@ -228,10 +243,11 @@ AntennaPod flattr selhal Získávání flattrovaných příspěvků - Stáhnout plugin - Plugin není nainstalován - Pro možnost měnit rychlost přehrávání musí být nainstalovaná knihovna třetí strany.\n\nKlikněte na \"Stáhnout Plugin\" ke stažení pluginu z Obchodu Play.\n\nAntennaPod nenese žádnou odpovědnost za jakékoliv problémy způsobené tímto pluginem. + Stáhnout modul + Modul není nainstalován + Pro možnost měnit rychlost přehrávání musí být nainstalovaná knihovna třetí strany nebo povolen experimentální přehrávač Sonic [Android 4.1+].\n\nKlikněte na \"Stáhnout modul\" k jeho stažení z Obchodu Play.\n\nAntennaPod nenese žádnou odpovědnost za jakékoliv problémy způsobené tímto modulem. Chyby hlaste jeho vývojářům. Rychlosti přehrávání + Povolit Sonic Žádné položky v seznamu. Zatím nebyly přidány žádné kanály. @@ -241,6 +257,8 @@ Fronta Služby Flattr + Vyčistit epizody + Epizody které nejsou ve frontě a nejsou označeny jako oblíbené lze smazat pro uvolnění místa Při odpojení sluchátek pozastavit přehrávání. Pokračovat v přehrávání po připojení sluchátek Po přehrání položky z fronty přejít automaticky na další @@ -248,6 +266,8 @@ Automatické mazání Označit epizody jako poslechnuté i pokud ještě zbývá určitý počet sekund přehrávání do jejich konce Chytré označování jako poslechnuté + Odstranit epizody z fronty při jejich přeskočení + Přeskočení odstraní epizody Přehrávání Síť Aktualizovat interval nebo čas v průběhu dne @@ -314,6 +334,8 @@ Vždy zobrazovat tlačítka pro přehrávání v upozornění. Pevné ovládání přehrávání Zachovat upozornění a ovládání na obrazovce uzamčení i při pozastaveném přehrávání. + Nastavit pozadí uzamčené obrazovky + Nastavit pozadí uzamčené obrazovky na obrázek aktuální epizody. Jako vedlejší efekt zobrazí toto nastavení obrázek i v aplikacích třetích stran. Zobrazit report stahování Pokud selže stahování, vygenerovat report zobrazující detaily o chybě. Verze Androidu nižší než 4.1 nepodporují rozšířená upozornění. @@ -322,6 +344,9 @@ Vypnuto Velikost odkládací paměti obrázků Velikost diskové paměti pro obrázky. + Experimentální + Přehrávač médií Sonic + Použít vestavěný přehrávač médií Sonic, jako náhradu za Prestissimo Povolit automatické flattrování Flattrovat díl jakmile bude odehráno %d procent @@ -336,6 +361,7 @@ Nalezeno v názvu OPML soubory umožňují přenést vaše podcasty z jednoho přehrávače na jiný. + Možnost %1$d Vybrat umístění v místním souborovém systému. Použít externí aplikaci jako třeba Dropbox, Google Drive nebo oblíbeného správce souborů k otevření OPML souboru. Mnoho aplikací jako třeba Google Mail, Dropbox, Google Drive a většina správců souborů umí otevřít OPML soubory v aplikaci AntennaPod. @@ -362,6 +388,9 @@ Časovač vypnutí Zbývající čas:\u0020 Neplatný vstup, musí být zadáno celé číslo + Těsně před vypršením časovače: + Potřesením vynulovat časovač + Vibrovat sekund minut hodin diff --git a/core/src/main/res/values-da/strings.xml b/core/src/main/res/values-da/strings.xml index cc18185ec..086e2f4b5 100644 --- a/core/src/main/res/values-da/strings.xml +++ b/core/src/main/res/values-da/strings.xml @@ -5,7 +5,6 @@ Feeds Tilføj podcast PODCASTS - EPISODER Nye episoder Alle episoder Nye @@ -178,7 +177,6 @@ Hent Plugin Plugin er ikke installeret - For at variabel afspilningshastighed virker skal der installeres et 3. part bibliotek.\n\nTap \'Download Plugin\' for at downloade et gratis plugin fra Play Store\n\nHvis der findes nogen problemer med dette plugin, så er det ikke AntennaPods ansvar, og problemet bør reporteres til ejeren af pluginet. Afspilningshastigheder Der er ingen emner i denne liste. diff --git a/core/src/main/res/values-de/strings.xml b/core/src/main/res/values-de/strings.xml index 47a0d7877..dab91e9e7 100644 --- a/core/src/main/res/values-de/strings.xml +++ b/core/src/main/res/values-de/strings.xml @@ -5,9 +5,11 @@ Feeds Podcast hinzufügen PODCASTS - EPISODEN + Episoden Neue Episoden Alle Episoden + Alle + Favoriten Neu Warteliste Einstellungen @@ -29,6 +31,7 @@ Seitenleisten-Einstellungen Sortieren nach Zähler Alphabetisch sortieren + Sortiere nach Veröffentlichungsdatum Anzahl neuer und ungespielter Episoden Anzahl neuer Episoden Anzahl ungespielter Episoden @@ -69,12 +72,20 @@ Erneut versuchen Automatisch herunterladen Auf bisherige Episoden anwenden - Die neue Einstellung zum Automatischen Download wird automatisch auf neue Episoden angewandt.\nMöchtest du sie auch auf die bisherige Episoden anwenden? + Die neue Auto-Download-Einstellung wird automatisch auf neue Episoden angewandt.\nMöchtest du sie auch auf schon veröffentlichte Episoden anwenden? Episoden automatisch löschen\n(überschreibt globale Vorgabe) \u0020gleichzeitige Downloads Global Immer Nie + Senden... + Nie + Wenn nicht in der Abspielliste + wenn fertig gespielt gespielt + + 1 Tag nachdem fertig gespielt + %d Tage nachdem fertig gespielt + Feed URL URL des Feeds oder der Webseite @@ -124,6 +135,8 @@ Zur Abspielliste hinzufügen Zur Abspielliste hinzugefügt Aus der Abspielliste entfernen + Zu Favoriten hinzufügen + Aus Favoriten entfernen Webseite besuchen Flattrn Alle zur Abspielliste hinzufügen @@ -132,6 +145,7 @@ Automatischen Download aktivieren Automatischen Download deaktivieren Wiedergabe-Position zurücksetzen + Element entfernt erfolgreich fehlgeschlagen @@ -229,8 +243,9 @@ Plugin herunterladen Plugin nicht installiert - Um die Wiedergabegeschwindigkeit zu verändern, muss eine Drittanbieter-Bibliothek heruntegeladen werden. Drücke auf \"Plugin herunterladen\", um ein kostenloses Plugin aus dem Play Store zu installieren. Probleme, die bei der Benutzung des Plugins auftreten, sollten dem Entwickler des Plugins gemeldet werden. + Damit die variable Wiedergabegeschwindigkeit funktioniert, musst du eine Drittanbieterbibliothek oder den experimentellen Sonic Player [Android 4.1+] heruntegeladen.\n\n Drücke \"Plugin herunterladen\", um ein kostenloses Plugin aus dem Play Store zu installieren.\n\nProbleme, die bei der Benutzung des Plugins auftreten, liegen nicht im Verantwortungsbereich von AntennaPod, und sollten dem Entwickler des Plugins gemeldet werden. Wiedergabegeschwindigkeiten + Sonic aktivieren Es sind keine Einträge in dieser Liste. Du hast noch keine Feeds abonniert. @@ -240,6 +255,8 @@ Abspielliste Dienste Flattr + Episodenaufräumer + Episoden, die nicht in der Abspielliste und nicht favorisiert sind, werden zum Aufräumen freigegeben, wenn Speicherplatz benötigt wird Pausiere die Wiedergabe, wenn der Kopfhörer entfernt worden ist. Wiedergabe fortsetzen, wenn Kopfhörer wieder reingesteckt werden Springe zur nächsten Episode, wenn die vorherige Episode endet @@ -247,6 +264,8 @@ Automatisches Löschen Episoden werden als gespielt markiert, wenn weniger als eine bestimmte Anzahl Sekunden Restspielzeit übrig sind Schlaues als gespielt markieren + Epsoden aus der Abspielliste entfernen, wenn sie übersprungen werden + Überspringen entfernt Episoden Wiedergabe Netzwerk Aktualisierungsintervall oder -tageszeit @@ -313,6 +332,8 @@ Erweiterte Wiedergabebenachrichtigung mit Abspiel-, Pause- und Stop-Knöpfen anzeigen. Persistente Wiedergabesteurung Zeige Wiedergabebedienelemente in der Benachrichtigung und im Lockscreen an, während die Wiedergabe pausiert ist. + Lockscreen-Hintergrund einstellen + Verwende das aktuelle Episodenbild als Lockscreen-Hintergrund. Es wird als Nebeneffekt auch in anderen Apps gezeigt. Zeige Download-Bericht Wenn Downloads fehlschlagen, erstelle einen Bericht, der die Details des Fehlschlages beschreibt. Android-Versionen vor 4.1 unterstützen keine erweiterten Benachrichtigungen. @@ -321,6 +342,9 @@ Deaktiviert Größe des Bilder-Zwischenspeichers Größe des Zwischenspeichers für Bilder + Experimentell + Sonic Media Player + Benutze den eingebauten Sonic Media Player als Ersatz für Prestissimo Automatisches Flattrn aktivieren Flattr eine Episode, sobald %d Prozent gespielt worden sind @@ -335,6 +359,7 @@ In Titel gefunden Mit OPML Dateien kannst du deine Podcasts von einem Podcatcher auf einen anderen übertragen + Option %1$d Wähle einen bestimmten Dateipfad aus dem lokalen Dateisystem. Verwende externe Anwendungen wie Dropbox, Google Drive oder deinen Lieblingsdateimanager, um eine OPML-Datei zu öffnen. Viele Anwendungen wie Google Mail, Dropbox, Google Drive und die meisten Dateimanager können OPML-Dateien <i>mit</ i> AntennaPod <i>öffnen</i>. @@ -361,6 +386,9 @@ Schlummerfunktion Zeit übrig:\u0020 Ungültige Eingabe, Zeit muss eine Ganzzahl sein + Wenn der Timer gleich abläuft: + Timer durch Schütteln zurücksetzen + Vibriere Sekunden Minuten Stunden diff --git a/core/src/main/res/values-es-rES/strings.xml b/core/src/main/res/values-es-rES/strings.xml index 2607d1794..cff89d3a7 100644 --- a/core/src/main/res/values-es-rES/strings.xml +++ b/core/src/main/res/values-es-rES/strings.xml @@ -4,7 +4,6 @@ AntennaPod Canales PODCASTS - EPISODIOS Nuevos Lista de espera Ajustes diff --git a/core/src/main/res/values-es/strings.xml b/core/src/main/res/values-es/strings.xml index 6670836db..ec4c73373 100644 --- a/core/src/main/res/values-es/strings.xml +++ b/core/src/main/res/values-es/strings.xml @@ -5,9 +5,11 @@ Canales Añadir podcast PODCASTS - EPISODIOS + Episodios Episodios nuevos Todos los episodios + Todos + Favoritos Nuevos Lista de espera Ajustes @@ -29,6 +31,7 @@ Preferencias del cajón Ordenar por cuenta Ordenar alfabéticamente + Ordenar por fecha de publicación Cantidad de episodios nuevos y no escuchados Cantidad de episodios nuevos Cantidad de episodios no escuchados @@ -75,6 +78,14 @@ Global Siempre Nunca + Enviar... + Nunca + Cuando no esté en cola + Después de acabar + + 1 día después de acabar + %d días después de acabar + URL del canal URL del canal o del sitio web @@ -124,6 +135,8 @@ Añadir a la cola Añadido a la cola Quitar de la cola + Agregar a Favoritos + Eliminar de Favoritos Visitar el sitio web Añadir a Flattr Ponerlos todos en cola @@ -132,6 +145,7 @@ Activar descarga automática Desactivar descarga automática Resetear posición de reproducción + Elemento elminado exitoso fallido @@ -229,8 +243,9 @@ Descargar complemento Complemento no instalado - Para que funcione la reproducción a velocidad variable, es necesaria una librería de terceros.\n\nPulsa «Descargar plugin» para descargar un plugin gratuito desde el Play Store\n\nCualquier problema relacionado con este plugin no es responsabilidad de AntennaPod y deberían ser reportados al autor del plugin. + Para que funcione la reproducción a velocidad variable, es necesaria una librería de terceros o habilitar el reproductor experimental Sonic Player [Android 4.1+].\n\nPulsa «Descargar plugin» para descargar un plugin gratuito desde el Play Store\n\nCualquier problema relacionado con este plugin no es responsabilidad de AntennaPod y deberían ser reportados al autor del plugin. Velocidades de reproducción + Habilitar Sonic Esta lista no tiene elementos. No se ha suscrito a ningún canal. @@ -240,6 +255,8 @@ Cola Servicios Flattr + Limpieza de episodios + Los episodios que no están en la cola ni son favoritos serían candidatos a eliminarse si hace falta espacio Pausar la reproducción al desconectar los auriculares Reanudar reproducción cuando se reconecten los auriculares Saltar al siguiente elemento de la cola al acabar la reproducción @@ -247,6 +264,8 @@ Eliminar automáticamente Marcar episodios como escuchados incluso si todavía quedan unos segundos por escuchar Marcar como escuchado inteligente + Eliminar episodios de la cola cuando al saltarlos + Saltar elimina el episodio Reproducción Red Intervalo de actualización u hora del día @@ -313,6 +332,8 @@ Expandir siempre la notificación para mostrar los botones de reproducción Controles de reproducción persistentes Mantener la notificación y controles en pantalla de bloqueo cuando se pausa. + Establecer fondo de pantalla de bloqueo + Establecer el fondo de pantalla de bloqueo desde la imagen del episodio. Como efecto lateral, esto también mostrará la imagen en aplicaciones de terceros. Mostrar informe de descarga Si la descarga falla, generar un informe con los detalles del fallo Las versiones de Android anteriores a la 4.1 no soportan notificaciones expandidas @@ -321,6 +342,9 @@ Deshabilitado Tamaño de la caché de imágenes Tamaño de la caché en disco para imágenes. + Experimental + Sonic media player + Usar sonic media player integrado como sustitución de Prestissimo Habilitar Flattr automático Hacer Flattr del episodio en cuanto se haya reproducido el %d por ciento @@ -335,6 +359,7 @@ Encontrado en el título Los archivos OPML le permiten migrar sus podcasts de una aplicación a otra. + Opción %1$d Elegir un una ruta del sistema de ficheros local. Usar una aplicación externa tipo Dropbox, Google Drive or su gestor de ficheros favorito para abrir un archivo OPML. Muchas aplicaciones como Google Mail, Dropbox, Google Drive y la mayoría de gestores de ficheros pueden abrir archivos OPML con AntennaPod. @@ -361,6 +386,9 @@ Temporizador Tiempo restante:\u0020 Entrada no válida, el tiempo debe ser un entero + Cuando el temporizador vaya a expirara: + Agitar para reiniciar temporizador + Vibrar segundos minutos horas diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml index 10d3fe9a4..81c731195 100644 --- a/core/src/main/res/values-fr/strings.xml +++ b/core/src/main/res/values-fr/strings.xml @@ -5,9 +5,11 @@ Flux Ajouter un podcast PODCASTS - ÉPISODES + Épisodes Nouveaux épisodes Tous les épisodes + Tout + Favoris Nouveau Liste d\'attente Préférences @@ -19,15 +21,17 @@ Annuler les téléchargements Journal des lectures gpodder.net - identifiants gpodder.net + Identifiants gpodder.net Publié récemment N\'afficher que les nouveaux épisodes Ouvrir le menu Fermer le menu + Préférences du volet Trier par compteur Trier alphabétiquement + Trier par date de publication Nombre de nouveaux épisodes non-lus Nombre de nouveaux épisodes Nombre d\'épisodes non-lus @@ -68,10 +72,20 @@ Réessayer Télécharger automatiquement à l\'avenir Appliquer aux épisodes précédents + Le nouveau paramètre Téléchargement Automatique sera automatiquement appliqué sur chaque nouvel épisode.\nVoulez-vous faire de même avec les épisodes précédents ? + Supprimer Épisode Automatiquement\n(redéfini les paramètres par défaut) \u0020téléchargements parallèles Global Toujours Jamais + Envoyer.... + Jamais + Quand l’épisode n\'est pas dans la liste + Après avoir terminé + + 1 jour après avoir été écouté + %d jours après avoir été écouté + URL du flux URL ou flux ou site web @@ -121,6 +135,8 @@ Ajouter à la liste Ajouté à la liste Supprimer de la liste + Ajouter aux Favoris + Supprimer des Favoris Visiter le site Flattr ça! Ajouter tous à la liste @@ -128,6 +144,8 @@ Passer cet épisode Activer téléchargement automatique Désactiver téléchargement automatique + Remettre a zéro la position de lecture actuelle + Élément retiré terminé échoué @@ -145,6 +163,7 @@ Erreur d\'authentification Annuler tous les téléchargements Téléchargement annulé + Téléchargement annulé\n Téléchargement Automatique désactivé pour cet élément Téléchargements terminés Rapport des téléchargements URL incorrecte @@ -163,6 +182,8 @@ Authentification requise La ressource que vous avez demandé nécessite un nom d\'utilisateur et un mot de passe Confirmer téléchargement mobile + Le téléchargement sur la connexion mobile est désactivé dans les options.\n\nVous pouvez choisir d'ajouter seulement l’épisode à la liste ou vous pouvez autoriser temporairement le téléchargement.\n\n<small>Votre choix sera retenu pour les 10 prochaines minutes.<small> + Le téléchargement sur la connexion mobile est désactivé dans les options.\n\nVoulez-vous autoriser temporairement le téléchargement?\n\n<small>Votre choix sera retenu pour les 10 prochaines minutes.<small> Rajouter à la liste Permettre temporairement @@ -222,8 +243,9 @@ Télécharger une extension Extension non installée - Pour pouvoir changer la vitesse de lecture il est nécessaire d\'installer une librairie tierce.\n\nSélectionnez \"Télécharger une extension\" pour télécharger une extension gratuite depuis le Play Store\n\nLes problèmes concernant les extensions sont de la responsabilité de leur créateur et non d\'AntennaPod. Veillez à notifier le créateur de l\'extension de tout problème. + Pour pouvoir changer la vitesse de lecture il est nécessaire d\'installer une librairie tierce ou d\'activer le lecteur expérimental Sonic [Android 4.1+].\n\nSélectionnez \"Télécharger une extension\" pour télécharger une extension gratuite depuis le Play Store\n\nLes problèmes concernant les extensions sont de la responsabilité de leur créateur et non d\'AntennaPod. Veillez à notifier le créateur de l\'extension de tout problème. Vitesses de lecture + Activer Sonic Cette liste est vide. Vous n\'êtes encore abonné à aucun flux. @@ -233,17 +255,25 @@ Liste Services Flattr + Nettoyage des épisodes + Les épisodes qui ne sont ni dans la liste ni dans les favoris peuvent être supprimés s\'il l\'espace disque devient faible Interrompre la lecture lorsque le casque est débranché Reprendre la lecture quand les écouteurs sont reconnectés Après la fin d\'un épisode, passer au suivant Supprimer l\'épisode quand la lecture est finie - Supression automatique + Suppression automatique Marquer les épisodes comme lus même s\'il reste encore moins d\'un certain intervalle de temps Marquer comme lu intelligent + Retirer les épisodes de la liste lorsqu\'ils sont passés + Passer l’épisode le retire de la liste Lecture Réseau + Intervalle de mise à jour ou heure de la journée + Indiquer un intervalle ou une heure spécifique de mise à jour des flux + Vous pouvez mettre en place un intervalle comme \"toutes les 2 heures\", une heure précise comme \"7:00\" ou désactiver les mises à jours automatique.\n\nNote: Il est possible qu\'il y ait des délais car les heures mises à jours sont inexactes. Désactiver Définir intervalle + Régler l\'heure Ne télécharger les épisodes que par Wi-Fi Lecture continue Téléchargement en Wi-Fi @@ -263,6 +293,10 @@ Configurer les paiements flattr automatiques Interface utilisateur Choisir un thème + Personnaliser le volet de navigation + Personnaliser l\'apparence du volet de navigation + Changer les éléments du volet de navigation + Choisir quels éléments apparaissent dans le volet de navigation Définir ordre des abonnements Change l\'ordre de vos abonnements Définir compteur des abonnements @@ -298,6 +332,8 @@ Toujours étendre les notifications pour montrer les boutons de lecture Boutons de lecture permanents Garder les notifications et les boutons de lecture sur l\'écran de verouillage quand la lecture est en pause + Changer l’arrière plan de l\'écran de déverrouillage + Placer l\'image de l’épisode en arrière plan de l\'écran de déverrouillage. Cela a pour effet secondaire de montrer l\'image dans les apps tierces. Afficher rapport des téléchargements Si les téléchargements échouent, générer un rapport des détails des échecs. Les versions d\'Android antérieures à 4.1 ne sont pas compatibles avec les notifications élargies @@ -306,6 +342,9 @@ Désactivé Taille de la cache d\'image Taille de l’espace disque pour stocker temporairement les images. + Expérimental + Lecteur multimédia Sonic + Utiliser le lecteur multimédia interne Sonic au lieu de Prestissimo Activer le paiement flattr automatique Lancer un paiement flattr pour un épisode dès que %d de l\'épisode a été joué @@ -320,6 +359,7 @@ Trouvé dans le titre Les fichiers OPML vous permettent de bouger vos podcasts d\'un logiciel à un autre. + Option %1$d Choisir un chemin de fichier spécifique dans le système de fichiers local Utiliser une application tierce comme Dropbox, Google Drive ou votre gestionnaire de fichier favori pour ouvrir un fichier OPML De nombreuses applications comme Google Mail, Dropbox ou Google Drive et la plupart des gestionnaires de fichiers peuvent ouvrir les fichiers OPML avec AntennaPod. @@ -346,6 +386,9 @@ Arrêt automatique Durée restante :\u0020 Entrée invalide, la durée doit être un nombre entier + Quand le minuteur est sur le point de se terminer: + Secouer afin de remettre le minuteur a zéro + Vibrer secondes minutes heures diff --git a/core/src/main/res/values-hi-rIN/strings.xml b/core/src/main/res/values-hi-rIN/strings.xml index 13ef6d489..a47178f60 100644 --- a/core/src/main/res/values-hi-rIN/strings.xml +++ b/core/src/main/res/values-hi-rIN/strings.xml @@ -4,7 +4,6 @@ ऐन्टेनापॉड फिड्स पॉडकास्ट - एपिसोड नया वेटिंग लिस्ट सेटिंग्स diff --git a/core/src/main/res/values-it-rIT/strings.xml b/core/src/main/res/values-it-rIT/strings.xml index a7ddf81d3..ba4ad9e38 100644 --- a/core/src/main/res/values-it-rIT/strings.xml +++ b/core/src/main/res/values-it-rIT/strings.xml @@ -5,9 +5,11 @@ Feed Aggiungi un podcast PODCAST - EPISODI + Episodi Episodi nuovi Tutti gli episodi + Tutti + Preferiti Nuovo Lista d\'attesa Impostazioni @@ -71,6 +73,12 @@ Globale Sempre Mai + Invia... + Mai + + 1 giorno dopo il completamento + %d giorni dopo il completamento + URL del feed www.example.com/feed @@ -86,8 +94,10 @@ Rimuovi un podcast Condividi... Condividi il link al sito + Condividi il Link con la Posizione Condividi URL del Feed Condividi URL dell\'Episodio + Condividi l\'URL dell\'Episodio con la Posizione Per favore conferma la cancellazione di questo feed e di TUTTI gli episodi collegati che sono stati precedentemente scaricati. Rimozione feed Ricarica il feed completo @@ -115,6 +125,8 @@ Aggiungi alla coda Aggiunto alla coda Rimuovi dalla coda + Aggiungi ai preferiti + Rimuovi dai preferiti Visita il sito Carica questo su Flattr Accoda tutti @@ -123,6 +135,7 @@ Attiva il download automatico Disattiva il download automatico Azzera la posizione della riproduzione + Oggetto rimosso successo fallito @@ -216,7 +229,6 @@ Scarica plugin Plugin non installato - Perché la riproduzione a velocità variabile funzioni, deve venire installata una libreria di terze parti.\n\nPremi \'Scarica un plugin\' scaricare un plugin gratuito dal Play Store.\n\nTutti i problemi rilevati con questo plugin non sono responsabilità di AntennaPod, e devono essere segnalati al proprietario del plugin. Velocità di riproduzione Non ci sono oggetti in questo elenco. @@ -235,6 +247,7 @@ Riproduzione Rete Disabilita + Imposta Intervallo Abilita il download dei media solo tramite WiFi Playback continuo Download dei media su WiFi diff --git a/core/src/main/res/values-iw-rIL/strings.xml b/core/src/main/res/values-iw-rIL/strings.xml index 07f3602ff..9f6b85c29 100644 --- a/core/src/main/res/values-iw-rIL/strings.xml +++ b/core/src/main/res/values-iw-rIL/strings.xml @@ -8,6 +8,7 @@ פרקים פרקים חדשים כל הפרקים + מועדפים חדש רשימת המתנה הגדרות @@ -37,6 +38,8 @@ אישור בטל + כן + לא מחבר שפה הגדרות @@ -63,6 +66,7 @@ לפי הגדרה גלובלית תמיד אף פעם + אף פעם כתובת הזנה כתובת של הזנה או אתר אינטרנט @@ -77,6 +81,7 @@ אנא אשר שאתה רוצה לסמן את כל פרקים בהזנה זו כנקראים. הצג מידע הסר פודקאסט + שתף... שתף קישור אתר אשר מחיקת הזנה זו ואת כל פרקי ההזנה שהורדת. הסר הזנה @@ -93,7 +98,9 @@ סומן כנקרא סמן כלא נקרא הוסף לתור + התווסף לתור הסר מהתור + התווסף למועדפים בקר באתר תרום באמצעות Flattr הכנס לתור הכל @@ -187,8 +194,6 @@ הורד תוסף תוסף לא מותקן - לאפשר השמעה במהירות משתנה, יש להתקין ספריית צד שלישית.\n\nלחץ על \'הורד תוסף\' להוריד תוסף חינמי מחנות Play.\n\n כל בעיה שתמצא בשימוש עם תוסף זה אינה באחריות של אנטנה-פוד ויש לדווחה לבעל התוסף. - מהירויות ניגון אין פריטים ברשימה זו. diff --git a/core/src/main/res/values-ja/strings.xml b/core/src/main/res/values-ja/strings.xml index 3a9e58d9a..a83b16ab9 100644 --- a/core/src/main/res/values-ja/strings.xml +++ b/core/src/main/res/values-ja/strings.xml @@ -8,6 +8,8 @@ エピソード 新エピソード 全てのエピソード + すべて + お気に入り 待ちリスト 設定 @@ -29,6 +31,7 @@ ドロワー設定 カウンターで並び替え アルファベット順に並び替え + 公開日で並び替え 新しい未再生のエピソードの数 新しいエピソードの数 未再生のエピソードの数 @@ -69,12 +72,19 @@ 再試行 自動ダウンロードに含む 前のエピソードに適用 - 新しい 自動ダウンロード の設定は、新しいエピソードに自動的に適用されます。\n前のエピソードにも適用しますか? + 新しい 自動ダウンロード の設定は、自動的に新しいエピソードに適用されます。\n以前に公開されたエピソードにも適用しますか? エピソードの自動削除\n(全般のデフォルトを上書きします) \u0020パラレル ダウンロード 全般 常に しない + 送信... + しない + キューにない時 + 完了後 + + 完了 %d 日後 + フィードURL フィードまたはWebサイトのURL @@ -124,6 +134,8 @@ キューに追加 キューに追加しました キューから削除 + お気に入りに追加 + お気に入りから削除 Webサイトを訪問 これをFlattr すべてキューに入れる @@ -132,6 +144,7 @@ 自動ダウンロードを有効にする 自動ダウンロードを無効にする 再生位置をリセット + アイテムを削除しました 完成 失敗 @@ -229,8 +242,9 @@ プラグインをダウンロード プラグイン はインストールされていません - 再生速度の変更が機能するには、サードパーティのライブラリをインストールしておく必要があります。\n\n\'プラグインをダウンロード\' をタップして、Google Playから無料のプラグインをダウンロードしてください\n\nこのプラグインを使用して見つかったすべての問題は AntennaPodの責任ではなく、プラグインのオーナーに報告すべきです。 + 再生速度の変更が機能するには、サードパーティのライブラリをインストールするか、実験的に Sonic プレーヤー [Android 4.1+] を有効にする必要があります。\n\n\'プラグインをダウンロード\' をタップして、Google Playから無料のプラグインをダウンロードしてください\n\nこのプラグインを使用して見つかったすべての問題は AntennaPodの責任ではなく、プラグインのオーナーに報告すべきです。 再生速度 + Sonic を有効にする このリストにはアイテムがありません。 まだフィードを何も購読していません。 @@ -240,6 +254,8 @@ キュー サービス Flattr + エピソード クリーンアップ + 空き容量が必要な場合、キューに含まれていおらず、お気に入りでもないエピソードは、削除の対象になります ヘッドフォンの接続が切断された時、再生を一時停止します ヘッドフォンが再接続された時に再生を再開します 再生が完了した時に次のキューのアイテムに移動します @@ -247,6 +263,8 @@ 自動削除 一定の秒数未満の再生時間がまだ残っている場合でも、エピソードを再生済としてマークします 再生済としてスマートマーク + エピソードをスキップしたときに、エピソードをキューから削除します + スキップでエピソードを削除 再生 ネットワーク 間隔または時間を更新 @@ -313,6 +331,8 @@ 常に再生ボタンを表示するように通知を展開します。 永続再生コントロール 再生が一時停止された時に、通知およびロック画面のコントロールを保持します。 + ロック画面の背景を設定 + ロック画面の背景を、現在のエピソードの画像に設定します。副作用として、これはサードパーティのアプリケーションでも画像を表示します。 ダウンロード レポートを表示 ダウンロードが失敗した場合、失敗の詳細を表示するレポートを生成します。 Androidバージョン4.1以前では、拡張通知をサポートしていません。 @@ -321,6 +341,9 @@ 無効 画像キャッシュサイズ 画像のディスクキャッシュのサイズ。 + 実験的 + Sonic メディアプレーヤー + Prestissimo の代わりに、内蔵の Sonic メディアプレーヤーを使用します 自動Flattrを有効にする %d %再生したらエピソードをFlattr @@ -335,6 +358,7 @@ タイトルで見つかりました OPMLファイルで、あるポッドキャッチャーから別のものにポッドキャストを移動することができます。 + オプション %1$d ローカルのファイルシステムから指定するファイルパスを選択してください。 Dropbox、Google ドライブ、またはお好みのファイルマネージャなどの外部アプリケーションを使用して、OPML ファイルを開いてください。 Google メール、Dropbox、Google ドライブ、および多くのファイルマネージャーなどのアプリケーションで、AntennaPod OPML ファイルを 開く ことができます。 @@ -361,6 +385,9 @@ スリープタイマー 残り時間:\u0020 入力が正しくありません、時間は数字で入力してください + タイマーが期限切れになるとき: + 振るとタイマーをリセット + 振動 時間 diff --git a/core/src/main/res/values-ko/strings.xml b/core/src/main/res/values-ko/strings.xml index 7c9f76fcf..38b2fa3be 100644 --- a/core/src/main/res/values-ko/strings.xml +++ b/core/src/main/res/values-ko/strings.xml @@ -5,7 +5,6 @@ 피드 팟캐스트 추가 팟캐스트 - 에피소드 새 에피소드 모든 에피소드 신규 @@ -69,7 +68,6 @@ 다시 시도 자동 다운로드에 포함 예전 에피소드에 적용 - 새로운 <i>자동 다운로드</I> 설정은 자동으로 새로운 에피소드에 적용됩니다. 예전 에피소드에도 적용하시겠습니까? 에피소드 자동 삭제\n(전체 설정보다 우선) \u0020동시 다운로드 전체 설정 @@ -229,7 +227,6 @@ 플러그인 다운로드 플러그인을 설치하지 않았습니다 - 재생 속도 조절이 동작하려면 외부 라이브러리를 설치해야 합니다.\n\nPlay Store에서 무료 플러그인을 다운로드하려면 \'플러그인 다운로드\'를 누르십시오.\n\n이 플러그인을 사용하면서 생기는 문제는 안테나팟의 책임이 아니므로 해당 플러그인의 관리자에게 문의하십시오. 재생 속도 이 목록에 항목이 없습니다. diff --git a/core/src/main/res/values-nl/strings.xml b/core/src/main/res/values-nl/strings.xml index 4ef43ecaf..07c786ad9 100644 --- a/core/src/main/res/values-nl/strings.xml +++ b/core/src/main/res/values-nl/strings.xml @@ -3,31 +3,55 @@ AntennaPod Feeds + Podcast toevoegen PODCASTS - AFLEVERINGEN + Afleveringen + Nieuwe afleveringen + Alle afleveringen + Alle + Favorieten Nieuw Wachtlijst Instellingen Podcast toevoegen Downloads + Bezig + Voltooid + Geschiedenis Annuleer download Afspeelgeschiedenis gpodder.net gpodder.net login + Recent gepubliceerd + Alleen nieuwe afleveringen weergeven + Menu openen + Menu sluiten + Menu voorkeuren + Op aantal afleveringen + Op alfabetische volgorde + Op datum van feed-update + Aantal nieuwe en onbeluisterde afleveringen + Aantal nieuwe afleveringen + Aantal onbeluisterde afleveringen + Geen (alfabetisch sorteren) In de browser openen - URL kopieren + URL kopiëren URL delen URL naar klembord gekopieerd. + Ga naar specifiek tijdstip Geschiedenis wissen Bevestig - Annuleer + Annuleren + Ja + Nee Auteur Taal + URL Instellingen Beeld Fout @@ -46,32 +70,85 @@ Gebruikersnaam en wachtwoord opslaan Sluiten Opnieuw proberen - Voor het automatisch downloaden beschouwen + Meenemen bij automatisch downloaden + Toepassen op bestaande afleveringen + De instelling voor Automatisch downloaden wordt automatisch toegepast op toekomstige afleveringen.\nWilt u het ook toepassen op eerder gepubliceerde afleveringen? + Automatisch aflevering verwijderen + \u0020parallele downloads + Standaardinstelling + Altijd + Nooit + Versturen... + Nooit + Wanneer niet in de wachtrij + Wanneer aflevering volledig is afgespeeld + + 1 dag nadat de aflevering als afgespeeld is gemarkeerd + %d dagen nadat de aflevering als afgespeeld is gemarkeerd + Feed URL - Podcast toevoegen bij URL + www.voorbeeld.nl/feed + Podcast toevoegen via URL + Podcast vinden in de gids + U kunt nieuwe podcasts zoeken op naam, categorie of populariteit in de gpodder.net database, of de iTunes winkel doorzoeken. + gpodder.net doorbladeren - Alles als gelezen markeren + Alles als beluisterd markeren + Alle afleveringen als afgespeeld markeren + Bevestig aub dat u alle afleveringen als afgespeeld wilt markeren. + Bevestig aub dat u alle afleveringen van deze feed als afgespeeld wilt markeren. + Alles als gelezen markeren Toon informatie - Website link delen + Podcast verwijderen + Delen... + Link van de aflevering delen + Link van de aflevering met tijdstip delen + URL van de feed delen + URL van het mediabestand delen + URL van mediabestand met tijdstip delen Bevestig dat u deze feed en ALLE afleveringen van deze feed die u hebt gedownload wilt verwijderen. Feed verwijderen + Hele feed vernieuwen + Afleveringen verbergen + Afleveringen beheren + Niet afgespeeld + Gepauzeerd + Afgespeeld + In de wachtrij + Niet in de wachtrij + Gedownload + Niet gedownload + Gefilterd + {fa-exclamation-circle} Laatste vernieuwing mislukt Download Spelen Pauze + Stop Stream Verwijderen - Als gelezen markeren - Als ongelezen markeren + Aflevering(en) verwijderen + Als afgespeeld markeren + Als afgespeeld gemarkeerd + Als niet afgespeeld markeren Voeg toe aan wachtrij + Aan wachtrij toegevoegd Verwijder van wachtrij + Toevoegen aan favorieten + Verwijderen uit favorieten Website bezoeken Flattr dit - Alle in wachtrij plaatsen + Alle aan wachtrij toevoegen Alles downloaden Aflevering overslaan + Automatisch downloaden activeren + Automatisch downloaden deactiveren + Afspeelpositie resetten + Aflevering verwijderd + succesvol + mislukt Download in afwachting Aan het downloaden Opslagmedium niet gevonden @@ -86,12 +163,15 @@ Authenticatie fout Alle downloads annuleren Download geannuleerd - Downloads afgerond + Downloaden geannuleerd\nAutomatisch downloaden uitgezet voor deze aflevering + Downloads afgerond met fouten + Downloadrapport Misvormde URL IO fout Fout in de aanvraag Databasetoegangsfout Nog \u0020 downloads + Downloads verwerken Podcast gegevens aan het downloaden %1$d downloads geslaagd, %2$d mislukt Onbekende titel @@ -101,6 +181,11 @@ Er is een fout opgetreden bij het ​​downloaden van bestand:\u0020 Authenticatie vereist De opgevraagde bron vereist een gebruikersnaam en een wachtwoord + Bevestig downloaden over mobiel netwerk + Het downloaden via mobiele verbindingen is uitgezet in de instellingen.\n\nU kunt er voor kiezen om slechts de aflevering aan de wachtrij toe te voegen, of om downloaden via mobiele netwerken tijdelijk toe te staan.\nUw keuze is 10 minuten geldig. + Het downloaden via mobiele verbindingen is uitgezet in de instellingen.\n\nWilt u dit tijdelijk toestaan?\nUw keuze is 10 minuten geldig. + Toevoegen aan wachtrij + Tijdelijk toestaan Fout! Geen media aan het afspelen @@ -113,12 +198,22 @@ 00:00:00 Buffering Podcast aan het afspelen + AntennaPod - Mediaknop onbekend: %1$d + Wachtrij vastzetten + Wachtrij ontgrendelen Wachtrij leeg maken Ongedaan maken Item verwijderd Naar boven verplaatsen Naar beneden verplaatsen + Sorteren + Alfabetisch + Datum + Lengte + Oplopend + Aflopend + Bevestig aub dat u alle afleveringen uit de wachtrij wilt verwijderen Flattr inloggen Druk op onderstaande knop om het verificatieproces te starten. U wordt doorgestuurd naar de Flattr inlogscherm in uw browser en wordt gevraagd om toestemming aan AntennaPod te geven om dingen te Flattr\'en. Nadat u toestemming hebt gegeven, keert u automatisch terug naar dit scherm. @@ -126,6 +221,7 @@ Terug naar de startscherm Authenticatie is geslaagd! U kunt nu dingen vanuit de app Flattr\'en. Geen Flattr token gevonden + Het lijkt er op dat uw Flattr account niet is verbonden met AntennaPod. Klik hier om te authenticeren. Uw Flattr account lijkt niet aangesloten te zijn op AntennaPod. U kunt uw account aan AntennaPod sluiten om dingen vanuit de app te Flattr\'en, of u kunt op de website van het ding terecht om het daar te Flattr\'en. Authenticeren Actie verboden @@ -146,8 +242,9 @@ Geflattr\'de dingen aan het ontvangen Plugin downloaden - Plugin niet geinstalleerd + Plugin niet geïnstalleerd Afspeelsnelheden + Sonic instellen Er zijn geen items in deze lijst. U bent nog tot geen enkele feed geabonneerd. @@ -157,14 +254,30 @@ Wachtrij Services Flattr - Afspelen pauzeren wanneer de hoofdtelefoon wordt losgekoppeld - Volgende wachtrij item afspelen als de episode voltooid is + Automatisch opschonen + Afleveringen die niet in de wachtrij staan en niet zijn gemarkeerd zijn als favoriet, komen in aanmerking voor verwijdering bij automatisch opschonen. + Afspelen pauzeren wanneer de koptelefoon wordt losgekoppeld + Afspelen hervatten wanneer de koptelefoon opnieuw wordt aangesloten + Volgende item in de wachtrij afspelen als de aflevering voltooid is + Afleveringen verwijderen als ze zijn afgespeeld + Automatisch verwijderen + Als afgespeeld markeren wanneer minder dan een bepaald aantal seconden van de afspeeltijd over is + Slimme afgespeeld markering + Afleveringen uit de wachtrij verwijderen als u op \'overslaan\' klikt + Verwijderen na overslaan Afspelen Netwerk + Feed update interval of tijdstip + Specificeer een interval of tijdstip waarop feeds automatisch vernieuwd moeten worden + U kunt een interval zoals \'elke twee uur\' of een specifiek tijdstip zoals \'07:00 uur\' instellen, of het automatisch verversen van feeds uitzetten.\n\nNota bene: tijdstippen voor updates zijn niet precies. Er kan een kleine vertraging plaatsvinden. + Uitschakelen + Interval instellen + Tijdstip instellen Download mediabestanden alleen via WiFi Continu afspelen WiFi download van media - Loskoppeling van de hoofdtelefoon + Loskoppeling koptelefoon + Aansluiten koptelefoon Mobiele updates Updates toestaan ​​via de mobiele dataverbinding Aan het verversen @@ -176,18 +289,30 @@ Toegang intrekken Trek de toegang van deze app in tot je Flattr account. Automatische Flattr + Automatisch flattr\'en instellen User Interface Kies theme + Menu aanpassen + Het uiterlijk en andere instellingen van het menu aanpassen. + Menu-items instellen + Aanpassen welke items in het menu worden getoond + Feed volgorde instellen + De volgorde van uw feeds instellen + Teller instellen + Pas aan welke aantallen in het menu worden getoond Verander het uiterlijk van AntennaPod. Automatisch downloaden Configureer het automatisch downloaden van afleveringen. Wi-Fi filter inschakelen Automatisch downloaden alleen toestaan voor geselecteerde Wi-Fi-netwerken. + Downloaden zonder opladen + Downloaden toestaan als het apparaat niet wordt opgeladen + Gelijktijdige downloads Afleveringen cache Licht Donker Onbeperkt - uren + uur uur Handmatig Log in @@ -198,9 +323,32 @@ Wijzig de aanmeldingsgegevens van je gpodder.net account. Afspeelsnelheden Pas de beschikbare snelheden aan voor de variabele audio afspeelsnelheid + Snelheid van vooruitspoelen + Snelheid terugspoelen Definieer hostname Gebruik standaard host + Bedienen via melding + Altijd de bedieningsknoppen tonen bij de melding in het notificatiecentrum. + Behoud bedieningsknoppen + Ook bedieningsknoppen in het notificatiecentrum en op het vergrendelingsscherm behouden als het afspelen gepauzeerd wordt. + Achtergorndafbeelding vergrendelingsscherm + Laat de afbeelding van de huidige aflevering zien. Ten gevolge van deze functie is de aflevering ook beschikbaar voor andere apps. + Laat downloadrapport zien + Genereer een rapport met fout-details als downloads mislukken + Android versies lager dan 4.1 ondersteunen geen knoppen in het notificatiecentrum. + Nieuwe afleveringen aan het begin van de wachtrij toevoegen. + Bovenaan wachtrij toevoegen + Uitgeschakeld + Grootte cachegeheugen + De groote van het cachegeheugen voor afbeeldingen aanpassen. + Experimentele functie + Sonic mediaspeler + Sonic, de standaard mediaspeler van Android, gebruiken als alternatief voor Prestissimo + Automatisch flattr\'en aanzetten + Flattr een aflevering zodra %d procent is afgespeeld + Flattr de aflevering bij afspelen + Flattr aflevering als afspelen is gestopt Feeds of afleveringen zoeken Gevonden in de shownotes @@ -210,17 +358,25 @@ Gevonden in de titel Met OPML-bestanden kan je podcasts van de ene naar de andere podcatcher verplaatsen. + Optie %1$d + Kies een bestand van een specifieke locatie via bestandsbeheer. + Kies een OPML bestand via een andere app, zoals Dropbox en Google Drive, of via uw bestandsbeheerder. + Ga naar een OPML bestand in apps zoals GMail, Dropbox en Google Drive om het met AntennaPod te openen. Start importeren - OPML import + OPML importeren FOUT! OPML-bestand aan het lezen Er is een fout opgetreden bij het lezen van het OPML-bestand: De import map is leeg. Selecteer alles Deselecteer alles + Selecteren … + Via bestandsbeheer + Via externe app OPML export Aan het exporteren... Export fout + OPML bestand succesvol geëxporteerd. Het OPML-bestand is in \u0020 geplaatst Slaap timer instellen @@ -229,6 +385,24 @@ Slaap timer Resterende tijd:\u0020 Ongeldige invoer, de tijd moet een geheel getal zijn + Als de timer bijna afloopt: + Schudden om opnieuw in te stellen + Trillen + seconden + minuten + uur + + 1 seconde + %d seconden + + + 1 minuut + %d minuten + + + 1 uur + %d uur + CATEGORIEËN TOP PODCASTS @@ -237,12 +411,13 @@ Log in Welkom op de gpodder.net login proces. Eerst, typ je login gegevens: Log in + Als u nog geen account hebt, kunt u er hier een aanmaken:\nhttps://gpodder.net/register/ Gebruikersnaam Wachtwoord Apparaatselectie Maak een nieuw apparaat aan om voor je gpodder.net account te gebruiken of kies een bestaande: Device ID:\u0020 - Titel + Apparaatnaam Maak een nieuw apparaat aan Kies een bestaand apparaat: Apparaat ID mag niet leeg zijn @@ -270,6 +445,9 @@ Kies default map Het afspelen onderbreken in plaats van het volume te verlagen wanneer er een andere app geluiden af wilt spelen Pauze voor onderbrekingen + Afspelen hervatten na beëindigen telefoongesprek + Hervatten na gesprek + AntennaPod moet opnieuw worden opgestart om deze wijziging door te voeren. Abonneren Geabonneerd @@ -291,8 +469,34 @@ Aflevering is in de queue Aantal nieuwe afleveringen Aantal afleveringen dat begonnen te luisteren zijn + Item verslepen om het te verplaatsen + Volgende pagina laden + Authenticatie + Gebruikersnaam en wachtwoord aanpassen voor deze podcast + Database upgraden Abonnementen aan het importeren vanuit single-purpose apps... + Zoeken in iTunes + Selecteren … + Alle + Alle afleveringen selecteren + Geen + Alle afleveringen deselecteren + Afgespeeld + Alle afgespeelde afleveringen selecteren + Niet afgespeeld + Niet afgespeelde afleveringen geselecteerd + Gedownload + Gedownloadde afleveringen geselecteerd + Niet gedownload + Niet gedownloadde afleveringen geselecteerd + Sorteren op ... + Titel (A \u2192 Z) + Titel (A \u2192 A) + Datum (nieuw \u2192 oud) + Datum (oud \u2192 nieuw) + Lengte (kort \u2192 lang) + Lengte (lang \u2192 kort) diff --git a/core/src/main/res/values-pl-rPL/strings.xml b/core/src/main/res/values-pl-rPL/strings.xml index a43ce7722..f61dd7c07 100644 --- a/core/src/main/res/values-pl-rPL/strings.xml +++ b/core/src/main/res/values-pl-rPL/strings.xml @@ -5,7 +5,6 @@ Kanały Dodaj podcast PODCASTY - ODCINKI Nowe odcinki Wszystkie odcinki Nowy @@ -178,7 +177,6 @@ Pobierz wtyczkę Wtyczka nie zainstalowana - Aby odtwarzać ze zmienną prędkością niezbędna jest instalacja biblioteki innej firmy.\n\nDotknij \'Pobierz wtyczkę\' aby pobrać darmową wtyczkę z Play Store\n\nAntennaPod nie odpowiada za problemy wynikłe z używania tej wtyczki, które powinny zostać zgłoszone bezpośrednio autorowi wtyczki. Prędkość odtwarzania Brak elementów na tej liście. diff --git a/core/src/main/res/values-pt-rBR/strings.xml b/core/src/main/res/values-pt-rBR/strings.xml index 3d421fdb2..63c3ffb18 100644 --- a/core/src/main/res/values-pt-rBR/strings.xml +++ b/core/src/main/res/values-pt-rBR/strings.xml @@ -3,8 +3,10 @@ AntennaPod Feeds + Adicionar Podcast PODCASTS - EPISÓDIOS + Novos Episódios + Todos Episódios Novo Lista de espera Configurações @@ -15,19 +17,28 @@ gpodder.net gpodder.net login + Mostrar apenas novos episódios + Abrir menu + Fechar menu + Numero de novos episódios + Nenhum Abrir no navegador Copiar URL Compartilhar URL URL copiada para área de transferência. + Ir para esta posição Apagar histórico Confirmar Cancelar + Sim + Não Autor Idioma + URL Configurações Capa Erro @@ -47,31 +58,53 @@ Fechar Tentar novamente Incluir em downloads automáticos + Sempre + Nunca URL do Feed + www.example.com/feed Adicionar podcast por URL Marcar todos como lido + Marcar todos como lido Mostrar informação + Remover Podcast + Compartilhar... Compartilhar link do site + Compartilhar link com posição + Compartilhar url do episódio + Compartilhar url do episódio com posição Por favor confirme que você deseja apagar este feed e TODOS os episódios que você fez download deste feed. Removendo feed + Ocultar Episódios + Aplicar ações + Pausado + Baixado + Não baixado + {fa-exclamation-circle} Última Atualização falhou Download Reproduzir Pausar + Parar Stream Remover + Remover Episódio Marcar como lido + Marcado como lido Marcar como não lido Adicionar à fila + Adicionado à fila Remover da fila Visitar Website Adicionar ao Flattr Enfileirar todos Baixar todos Pular episódio + Ativar download automático + Desativar download automático + com sucesso Download pendente Download em execução Dispositivo de armazenamento não encontrado @@ -83,6 +116,7 @@ Tipo de feed não suportado Erro de conexão Host desconhecido + Erro de autenticação Cancelar todos os downloads Download cancelado Downloads finalizados @@ -91,6 +125,7 @@ Erro de requisição Erro no acesso ao Banco de dados \u0020Downloads restantes + Processando downloads Baixando dados do podcast %1$d downloads com sucesso, %2$d falharam Título desconhecido @@ -98,6 +133,7 @@ Arquivo de mídia Imagem Ocorreu um erro durante download do arquivo:\u0020 + Permitir temporariamente Erro! Nenhuma mídia tocando @@ -116,6 +152,12 @@ Item removido Mover para o topo Mover para o fim + Ordenar + Alfabeticamente + Data + Duração + Crescente + Decrescente Logar no Flattr Pressione o botão abaixo para iniciar o processo de autenticação. Você será direcionado para a tela de login do Flattr, que pedirá autorização para que o AntennaPod utilize o Flattr. Após conceder a permissão, você retornará a esta tela automaticamente. @@ -203,6 +245,7 @@ O diretório de importação está vazio. Selecionar todos Remover seleção + Selecionar Exportar OPML Exportando... Erro na exportação @@ -214,6 +257,9 @@ Desligamento automático Tempo restante:\u0020 Entrada inválida, a duração precisa ser um número inteiro + segundos + minutos + horas CATEGORIAS TOP PODCASTS @@ -222,6 +268,7 @@ Login Bem-vindo ao processo de login gpodder.net. Primeiramente, digite suas informações: Login + Se você ainda não possui uma conta, você pode criar uma aqui:\nhttps://gpodder.net/register/ Nome do usuário Senha Seleção de dispositivo diff --git a/core/src/main/res/values-pt/strings.xml b/core/src/main/res/values-pt/strings.xml index f02cd629e..b9752dd49 100644 --- a/core/src/main/res/values-pt/strings.xml +++ b/core/src/main/res/values-pt/strings.xml @@ -8,6 +8,8 @@ Episódios Novos episódios Todos os episódios + Todos + Favoritos Novo Lista de espera Definições @@ -29,6 +31,7 @@ Preferências do menu Ordenar por contador Ordenar alfabeticamente + Ordenar por data de publicação Número de episódios novos ou por reproduzir Número de novos episódios Número de episódios por reproduzir @@ -75,6 +78,14 @@ Global Sempre Nunca + Enviar... + Nunca + Se não estiver na fila + Ao terminar + + 1 dia depois de terminar + %d dias depois de terminar + URL da fonte URL da fonte ou sítio web @@ -124,6 +135,8 @@ Adicionar à fila Adicionado à fila Remover da fila + Adicionar aos favoritos + Remover dos favoritos Aceder ao sítio web Flattr Colocar tudo na fila @@ -132,6 +145,7 @@ Ativar transferência automática Desativar transferência automática Repor posição de reprodução + Item removido sucesso falha @@ -229,8 +243,9 @@ Transferir extra Extra não instalado - Para que a velocidade variável de reprodução funcione, tem que instalar um biblioteca de terceiros.\n\nClique em Transferir extra para a transferir no Google Play.\n\nQuaisquer erros que ocorram na utilização do extra devem ser reportados diretamente ao seu programador. + Para que a velocidade variável de reprodução funcione, tem que instalar um biblioteca de terceiros ou ativar o reprodutor Sonic [Android 4.1+].\n\nClique em \'Transferir extra\' para a transferir no Google Play.\n\nQuaisquer erros que ocorram na utilização do extra não são da responsabilidade do AntennaPod e devem ser reportados diretamente ao seu programador. Velocidades de reprodução + Ativar Sonic Não existem itens nesta lista Ainda não possui quaisquer fontes @@ -240,6 +255,8 @@ Fila Serviços Flattr + Limpeza de episódios + Os episódios que não estiverem na fila ou que não sejam favoritos são elegiveis para remoção se necessitar de espaço Pausa na reprodução ao remover os auscultadores Continuar reprodução ao ligar os auscultadores Ir para a faixa seguinte ao terminar a reprodução @@ -247,6 +264,8 @@ Eliminação automática Marcar episódios como reproduzidos mesmo que restem alguns segundos de reprodução Marcar como reproduzido (inteligente) + Remover episódios da fila quando forem ignorados + Remover episódios ao ignorar Reprodução Rede Intervalo de atualização ou hora do dia @@ -275,14 +294,14 @@ Interface Tema Personalizar menu de navegação - Personaliza a aparência do menu de navegação + Personalizar a aparência do menu de navegação Alterar elementos do menu Alterar os itens que aparecem no menu de navegação Definir ordem de subscrição Alterar a ordem das suas subscrições - Definir contador de subsrições - Mudar informação mostrada no contador de subscrições - Mudar o aspeto do AntennaPod + Definir contador de subscrições + Alterar a informação mostrada no contador de subscrições + Alterar a aparência do AntennaPod Transferência automática Configure a transferência automática dos episódios Ativar filtro Wi-Fi @@ -301,10 +320,10 @@ Aceda à sua conta gpodder.net para poder sincronizar as subscrições Sair Sessão terminada - Mudar informação de acesso - Mudar informação de acesso à sua conta gpodder.net + Alterar informação de acesso + Alterar a informação de acesso à sua conta gpodder.net Velocidades de reprodução - Personalize as velocidades de reprodução disponíveis + Personalizar as velocidades de reprodução disponíveis Tempo a avançar Tempo a recuar Definir nome de servidor @@ -313,6 +332,8 @@ Expandir sempre a notificação para mostrar os botões de reprodução Controlos de reprodução persistentes Manter controlos de notificação e ecrã de bloqueio ao colocar a reprodução em pausa + Definir fundo do ecrã de bloqueio + Define a imagem do episódio como fundo do ecrã de bloqueio. Efeito colateral: também será mostrada em outras aplicações Mostrar relatório de erros Se a transferência falhar, gera um relatório que mostra os detalhes do erro As versões Android anteriores à 4.1 não possuem suporte à expansão de notificações @@ -321,6 +342,9 @@ Desativada Cache de imagens O tamanho da cache de imagens + Experimental + Reprodutor Sonic + Utilizar reprodutor multimédia Sonic como substituto de Prestissimo Ativar flattr automático Flattr de episódios ao atingir %d porcento de reprodução @@ -335,6 +359,7 @@ Encontrado no título Os ficheiros OPML permitem-lhe mover os podcasts entre aplicações + Opção %1$d Escolha um caminho especifico no sistema local de ficheiros Utilize aplicações externas como o Dropbox, Google Drive ou o seu gestor de ficheiros preferido para abrir o ficheiro OPML As aplicações como o Google Mail, Dropbox, Google Drive ou gestores de ficheiros podem abrir os ficheiros OPML através do AntennaPod @@ -361,6 +386,9 @@ Temporizador Tempo restante:\u0020 Tem que introduzir um número inteiro + Se o temporizador estiver a expirar: + Agitar para repor + Vibrar segundos minutos horas @@ -442,11 +470,11 @@ Episódio está na fila Número de novos episódios Número de episódios que já foi iniciada a reprodução - Arraste para mudar a posição deste item + Arraste para alterar a posição deste item Carregar próxima página Autenticação - Altere o seu nome de utilizador e senha para este podcast e seus episódios + Altere o seu nome de utilizador e palavra-passe para este podcast e seus episódios Atualizando base de dados diff --git a/core/src/main/res/values-ro-rRO/strings.xml b/core/src/main/res/values-ro-rRO/strings.xml index ce82dec1e..620336586 100644 --- a/core/src/main/res/values-ro-rRO/strings.xml +++ b/core/src/main/res/values-ro-rRO/strings.xml @@ -4,7 +4,6 @@ AntennaPod Feeduri PODCASTURI - EPISOADE Nou Listă de așteptare Setări diff --git a/core/src/main/res/values-ru/strings.xml b/core/src/main/res/values-ru/strings.xml index c2c27484a..21d4dc2f7 100644 --- a/core/src/main/res/values-ru/strings.xml +++ b/core/src/main/res/values-ru/strings.xml @@ -5,7 +5,6 @@ Каналы Добавить подкаст Подкасты - Выпуски Новые выпуски Все выпуски Новые @@ -195,7 +194,6 @@ Загрузить плагин Плагин не установлен - Для работы переменной скорости воспроизведения нужно установить библиотеку стороннего разработчика.\n\nНажмите \"Загрузить плагин\", чтобы скачать бесплатный плагин из Play Store\n\nЛюбые вопросы по работе плагина находятся вне ответственности AntennaPod и должны быть направлены владельцу плагина. Скорость воспроизведения Список пуст diff --git a/core/src/main/res/values-sv-rSE/strings.xml b/core/src/main/res/values-sv-rSE/strings.xml index ad970e521..9eabbf0c3 100644 --- a/core/src/main/res/values-sv-rSE/strings.xml +++ b/core/src/main/res/values-sv-rSE/strings.xml @@ -5,7 +5,6 @@ Flöden Lägg till Podcast PODCASTS - EPISODER Nya Episoder Alla Episoder Ny @@ -69,7 +68,6 @@ Försök igen Inkludera i automatiska nedladdningar Applicera på Föregående Episoder - Den nya inställningen Automatisk Nedladdning kommer automatiskt att appliceras på nya episoder.\nVill du också applicera det på tidigare episoder? Ta automatiskt bort episod\n(åsidosätter global standardinställning) \u0020parallella nedladdningar Global @@ -229,7 +227,6 @@ Ladda ner tillägg Tillägg ej installerat - För att variabel uppspelningshastighet skall fungera måste ett tredjepartstillägg installeras.\n\nTryck på \'Ladda ner tillägg\' för att ladda ner ett gratis tillägg från Play Store.\n\nAntennaPod ansvarar inte för problem med detta tillägg och de bör rapporteras till tilläggets skapare. Uppspelningshastigheter Det finns inget i denna lista. diff --git a/core/src/main/res/values-tr/strings.xml b/core/src/main/res/values-tr/strings.xml index d202bc67c..deaa63080 100644 --- a/core/src/main/res/values-tr/strings.xml +++ b/core/src/main/res/values-tr/strings.xml @@ -5,7 +5,6 @@ Beslemeler Cep yayını ekle CEP YAYINLARI - BÖLÜMLER Yeni bölümler Tüm bölümler Yeni @@ -27,6 +26,12 @@ Münüyü aç Menüyü kapat Çekmece Seçenekleri + Sayaca göre sırala + Alfabetik olarak sırala + Yeni ve çalınmamış bölümlerin sayısı + Yeni bölümlerin sayısı + Çalınmamış bölümlerin sayısı + Hiçbiri Tarayıcıda aç URL\'yi kopyala @@ -38,6 +43,8 @@ Onayla İptal + Evet + Hayır Yayıncı Dil URL @@ -60,7 +67,12 @@ Kapat Yeniden dene Otomatik indirmelere dahil et + Önceki Bölümlere Uygula + Bölümü Otomatik Olarak Sil\n(genel varsayılanı yoksayar) \u0020paralel indirmeler + Genel + Her zaman + Hiçbir zaman Besleme Adresi www.example.com/feed @@ -73,13 +85,20 @@ Tüm bölümleri oynatıldı olarak işaretle Lütfen tüm bölümleri oynatıldı olarak işaretlemek istediğinizi onaylayın. Lütfen bu besleme içindeki tüm bölümleri oynatıldı olarak işaretlemek istediğinizi onaylayın. + Hepsini görüldü olarak işaretle Bilgiyi göster Cep yayını kaldır - Web sayfası bağlantısı paylaş + Paylaş... + Link\'i paylaş + Link\'i Konumla birlikte paylaş + Besleme Adresini Paylaş + Bölüm Adresini Paylaş + Bölüm Adresini Konumla birlikte paylaş Lütfen bu beslemeyi ve bu beslemeye ait indirilmiş BÜTÜN bölümleri silme isteğinizi onaylayın. Besleme kaldırılıyor Tüm beslemeyi yenile Bölümleri gizle + Eylemleri uygula Oynatılmadı Duraklatıldı Oynatıldı @@ -208,7 +227,6 @@ Eklentiyi İndir Eklenti Yüklenmedi - Değişken hızlı yürütmenin çalışabilmesi için üçüncü parti bir kütüphane yüklemelisiniz.\n\nEklentiyi Play Store\'dan indirmek için \'Eklentiyi İndir\' butonuna tıklayın\n\nBu eklentiden doğacak hatalar AntennaPod\'un sorumluluğunda değildir ve bu durum eklenti sahibine bildirilmelidir. Çalma hızları Bu listede hiç öge yok. @@ -224,8 +242,15 @@ Çalma tamamlandığında kuyruktaki diğer öğeye geç Çalma bittiğinde bölümü sil Otomatik Silme + Bitmesine birkaç saniye kalmış olsa da bölümleri oynatıldı olarak işaretle Çalma + Güncelleme Aralığı veya Belirli Zamanı + Beslemelerin otomatik olarak güncellenmesi için bir zaman aralığı veya belirli bir saat ayarlayın + Otomatik güncelleştirmelerin yapılması için \"her 2 saatte bir\" gibi aralık, \"07:00\" gibi \"belirli saat\" ayarlayabilirsiniz veya devre dışı bırakabilirsiniz.\n\nNot: Güncelleme zamanları kesin değildir, kısa gecikmeler yaşanabilir. + Devre dışı + Aralık ayarla + Belirli saat ayarla Medya dosyalarını sadece kablosuz bağlantı üzerinden indir Devamlı çalma Kablosuz medya indirmesi @@ -245,6 +270,10 @@ Otomatik Flattr\'lamayı Yapılandır Kullanıcı Arayüzü Temayı seç + Uygulama Çekmecesini Özelleştir + Uygulama çekmecesinin görüntüsünü özelleştir. + Uygulama Çekmecesi öğelerini ayarla + Hangi öğelerin uygulama çekmecesinde görüneceğini değiştir. AntennaPod\'un görüntüsünü değiştir. Otomatk indirme Bölümlerin otomatik indirilmesini yapılandır. @@ -276,10 +305,14 @@ Çalma tuşlarını göstermek için bildirimi her zaman genişlet. Kalıcı oynatma kontrolleri Çalma duraklatıldığında bildirim ve ekran kilidi ayarlarını sakla. + İndirme Raporunu Göster + Eğer indirme başarısız olursa, hatanın ayrıntılarını gösteren bir rapor oluştur. Android 4.1 öncesi sürümler genişletilmiş bildirimleri desteklememektedir. Yeni bölümleri kuyruğun önüne ekle. Kuyruğun önüne ekle. Devre dışı + Görüntü Önbelleği Boyutu + Görüntüler için diskte tutulacak önbelleğin boyutu. Otomatik Flattr\'lamayı etkinleştir Bölümün yüzde %d kısmı oynatıldığında Flattr\'la @@ -305,6 +338,7 @@ İça aktarma dizini boş Hepsini seç Tüm seçimleri geri al + Seç ... Yerel dosya sisteminden Harici uygulama kullan OPML dışa aktar @@ -319,6 +353,21 @@ Zamanlayıcı Kalan süre:\u0020 Geçersiz giriş, zaman bir tam sayı olmalıdır + saniye + dakika + saat + + 1 saniye + %d saniye + + + 1 dakika + %d dakika + + + 1 saat + %d saat + KATEGORİLER POPÜLER CEP YAYINLARI @@ -363,6 +412,7 @@ Kesintiler için duraklat Bir telefon konuşması tamamlandıktan sonra çalmaya kaldığı yerden devam et Konuşmadan sonra devam et + Bu değişikliğin geçerli olması için AntennaPod yeniden başlatılmalıdır. Üye ol Üye olundu @@ -390,7 +440,28 @@ Yetkilendirme Bu cep yayını ve içerdiği bölümler için kullanıcı adı şifreyi değiştir. + Veritabanı yükseltiliyor Üyelikler tek-amaçlı uygulamalardan içe aktarılıyor... iTunes\'da Arama + Seç ... + Tümü + Tüm Bölümler Seçildi + Hiçbiri + Tüm Bölümlerin Seçimi Kaldırıldı + Çalınan + Çalınan Bölümler Seçildi + Çalınmayan + Çalınmayan Bölümler Seçildi + İndirilen + İndirilen Bölümler Seçildi + İndirilmeyen + İndirilmeyen Bölümler Seçildi + Sırala ... + Başlık (A \u2192 Z) + Başlık (Z \u2192 A) + Tarih (Yeni \u2192 Eski) + Tarih (Eski \u2192 Yeni) + Süre (Kısa \u2192 Uzun) + Süre (Uzun \u2192 Kısa) diff --git a/core/src/main/res/values-uk-rUA/strings.xml b/core/src/main/res/values-uk-rUA/strings.xml index 9715e40c3..bb577baa4 100644 --- a/core/src/main/res/values-uk-rUA/strings.xml +++ b/core/src/main/res/values-uk-rUA/strings.xml @@ -8,6 +8,8 @@ Епізоди Нові епізоди Всі епізоди + Всі + Улюблені Нові Черга Налаштування @@ -26,9 +28,10 @@ Показати меню Сховати меню - Настройки навігації + Настройки меню навігації Сортувати за лічильником Сортування за абеткою + Сортувати за датою публікації Кількість нових та непрослуханих епізодів Кількість нових епізодів Кількість непрослуханих епізодів @@ -54,7 +57,7 @@ Помилка Трапилась помілка: Оновити - Немає доступної флешки. Зовнішній носій потрібен для коректної роботи додатку + Немає доступної карти пам\'яті. Зовнішній носій потрібен для коректної роботи додатку Глави Нотатки до епізода Опис @@ -69,12 +72,21 @@ Повторити знову Включити до автозавантаження Застосувати до попередніх епізодів - Нове налаштування Автозавантаження буде автоматично застосоване до нових епізодів.\nБажаєте також застосувати його до попередніх епізодів? + Нове налаштування Автозагрузка буде автоматично застосоване до нових епізодів.\nБажаєте також застосувати його до тих епізодів що було опубліковано раніше? Автоматичне видалення епізода\n(перевизначити глобальне налаштування за замовчуванням) - \u0020паралельні завантаження + \u0020паралельних завантажень Для всіх Завжди Ніколи + Надіслати... + Ніколи + Якщо не в черзі + Після закінчення + + 1 день після закінчення + %d дні після закінчення + %d днів після закінчення + Посилання на канал URL канала або сайта @@ -96,7 +108,7 @@ Поділитись посиланням на канал Поділитись посиланням на епізод Поділитись посиланням на епізод з позицією - Ви впенені що хочете видаліти канал та всі завантажені епізоди + Ви впенені що хочете видаліти канал та всі завантажені епізоди? Удаляю канал Оновити канал цілком Приховати епізоди @@ -124,14 +136,17 @@ Додати до черги Додано до черги Видалити з черги + Додати до улюблених + Видалити з улюблених Відкрити сайт Підтримати за допомогою Flattr Додати до черги Завантажити все Пропустити епізод - Включити автоматичне завантаження + Включити автозавантаження Виключити автозавантаження Вернути початкову позицію відтворення + Видалено успішно з помилками @@ -149,7 +164,7 @@ Помилка автентифікації Скасувати всі завантаження Завантаження скасоване - Завантаження скасоване\nВимкнуто автоматичне завантаження для цього елемента + Завантаження скасоване\nАвтозавантаження для цього елемента вимкнуто Завантаження завершені з помилками Звіт про завантаження Невірний URL @@ -180,7 +195,7 @@ Шукаю Сервер помер Невідома помилка - Німає що грати + Немає що грати 00:00:00 Буферізую Грає подкаст @@ -202,10 +217,10 @@ Будь ласка, підтвердіть що ви бажаєте вилучити всі епізоди з черги. Увійти до Flattr - Нажміть цю кнопку для початку авторізації. Буде відкрито flattr в браузері, буде запит на дозвіл доступу Antennapod до flattr. Після надання доступу ви повернетесь до цього екрану автоматично + Нажміть цю кнопку для початку авторізації. Буде відкрито flattr в браузері, буде запит на дозвіл доступу AntennaPod до flattr. Після надання доступу ви повернетесь до цього екрану автоматично Ввісти ім\'я та пароль Повернення до початку - Вийшло авторізуватись. Тепер ви можете flattr things за допомогою додатку + Вдала авторизація. Тепер ви можете flattr things за допомогою додатку Немає flattr token Ваш обліковий запис flattr, здається, не підключений до AntennaPod. Натисніть тут для підключення. Здається ваш обліковий запис flattr не під\'єднано до AntennaPod. Ви можете або під\'єднати її або відкривати web сторінку в браузері @@ -227,10 +242,11 @@ AntennaPod flattr failed Retrieving flattr\'ed things - Завантажити Plugin - Plugin не встановлено - Для керування швидкістю програвання потрібно встановити додаток.\n\nНатисніть \"Завантажити додаток\" для завантаження безкоштовного додатку з Play Store\n\nЯкщо при використанні plugin виникнуть будь які проблеми - це відповідальність автора додатка, а не автора AntennaPod. + Завантажити додаток + Додаток не встановлено + Для керування швидкістю програвання потрібно встановити додаток або включити експериментальний програвач Sonic [Android 4.1+].\n\nНатисніть \"Завантажити додаток\" для завантаження безкоштовного додатку з Play Store\n\nЯкщо при використанні plugin виникнуть будь які проблеми - це відповідальність автора додатка, а не автора AntennaPod. Швидкість програвання + Включити Sonic Нічого в цьому списку Немає підписаних каналів @@ -240,6 +256,8 @@ Черга Сервіси Flattr + Чищення епізодів + У разі нестачі пам\'яті видалять епізоди які не знаходяться ні в списку улюблених ні в черзі. Зупинятись коли навушники витягнуті Поновити відтворення коли навушники повторно під’єднано Перейти до наступного епізода в черзі коли поточний закінчено @@ -247,13 +265,15 @@ Автовидалення Позначити епізоди як грані навіть якщо залишилось менш ніж зазначене число секунд до кінця відтворення Розумне позначення граних епізодів + Видаляти епізод з черги у разі його пропуска при прослуховуванні + Видалення епізода пропуском Відтворення Мережа Частота оновлень або оновлення в зазначений час Визначити інтервал часу або визначити час щодня для автооновлення - Можливо встановити інтервал як то \"кожні 2 години\", встановити час щодня як то \"7:00\" або відклюсити автоматичне оновлення взагалі.\n\nЗверніть увагу: Час оновлення не є точним. Можливі короткі затримки. + Можливо встановити інтервал як то \"кожні 2 години\", встановити час щодня як то \"7:00\" або відключити автоматичне оновлення взагалі.\n\nЗверніть увагу: Час оновлення не є точним. Можливі короткі затримки. Вимкнути - Встановити інтервал + Інтервал Встановити час щодня Завантажувати тільки через Wifi Грати безперервно @@ -274,21 +294,21 @@ Налаштування автоматичного заохочення авторів через сервіс flattr Вигляд Обрати тему - Налаштувати панель навігації - Налаштувати вигляд панелі навігації - Змінити настройки навігації - Вибрати елементи для використання у навігації + Налаштувати меню навігації + Налаштувати вигляд меню навігації + Налаштувати зміст меню навігації + Вибрати елементи які мають бути у меню навігації Встановити порядок підписок Змінити порядок ваших підписок - Встановити лічильник підписок + Налаштувати лічильник підписок Змінити інформацію яку відображає лічильник підписок Змінити вигляд AntennaPod - Автоматичне завантаження - Налаштування автоматичного завантаження епізодів + Автозавантаження + Налаштування автозавантаження епізодів Увімкнути фільтр Wi-Fi - Дозволити автоматичне завантаження тільки в цих Wi-Fi мережах + Дозволити автозавантаження тільки в цих Wi-Fi мережах Завантаження без зарядного пристрою - Дозволити завантаження коли зарядний пристрій не підключено + Дозволити автозавантаження коли зарядний пристрій не підключено Паралельні завантаження Кеш епізодів Світла @@ -312,7 +332,9 @@ Розгорнути повідомлення Завжди розгортати повідомлення, щоб показати кнопки керування. Завжди показувати елементи керування відтворенням - Показувати повідомлення та елементи керування на lockscreen в режимі паузи. + Показувати повідомлення та елементи керування на екрані блокування в режимі паузи. + Змінювати фон екрана блокування + Встановити картинку поточного епізода як фон екрана блокування. Побічний ефект - це зображення буде також видно в інших додатках. Показати звіт про завантаження У разі помилки при завантаженні створити детальний звіт про помилку. Android до версії 4.1 не підтримує розширені повідомлення. @@ -321,6 +343,9 @@ Вимкнено Розмір кеша зображень Розмір дискового кеша для зображень. + Експериментальні + Програвач Sonic + Використовивать вбудований програвач sonic media player замість Prestissimo Включити автоматичне заохочення авторів через сервіс flattr Заохотити автора через Flattr щойно %d відсотків епізода було відтворено @@ -335,6 +360,7 @@ Знайдено у назві OPML файли дозволяют вам перенести подкасти з однієї программи до іншої + Варіант %1$d Виберіть локальну папку. Вибрати OPML файл за допомогою таких додатків як Dropbox, Google Drive або файловий менеджер. Багато додатків таких як Google Mail, Dropbox, Google Drive та більшість файлових менеджерів здатні відкрити OPML файли для AntennaPod. @@ -361,6 +387,9 @@ Таймер сну Залишилось:\u0020 Помилка вводу, час повинен бути цілим + Коли таймер добігає кінця: + Струснути для перезапуска таймера + Вібрувати секунд хвилин годин diff --git a/core/src/main/res/values-zh-rCN/strings.xml b/core/src/main/res/values-zh-rCN/strings.xml index 332c8ed4c..4c36ac734 100644 --- a/core/src/main/res/values-zh-rCN/strings.xml +++ b/core/src/main/res/values-zh-rCN/strings.xml @@ -3,9 +3,8 @@ AntennaPod 订阅 - 添加博客 + 添加播客 播客 - 曲目 新曲目 所有曲目 最新 @@ -26,6 +25,13 @@ 打开菜单 关闭菜单 + 侧边栏设置 + 按数量排序 + 按名称排序 + 新曲目和播放曲目数 + 新曲目数 + 未播曲目数 + 在浏览器打开 复制 URL @@ -37,8 +43,11 @@ 确定 取消 + + 作者 语言 + 链接地址 设置 图片 错误 @@ -58,7 +67,12 @@ 关闭 重试 包含到自动下载 + 应用到之前的曲目中 + 自动删除曲目(覆盖全局选项) \u0020 并行下载 + 全局 + 总是 + 从不 订阅 URL www.example.com/feed @@ -68,13 +82,30 @@ 浏览 gpodder.net 全部标识已读 - 将所有曲目标记为已读 + 将所有曲目标记为已播放 + 请确认您要将所有曲目标为已播放 + 请确认您要将该订阅下的所有曲目标为已播放 查看信息 删除播客 + 分享到... 分享网站链接 + 分享网站链接与位置 + 分享订阅地址 + 分享曲目下载地址 + 分享曲目下载地址与位置 确认要删除这些订阅吗? 该订阅所有已经下载的曲目将一并删除. 删除订阅 刷新全部订阅 + 隐藏曲目 + 未播放 + 已暂停 + 已播放 + 已在播放列表中 + 不在播放列表中 + 已下载 + 未下载 + 已过滤的 + {fa-exclamation-circle} 上次刷新失败 下载 播放 @@ -83,15 +114,20 @@ 流媒体 删除 移除曲目 - 标记已读 - 标记未读 + 标记已播放 + 已标记为已播放 + 标记未播放 添加到播放列表 + 已添加到播放列表 从播放列表中删除 访问网站 Flattr 他 全部添加到播放列表 全部下载 跳过曲目 + 开启自动下载 + 关闭自动下载 + 重置播放进度 成功 失败 @@ -109,7 +145,9 @@ 认证错误 取消所有下载 已取消下载 + 已取消下载\n对该曲目禁用自动下载 下载完成 + 下载报告 畸形 URL IO 错误 请求出错 @@ -139,6 +177,8 @@ 播客播放中 AntennaPod - 未知媒体密钥: %1$d + 锁定播放列表 + 解锁播放列表 清空播放列表 撤消 已删除项 @@ -180,7 +220,6 @@ 插件下载 插件没有安装 - 要使播放速度可变,必须安装第三方库。\n\n点击 \'插件下载\' 从 \'Play 商店\' 下载免费插件\n\n使用这些插件中碰到的任何问题请报告给插件作者,与 AntennaPod 无关。 播放速度 列表为空. @@ -196,8 +235,15 @@ 播放完成跳转到播放列表下一项 当播放完成后删除曲目 自动删除 + 当曲目的剩余未播放时间小于一个确定值时将其表为已播放 + 智能标记为已播放 播放 网络 + 定时更新 + 可以设置更新 间隔,比如“2 小时”;或着每天特定的 时间 ,比如\"上午 7:00\";或者 禁用 自动更新。\n\n请注意:更新时间不是严格的,可能会有少许的延时。 + 禁用 + 设置间隔 + 设置时间 仅在 WIFI 情况下载媒体文件 连续播放 仅在 WIFI 情况下载 @@ -218,6 +264,14 @@ 设置自动 flattring 界面 主题选择 + 侧边栏设置 + 侧边栏外观设置 + 设置侧边栏的选项 + 改变侧边栏中的选项 + 设置订阅的排序方式 + 改变你的订阅的排序方式 + 设定订阅数 + 改变订阅数所代表的信息 改变 AntennaPod 外观 自动下载 配置自动下载的曲目 @@ -247,9 +301,14 @@ 总是扩展通知以显示播放按钮 保持播放控制 在暂停时保持通知和锁屏界面的控制。 + 显示下载报告 + 如果下载失败,生成一份显示详细失败信息的报告。 Android 4.1 之前不支持扩展通知。 添加新曲目到队列之前。 新曲目从播放列表的前排插入 + 已禁用 + 图像缓存大小 + 用于缓存图像的存储空间大小 启用自动 flattring 当播放到百分之%d时Flattr改曲目 @@ -289,6 +348,18 @@ 休眠计时器 计时剩余:\u0020 无效的输入, 时间是一个整数 + + + 小时 + + %d 秒 + + + %d 分 + + + %d 小时 + 目录 头条播客 @@ -331,6 +402,9 @@ 选择默认文件夹 当另一个应用程序要播放声音时暂停播放, 而不是降低音量 中断暂停 + 通话结束后恢复播放 + 通话后恢复 + 需要重启 AntennaPod 使改变生效。 订阅 已订阅 @@ -358,7 +432,28 @@ 验证 给本播客及曲目变更用户名及密码 + 升级数据库 正在从选定的应用中导入订阅... 搜索 iTunes + 选择 ... + 全部 + 全选 + + 取消全选 + 已播放 + 选择已播放的曲目 + 未播放 + 选择未播放曲目 + 已下载 + 选择已下载的曲目 + 未下载 + 选择未下载的曲目 + 排序 ... + 标题 (A \u2192 Z) + 标题 (Z \u2192 A) + 日期 (新 \u2192 旧) + 日期 (旧 \u2192 新) + 时长 (短 \u2192 长) + 时长 (长 \u2192 短) -- cgit v1.2.3 From 289a9c3016ab91c26fb7ecc41d46442870b57c16 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 17 Oct 2015 14:21:57 -0400 Subject: escaped apostrophes that transifex probabaly should have escaped itself but didnt' --- core/src/main/res/values-fr/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml index 81c731195..f0a7a864e 100644 --- a/core/src/main/res/values-fr/strings.xml +++ b/core/src/main/res/values-fr/strings.xml @@ -182,7 +182,7 @@ Authentification requise La ressource que vous avez demandé nécessite un nom d\'utilisateur et un mot de passe Confirmer téléchargement mobile - Le téléchargement sur la connexion mobile est désactivé dans les options.\n\nVous pouvez choisir d'ajouter seulement l’épisode à la liste ou vous pouvez autoriser temporairement le téléchargement.\n\n<small>Votre choix sera retenu pour les 10 prochaines minutes.<small> + Le téléchargement sur la connexion mobile est désactivé dans les options.\n\nVous pouvez choisir d\'ajouter seulement l\’épisode à la liste ou vous pouvez autoriser temporairement le téléchargement.\n\n<small>Votre choix sera retenu pour les 10 prochaines minutes.<small> Le téléchargement sur la connexion mobile est désactivé dans les options.\n\nVoulez-vous autoriser temporairement le téléchargement?\n\n<small>Votre choix sera retenu pour les 10 prochaines minutes.<small> Rajouter à la liste Permettre temporairement -- cgit v1.2.3 From 29a4e27493918f7fdf2867367cbe2f27ab1d7424 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Fri, 23 Oct 2015 17:46:38 -0400 Subject: if we're skipping an epsiode and keeping it, don't mark it played. fixes AntennaPod/AntennaPod#1274 --- .../antennapod/core/service/playback/PlaybackService.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'core/src/main') 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 ab49bad08..5cef2fe79 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 @@ -566,7 +566,6 @@ public class PlaybackService extends Service { if (playable instanceof FeedMedia) { FeedMedia media = (FeedMedia) playable; FeedItem item = media.getItem(); - DBWriter.markItemPlayed(item, FeedItem.PLAYED, true); try { final List queue = taskManager.getQueue(); @@ -579,9 +578,15 @@ public class PlaybackService extends Service { boolean shouldKeep = wasSkipped && UserPreferences.shouldSkipKeepEpisode(); - if (isInQueue && !shouldKeep) { - DBWriter.removeQueueItem(PlaybackService.this, item, true); + if (!shouldKeep) { + // only mark the item as played if we're not keeping it anyways + DBWriter.markItemPlayed(item, FeedItem.PLAYED, true); + + if (isInQueue) { + DBWriter.removeQueueItem(PlaybackService.this, item, true); + } } + DBWriter.addItemToPlaybackHistory(media); // auto-flattr if enabled -- cgit v1.2.3 From 89e67f09192a44319e45b3f9b71e58108b10c951 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 25 Oct 2015 13:06:05 +0100 Subject: Replace loader Replace with lambda Replace Loader with Observable onResume and onPause instead of onStart and onStop; minor changes Makes more sense to load data once at start Reorder functions to mirror lifecycle --- .../java/de/danoeh/antennapod/core/event/QueueEvent.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/QueueEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/QueueEvent.java index 4d59d75eb..4992252d1 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/event/QueueEvent.java +++ b/core/src/main/java/de/danoeh/antennapod/core/event/QueueEvent.java @@ -41,6 +41,18 @@ public class QueueEvent { this.position = position; } + public boolean contains(long id) { + if(item != null) { + return item.getId() == id; + } + for(FeedItem item : items) { + if(item.getId() == id) { + return true; + } + } + return false; + } + @Override public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) -- cgit v1.2.3 From 1a6f237258eea5839d46dc461e4a3233b8f9e02f Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 29 Oct 2015 11:01:42 +0100 Subject: Just catch everything that could go wrong --- .../main/java/de/danoeh/antennapod/core/util/DateUtils.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java index c0233f684..1a148673c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/DateUtils.java @@ -88,9 +88,13 @@ public class DateUtils { for(String pattern : patterns) { parser.applyPattern(pattern); pos.setIndex(0); - Date result = parser.parse(date, pos); - if(result != null && pos.getIndex() == date.length()) { - return result; + try { + Date result = parser.parse(date, pos); + if (result != null && pos.getIndex() == date.length()) { + return result; + } + } catch(Exception e) { + Log.e(TAG, Log.getStackTraceString(e)); } } -- cgit v1.2.3 From 3d644c194c3114f7791a0416ecb6ee9f031c5396 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Thu, 29 Oct 2015 17:53:07 -0400 Subject: updated strings --- core/src/main/res/values-de/strings.xml | 4 ++-- core/src/main/res/values-fr/strings.xml | 4 +--- core/src/main/res/values-nl/strings.xml | 7 ++++--- 3 files changed, 7 insertions(+), 8 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values-de/strings.xml b/core/src/main/res/values-de/strings.xml index dab91e9e7..c984a932d 100644 --- a/core/src/main/res/values-de/strings.xml +++ b/core/src/main/res/values-de/strings.xml @@ -264,8 +264,8 @@ Automatisches Löschen Episoden werden als gespielt markiert, wenn weniger als eine bestimmte Anzahl Sekunden Restspielzeit übrig sind Schlaues als gespielt markieren - Epsoden aus der Abspielliste entfernen, wenn sie übersprungen werden - Überspringen entfernt Episoden + Behalte Episoden beim Überspringen + Behalte übersprungene Episoden Wiedergabe Netzwerk Aktualisierungsintervall oder -tageszeit diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml index f0a7a864e..87b414a18 100644 --- a/core/src/main/res/values-fr/strings.xml +++ b/core/src/main/res/values-fr/strings.xml @@ -182,7 +182,7 @@ Authentification requise La ressource que vous avez demandé nécessite un nom d\'utilisateur et un mot de passe Confirmer téléchargement mobile - Le téléchargement sur la connexion mobile est désactivé dans les options.\n\nVous pouvez choisir d\'ajouter seulement l\’épisode à la liste ou vous pouvez autoriser temporairement le téléchargement.\n\n<small>Votre choix sera retenu pour les 10 prochaines minutes.<small> + Le téléchargement sur la connexion mobile est désactivé dans les options.\n\nVous pouvez choisir d'ajouter seulement l’épisode à la liste ou vous pouvez autoriser temporairement le téléchargement.\n\n<small>Votre choix sera retenu pour les 10 prochaines minutes.<small> Le téléchargement sur la connexion mobile est désactivé dans les options.\n\nVoulez-vous autoriser temporairement le téléchargement?\n\n<small>Votre choix sera retenu pour les 10 prochaines minutes.<small> Rajouter à la liste Permettre temporairement @@ -264,8 +264,6 @@ Suppression automatique Marquer les épisodes comme lus même s\'il reste encore moins d\'un certain intervalle de temps Marquer comme lu intelligent - Retirer les épisodes de la liste lorsqu\'ils sont passés - Passer l’épisode le retire de la liste Lecture Réseau Intervalle de mise à jour ou heure de la journée diff --git a/core/src/main/res/values-nl/strings.xml b/core/src/main/res/values-nl/strings.xml index 07c786ad9..86c1399cf 100644 --- a/core/src/main/res/values-nl/strings.xml +++ b/core/src/main/res/values-nl/strings.xml @@ -98,7 +98,7 @@ Alle afleveringen als afgespeeld markeren Bevestig aub dat u alle afleveringen als afgespeeld wilt markeren. Bevestig aub dat u alle afleveringen van deze feed als afgespeeld wilt markeren. - Alles als gelezen markeren + \'Nieuw\' label van alle afleveringen verwijderen. Toon informatie Podcast verwijderen Delen... @@ -243,6 +243,7 @@ Plugin downloaden Plugin niet geïnstalleerd + Om variabele afspeelsnelheid te kunnen gebruiken, moet een bibliotheek van derden worden geïnstalleerd of de experimentele Sonic Player worden geactiveerd (beschikbaar voor Android 4.1 en hoger).\n\nKies \'Plugin Downloaden\' om de gratis plugin via de Play Store te installeren.\n\nProblemen bij het gebruik van deze plugin zijn niet de verantwoordelijkheid van AntennaPod en moeten gemeld worden bij de ontwikkelaar van de plugin. Afspeelsnelheden Sonic instellen @@ -263,8 +264,8 @@ Automatisch verwijderen Als afgespeeld markeren wanneer minder dan een bepaald aantal seconden van de afspeeltijd over is Slimme afgespeeld markering - Afleveringen uit de wachtrij verwijderen als u op \'overslaan\' klikt - Verwijderen na overslaan + Afleveringen bewaren en in de wachtrij houden als u op \'overslaan\' klikt + Overgeslagen afleveringen bewaren Afspelen Netwerk Feed update interval of tijdstip -- cgit v1.2.3 From bbd47715cec9505447c9b803e427ec678797d25f Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Thu, 29 Oct 2015 19:28:13 -0400 Subject: updated strings --- core/src/main/res/values-fr/strings.xml | 44 +++++++++++++++++---------------- 1 file changed, 23 insertions(+), 21 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml index 87b414a18..b17574401 100644 --- a/core/src/main/res/values-fr/strings.xml +++ b/core/src/main/res/values-fr/strings.xml @@ -94,11 +94,11 @@ Vous pouvez chercher de nouveaux podcasts en filtrant par nom, catégorie ou popularité dans la bibliothèque gpodder.net, ou sur l\'iTunes Store. Chercher sur gpodder.net - Tous marquer comme lus + Marquer tous les épisodes comme lus Tous les épisodes ont été marqués comme lus Veuillez confirmer que vous voulez bien marquer tous les épisodes comme lus Veuillez confirmer que vous voulez bien marquer tous les épisode de ce flux comme lus - Marquer tout comme vu + Marquer tout les épisodes comme vus Voir les détails Supprimer le podcast Partager... @@ -120,7 +120,7 @@ Téléchargé Non téléchargé Filtré - {fa-exclamation-circle} Dernière mise à jour échouée + {fa-exclamation-circle} La dernière mise à jour a échouée Télécharger Lire @@ -164,12 +164,12 @@ Annuler tous les téléchargements Téléchargement annulé Téléchargement annulé\n Téléchargement Automatique désactivé pour cet élément - Téléchargements terminés + Téléchargements terminés avec des erreurs Rapport des téléchargements URL incorrecte Erreur d\'E/S Erreur de requête - Problème dans l\'accès à la base de données + Problème d\'accès à la base de données \u0020téléchargements restants Traitement des téléchargements Téléchargement des données du podcast @@ -181,11 +181,11 @@ Une erreur s\'est produite durant le téléchargement du fichier :\u0020 Authentification requise La ressource que vous avez demandé nécessite un nom d\'utilisateur et un mot de passe - Confirmer téléchargement mobile - Le téléchargement sur la connexion mobile est désactivé dans les options.\n\nVous pouvez choisir d'ajouter seulement l’épisode à la liste ou vous pouvez autoriser temporairement le téléchargement.\n\n<small>Votre choix sera retenu pour les 10 prochaines minutes.<small> + Confirmer le téléchargement mobile + Le téléchargement sur la connexion mobile est désactivé dans les options.\n\nVous pouvez choisir d\'ajouter seulement l\'épisode à la liste ou vous pouvez autoriser temporairement le téléchargement.\n\nVotre choix sera retenu pour les 10 prochaines minutes. Le téléchargement sur la connexion mobile est désactivé dans les options.\n\nVoulez-vous autoriser temporairement le téléchargement?\n\n<small>Votre choix sera retenu pour les 10 prochaines minutes.<small> Rajouter à la liste - Permettre temporairement + Autoriser temporairement Erreur ! Pas de lecture en cours @@ -221,7 +221,7 @@ Revenir au départ L\'authentification a réussi. Vous pouvez maintenant flattr depuis cette application. Aucun jeton Flattr trouvé. - Votre compte flattr semble ne pas être connecté à AntennaPod. Touchez ici pour vous connecter. + Votre compte flattr ne semble pas être connecté à AntennaPod. Cliquer ici pour vous connecter. Votre compte Flattr se semble pas être connecté à AntennaPod. Vous pouvez soit connecter votre compte Flattr à AntennaPod pour pouvoir flattr depuis l\'application, ou vous pouvez aller sur le site de ce que vous voulez flattr. S\'authentifier Action interdite @@ -256,7 +256,7 @@ Services Flattr Nettoyage des épisodes - Les épisodes qui ne sont ni dans la liste ni dans les favoris peuvent être supprimés s\'il l\'espace disque devient faible + Les épisodes qui ne sont ni dans la liste ni dans les favoris peuvent être supprimés si l\'espace disque devient faible Interrompre la lecture lorsque le casque est débranché Reprendre la lecture quand les écouteurs sont reconnectés Après la fin d\'un épisode, passer au suivant @@ -264,6 +264,8 @@ Suppression automatique Marquer les épisodes comme lus même s\'il reste encore moins d\'un certain intervalle de temps Marquer comme lu intelligent + Garder les épisodes quand ils sont passés + Garder les épisodes passés Lecture Réseau Intervalle de mise à jour ou heure de la journée @@ -277,7 +279,7 @@ Téléchargement en Wi-Fi Déconnexion du casque Reconnexion du casque - Mise à jour mobile + Mises à jour mobile Autoriser les mises à jour à travers la connexion de données mobile Mise à jour en cours Paramètres Flattr @@ -297,8 +299,8 @@ Choisir quels éléments apparaissent dans le volet de navigation Définir ordre des abonnements Change l\'ordre de vos abonnements - Définir compteur des abonnements - Change l\'information affichée à côté du compteur des abonnements + Définir le compteur d\'abonnements + Changer l\'information affichée par le compteur d\'abonnements Modifier l\'apparence d\'AntennaPod. Téléchargement automatique Configurer le téléchargement automatique des épisodes. @@ -332,7 +334,7 @@ Garder les notifications et les boutons de lecture sur l\'écran de verouillage quand la lecture est en pause Changer l’arrière plan de l\'écran de déverrouillage Placer l\'image de l’épisode en arrière plan de l\'écran de déverrouillage. Cela a pour effet secondaire de montrer l\'image dans les apps tierces. - Afficher rapport des téléchargements + Afficher le rapport de téléchargements Si les téléchargements échouent, générer un rapport des détails des échecs. Les versions d\'Android antérieures à 4.1 ne sont pas compatibles avec les notifications élargies Ajouter de nouveaux épisodes en tête de file @@ -443,7 +445,7 @@ Le répertoire que vous avez choisi n\'est pas vide. Les fichiers téléchargés seront ajoutés à ce répertoire. Continuer malgré tout ? Choisir le répertoire par défaut Mettre la lecture en pause au lieu de baisser le volume quand une autre application veut jouer un son - Mettre en pause lors des interruptions + Mettre en pause lors d\'interruptions Reprendre la lecture après un appel téléphonique Reprendre après appel AntennaPod doit être redémarré afin que ce changement prenne effet @@ -480,17 +482,17 @@ Chercher sur iTunes Sélectionner ... Tout - Sélectionné tous les épisodes + Tous les épisodes ont été sélectionné Aucun - Désélectionné tous les épisodes + Tous les épisodes ont été désélectionné Joués - Sélectionné tous les épisodes joués + Episodes joués sélectionnés Non joués - Sélectionné tous les épisodes non joués + Episodes non joués sélectionnés Téléchargés - Sélectionné tous les épisodes téléchargés + Episodes téléchargés sélectionnés Non téléchargés - Sélectionné tous les épisodes non téléchargés + Les épisodes non téléchargés ont été sélectioné Trier par ... Titre (A \u2192 Z) Titre (Z \u2192 A) -- cgit v1.2.3 From 663c0fd8be37ecc160a3b6336df17c5e592db75f Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 30 Oct 2015 12:16:14 +0100 Subject: Don't let the user cancel the ProgressDialog --- .../antennapod/core/asynctask/FeedRemover.java | 25 ++++++---------------- 1 file changed, 6 insertions(+), 19 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java index 255b95119..bea8d2afd 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java @@ -3,15 +3,14 @@ package de.danoeh.antennapod.core.asynctask; import android.annotation.SuppressLint; import android.app.ProgressDialog; import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnCancelListener; import android.os.AsyncTask; + +import java.util.concurrent.ExecutionException; + import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.storage.DBWriter; -import java.util.concurrent.ExecutionException; - /** Removes a feed in the background. */ public class FeedRemover extends AsyncTask { Context context; @@ -35,12 +34,7 @@ public class FeedRemover extends AsyncTask { } return null; } - - @Override - protected void onCancelled() { - dialog.dismiss(); - } - + @Override protected void onPostExecute(Void result) { dialog.dismiss(); @@ -50,15 +44,8 @@ public class FeedRemover extends AsyncTask { protected void onPreExecute() { dialog = new ProgressDialog(context); dialog.setMessage(context.getString(R.string.feed_remover_msg)); - dialog.setOnCancelListener(new OnCancelListener() { - - @Override - public void onCancel(DialogInterface dialog) { - cancel(true); - - } - - }); + dialog.setIndeterminate(true); + dialog.setCancelable(false); dialog.show(); } -- cgit v1.2.3 From e673e500c3eb73afb169e5a0f7b2de4c1c5dcdd8 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 31 Oct 2015 10:47:00 -0400 Subject: updated strings --- core/src/main/res/values-ca/strings.xml | 157 +++++++++++++++++++++++++++- core/src/main/res/values-cs-rCZ/strings.xml | 4 +- core/src/main/res/values-es/strings.xml | 4 +- core/src/main/res/values-fr/strings.xml | 42 ++++---- core/src/main/res/values-ja/strings.xml | 4 +- core/src/main/res/values-pt/strings.xml | 8 +- core/src/main/res/values-sv-rSE/strings.xml | 31 ++++++ core/src/main/res/values-uk-rUA/strings.xml | 2 - 8 files changed, 215 insertions(+), 37 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values-ca/strings.xml b/core/src/main/res/values-ca/strings.xml index c4887e512..0352c1ab9 100644 --- a/core/src/main/res/values-ca/strings.xml +++ b/core/src/main/res/values-ca/strings.xml @@ -5,9 +5,11 @@ Canals Afegeix podcast PODCASTS - EPISODIS + Episodis Episodis nous Tots els episodis + Tot + Favorits Nous Llista d\'espera Configuració @@ -26,6 +28,14 @@ Obre menú Tanca menú + Calaix de preferències + Ordre per durada + Ordre alfabètic + Ordre per data de publicació + Número d\'episodis nous i per reproduir + Número de episodis nous + Número de episodis per reproduir + Cap Obre en un navegador Copia l\'enllaç @@ -37,8 +47,11 @@ D\'acord Cancel·la + + No Autor Llengua + Adreça web Configuració Imatge Error @@ -58,6 +71,21 @@ Tanca Reintenta Inclou a baixades automàtiques + Aplica als episodis previs + El nou ajustament de baixada automàtica s\'aplicarà als nous episodis.\nVols que també sigui aplicat als episodis publicats prèviament? + Esborra episodis automàticament\n(anula la preferència global) + \u0020baixades paral·leles + Global + Sempre + Mai + Envia... + Mai + Quan no està a la cua + Després d\'acabar + + 1 dia després d\'acabar + %d dies després d\'acabar + Enllaç del canal URL, canal o lloc web @@ -68,12 +96,31 @@ Marca-ho tot com a llegit S\'han marcat tots els episodis com a llegits + Si us plau confirma que vols marcar tots els episodis com reproduits. + Si us plau confirma que vols marcar tots els episodis d\'aquest canal com reproduits. + Marca tot com a llegit Mostra informació Esborra podcast - Comparteix l\'enllaç de la plana + Comparteix... + Comparteix l\'enllaç + Comparteix enllaç amb posició + Comparteix adreça del canal + Comparteix adreça d\'Episodi + Comparteix adreça d\'Episodi amb posició Confirmeu que, efectivament, voleu suprimir aquest canal i tots els episodis que us n\'heu baixat. S\'està esborrant el canal S\'ha actualitzat el canal + Amaga Episodis + Aplica accions + Per reproduir + Pausat + Reproduit + En cua + No en cua + Baixat + No baixat + Filtrat + {fa-exclamation-circle} Darrera actualització fallida Baixa Reprodueix @@ -83,14 +130,22 @@ Suprimeix Esborra episodi Marca com a llegit + Marcats com llegits Marca com a pendent Afegeix a la cua + Afegit a la cua Suprimeix de la cua + Afegit a Favorits + Suprimeix de Favorits Visita el lloc web Comparteix amb Flattr Posa-ho tot a la cua Baixa-ho tot Omet l\'episodi + Activa baixades automàtiques + Desactiva les baixades automàtiques + Restablir posició de reproducció + Element eliminat ha funcionat ha fallat @@ -108,7 +163,9 @@ Error d\'autenticació Cancel·la totes les baixades S\'ha cancel·lat la baixada - Baixades completades + Baixada cancel·lada\nDesactivada les baixades automàtiques per aquest element + Baixades completades amb error(s) + Registre de baixades URL mal formatada Error d\'E/S Error de petició @@ -124,6 +181,11 @@ S\'ha produït un error en intentar baixar el fitxer:\u0020 Cal autenticar-se Es necessita un usuari i una contrasenya per accedir al recurs + Confirma baixada mòvil + La baixada amb conexió de dades mòvils està desactivada.\n\nPots escollir ja sigui només afegir l\'episodi a la cua o pot permetre la descàrrega de forma temporal.\n\nLa seva elecció serà recordada durant 10 minuts. + La baixada amb conexió de dades mòvils està desactivada.\n\nVols permetre la descàrrega de forma temporal?\n\nLa seva elecció serà recordada durant 10 minuts. + En cua + Permetre temporalment Error No s\'està reproduint res @@ -138,6 +200,8 @@ Podcast en reproducció AntennaPod - Control desconegut: %1$d + Bloqueja la cua + Desbloqueja la cua Buida la cua Desfés Ítem esborrat @@ -149,6 +213,7 @@ Durada Ascendent Descendent + Si us plau confirma que vols suprimir tots els episodis de la cua Inici de sessió a Flattr Premeu el botó per iniciar el procés d\'autenticació. Quan s\'obri la pantalla d\'inici de sessió de Flattr al vostre navegador, introduïu les vostres credencials i concediu a AntennaPod els permisos de compartir mitjançant Flattr. En finalitzar el procés, tornareu automàticament a aquesta pantalla. @@ -178,8 +243,9 @@ Baixa el connector Connector no instal·lat - Per a què funcioni la velocitat de reproducció variable, cal instal·lar una biblioteca addicional.\n\nFeu un toc a «Baixa el connector» per baixar-vos el connector gratuït des de la Play Store.\n\nQualsevol problema que sorgeixi en utilitzar aquest connector no és culpa de l\'AntennaPod. Cal informar-ne, doncs, al propietari del connector. + Perque la reproducció de velocitat variable funcioni, ha d\'instal lar el connector de tercers o activar el reproductor experimental Sonic [Android 4.1+].\n\nPrem \'Baixa el connector\' per baixar el connector gratuït de la Play Store.\n\nQualsevol problema que us trobeu amb l\'ús d\'aquest connector no són responsabilitat d\'AntennaPod i han de ser reportats al propietari del connector. Velocitats de reproducció + Activa Sonic No hi ha elements a la llista. No us heu subscrit a cap canal. @@ -189,13 +255,23 @@ Cua Serveis Flattr + Neteja l\'episodi + Episodis que no estan a la cua i no són favorits haurien de ser escollits per eliminar-los si es requereix espai Pausa la reproducció en desconnectar els auriculars. Continua la reproducció en connectar novament els auriculars Salta al següent element de la cua en acabar la reproducció Suprimeix l\'episodi quan s\'acabi de reproduir Esborrat automàtic + Marca episodis com com reproduits, encara que quedi menys d\'una certa quantitat de segons de temps + Marcació intel·ligent com a reproduit Reproducció Xarxa + Actualitza interval o horari del dia + Especifica un interval o una hora específica del dia per refrescar els canals de forma automàtica + Pots establir un interval com \"cada 2 hores\", establir una hora del dia com \"7:00 AM\" o disactiva l\'actualització automàtica del conjunt.\n\nPren nota: Les actualitzacions de vegades són inexactes. Es pot trobar una breu demora. + Desactivar + Establir interval + Establir hora del dia Només baixa fitxers a través d\'una xarxa sense fils Reproducció continuada Baixa a través de xarxes sense fils @@ -215,6 +291,14 @@ Configura la compartició automàtica per Flattr Interfície d\'usuari Selecció de tema + Personalitzar navegació del calaix + Personalitza l\'aparença del calaix de navegació. + Establir els elements del calaix de navegació + Canviar els elements que apareixen al calaix de navegació. + Establir ordre de subscripció + Canviar l\'ordre de les subscripcions + Establir contador de subscripció + Canviar la informació mostrada pel comptador de subscripció Canvieu l\'aparença d\'AntennaPod. Baixada automàtica Configureu la baixada automàtica d\'episodis. @@ -222,6 +306,7 @@ Permet les baixades automàtiques només per a les xarxes sense fils seleccionades. Baixa mentre no es carrega Permet les baixades automàtiques mentre la bateria no es carrega + Baixades paral·leles Memòria d\'episodis Clar Fosc @@ -237,13 +322,27 @@ Canvia les dades d\'inici de sessió del vostre compte de gpodder.net Velocitats de reproducció Personalitzeu les velocitats disponibles per a una velocitat de reproducció d\'àudio variable + Temps d\'avançada ràpida + Temps de rebobinat Definex nom del servidor Utilitza el servidor per defecte Amplia la notificació Amplia sempre les notificacions per mostrar els botons de reproducció. Botons de reproducció persistents Mantén els controls a l\'àrea de notificacions i pantalla de bloqueig quan la reproducció estigui aturada + Establir fons de la pantalla de bloqueig + Establir el fons de pantalla de bloqueig a la imatge de l\'episodi actual. Com efecte secundari, això també mostrarà la imatge en aplicacions de tercers. + Mostra informació de baixades + Si les descàrregues fallen, genera un informe que mostra els detalls de la falla. Les versions d\'Android anteriors a la 4.1 no suporten les notificacions ampliades. + Afegir nous episodis a la part davantera de la cua. + Cua al davant + Desactivar + Mida de la memòria cau de les imatges + Mida de la memòria cau en el disc de les imatges. + Experimental + Reproductor multimèdia Sonic + Utilitzeu la funció incorporada del reproductor multimèdia Sonic com a reemplaçament per Prestissimo Activa la compartició automàtica per Flattr Comparteix per Flattr l\'episodi en haver-ne reproduït el %d per cent @@ -258,6 +357,10 @@ Trobat al títol Els fitxers OPML us permeten moure els podcasts d\'un gestor de podcasts a un altre. + Opció %1$d + Trieu una ruta de fitxer específic del sistema de fitxers local. + Utilitzeu una aplicació externa com Dropbox, Google Drive o el seu gestor de fitxers preferit per obrir un fitxer OPML. + Algunes aplicacions com Google Mail, Dropbox, Google Drive i la majoria dels administradors d\'arxius pot obrir arxius OPML amb AntennaPod. Inicia la importació Importació OPML Error! @@ -266,6 +369,9 @@ El directori d\'importacions és buit. Selecciona-ho tot Deselecciona-ho tot + Sel·lecciona... + Des de sistema d\'arxius local + Utilitza aplicació externa Exportació OPML S\'està exportant... Error d\'exportació @@ -278,6 +384,24 @@ Temporitzador Temps restant:\u0020 L\'entrada no és vàlida, ja que el temps ha de ser un nombre i no ho és + Quan el temporitzador està a punt d\'expirar: + Agitar per reiniciar el temporitzador + Vibrar + segons + minuts + hores + + 1 segon + %d segons + + + 1 minut + %d minuts + + + 1 hora + %d hores + CATEGORIES TOP PODCASTS @@ -320,6 +444,9 @@ Selecciona la carpeta per defecte Pausa la reproducció en lloc de baixar el volum quan una altra app necessiti reproduir sons Pausa en interrompre + Reprendre la reproducció després d\'una trucada telefònica + Reprendre després d\'una trucada + AntennaPod s\'ha de reiniciar perquè aquest canvi tingui efecte. Subscriu Subscrit @@ -347,6 +474,28 @@ Autenticació Canvieu el nom d\'usuari i contrasenya per a aquest podcast i els seus episodis. + Actualització de la base de dades S\'estan important les subscripcions des de les apps de propòsit únic... + Cerca a iTunes + Seleccionar... + Tot + Selecciona tots els episodis + Cap + Deselecciona tots els episodis + Reproduit + Selecciona episodis reproduits + Per reproduir + Selecciona episodis sense reproduir + Baixat + Selecciona episodis descarregats + No baixat + Selecciona episodis sense descarregar + Ordena per... + Títol (A \u2192 Z) + Títol (Z \u2192 A) + Data (Nou \u2192 Antic) + Data (Antic \u2192 Nou) + Duració (Curt \u2192 Llarg) + Duration (Llarg \u2192 Curt) diff --git a/core/src/main/res/values-cs-rCZ/strings.xml b/core/src/main/res/values-cs-rCZ/strings.xml index 2032c307c..24479751b 100644 --- a/core/src/main/res/values-cs-rCZ/strings.xml +++ b/core/src/main/res/values-cs-rCZ/strings.xml @@ -266,8 +266,8 @@ Automatické mazání Označit epizody jako poslechnuté i pokud ještě zbývá určitý počet sekund přehrávání do jejich konce Chytré označování jako poslechnuté - Odstranit epizody z fronty při jejich přeskočení - Přeskočení odstraní epizody + Neodstraňovat epizody při jejich přeskočení + Nemazat přeskočené epizody Přehrávání Síť Aktualizovat interval nebo čas v průběhu dne diff --git a/core/src/main/res/values-es/strings.xml b/core/src/main/res/values-es/strings.xml index ec4c73373..bd8abe3a2 100644 --- a/core/src/main/res/values-es/strings.xml +++ b/core/src/main/res/values-es/strings.xml @@ -264,8 +264,8 @@ Eliminar automáticamente Marcar episodios como escuchados incluso si todavía quedan unos segundos por escuchar Marcar como escuchado inteligente - Eliminar episodios de la cola cuando al saltarlos - Saltar elimina el episodio + Conservar episodios al saltarlos + Conservar episodios saltados Reproducción Red Intervalo de actualización u hora del día diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml index b17574401..9b0685d68 100644 --- a/core/src/main/res/values-fr/strings.xml +++ b/core/src/main/res/values-fr/strings.xml @@ -88,7 +88,7 @@ URL du flux - URL ou flux ou site web + URL du flux Ajouter un podcast par son URL Trouver le podcast dans la bibliothèque Vous pouvez chercher de nouveaux podcasts en filtrant par nom, catégorie ou popularité dans la bibliothèque gpodder.net, ou sur l\'iTunes Store. @@ -96,8 +96,8 @@ Marquer tous les épisodes comme lus Tous les épisodes ont été marqués comme lus - Veuillez confirmer que vous voulez bien marquer tous les épisodes comme lus - Veuillez confirmer que vous voulez bien marquer tous les épisode de ce flux comme lus + Confirmer le marquage de tous les épisode comme lus + Confirmer le marquage de tous les épisode de ce flux comme lus Marquer tout les épisodes comme vus Voir les détails Supprimer le podcast @@ -115,8 +115,8 @@ Non joués En pause Joués - Rajouté à la liste - Pas rajouté à la liste + Rajouté à la liste d\'attente + Pas rajouté à la liste d\'attente Téléchargé Non téléchargé Filtré @@ -216,16 +216,16 @@ Veuillez confirmer que vous voulez bien supprimer TOUS les épisodes de la file d\'attente Connecter à Flattr - Appuyez sur le bouton ci-dessous pour vous authentifier. Vous serez envoyés à l\'écran de connexion Flattr dans le navigateur, et il vous sera demandé de donner à AntennaPod la permission de flattr. Une fois ceci fait, vous reviendrez automatiquement à cet écran. + Appuyez sur le bouton ci-dessous pour vous authentifier. Voter navigateur va s\'ouvrir et vous serez envoyés vers l\'écran de connexion Flattr afin de donner à AntennaPod la permission de flattr. Une fois fait, vous reviendrez automatiquement à cet écran. S\'authentifier - Revenir au départ + Retourner à l\'écran d\'accueil L\'authentification a réussi. Vous pouvez maintenant flattr depuis cette application. Aucun jeton Flattr trouvé. Votre compte flattr ne semble pas être connecté à AntennaPod. Cliquer ici pour vous connecter. Votre compte Flattr se semble pas être connecté à AntennaPod. Vous pouvez soit connecter votre compte Flattr à AntennaPod pour pouvoir flattr depuis l\'application, ou vous pouvez aller sur le site de ce que vous voulez flattr. S\'authentifier Action interdite - AntennaPod n\'a pas la permission pour cette action. Il est possible que l\'accès à votre compte depuis AntennaPod ait été révoqué. Vous pouvez vous authentifier à nouveau, ou bien visiter le site à flattr directement. + AntennaPod n\'a pas la permission pour cette action. Il est possible que l\'accès à votre compte depuis AntennaPod ait été révoqué. Vous pouvez vous authentifier à nouveau, ou bien visiter le site à Flattrer directement. Accès révoqué Vous avez révoqué le jeton d\'accès d\'AntennaPod à votre compte. Pour terminer cette opération, vous devez retirer AntennaPod de la liste des applications autorisées sur le site web de Flattr. @@ -238,12 +238,12 @@ En train de Flattrer %s AntennaPod est en train de Flattrer AntennaPod a Flattré - Flattr d\'AntennaPod a échoué + Le Flattr d\'AntennaPod a échoué Obtention de la liste des choses Flattrées Télécharger une extension Extension non installée - Pour pouvoir changer la vitesse de lecture il est nécessaire d\'installer une librairie tierce ou d\'activer le lecteur expérimental Sonic [Android 4.1+].\n\nSélectionnez \"Télécharger une extension\" pour télécharger une extension gratuite depuis le Play Store\n\nLes problèmes concernant les extensions sont de la responsabilité de leur créateur et non d\'AntennaPod. Veillez à notifier le créateur de l\'extension de tout problème. + Pour pouvoir changer la vitesse de lecture il est nécessaire d\'installer une librairie tierce ou d\'activer le lecteur expérimental Sonic [Android 4.1+].\n\nSélectionnez \"Télécharger une extension\" pour télécharger une extension gratuite depuis le Play Store.\n\nLes problème rencontrés avec cette extension ne sont pas de la responsabilité d\'AntennaPod. Veillez à notifier le créateur de l\'extension pour tout problème. Vitesses de lecture Activer Sonic @@ -262,15 +262,15 @@ Après la fin d\'un épisode, passer au suivant Supprimer l\'épisode quand la lecture est finie Suppression automatique - Marquer les épisodes comme lus même s\'il reste encore moins d\'un certain intervalle de temps - Marquer comme lu intelligent + Marquer les épisodes comme lus même s\'il reste encore un certain nombre de secondes à jouer + Marquer comme lu de manière intelligente Garder les épisodes quand ils sont passés Garder les épisodes passés Lecture Réseau - Intervalle de mise à jour ou heure de la journée + Mettre à jour l’intervalle ou l\'heure Indiquer un intervalle ou une heure spécifique de mise à jour des flux - Vous pouvez mettre en place un intervalle comme \"toutes les 2 heures\", une heure précise comme \"7:00\" ou désactiver les mises à jours automatique.\n\nNote: Il est possible qu\'il y ait des délais car les heures mises à jours sont inexactes. + Vous pouvez mettre en place un intervalle comme \"toutes les 2 heures\", une heure précise comme \"7:00\" ou désactiver les mises à jours automatique.\n\nNote: Il est possible qu\'il y ait un délai car l\'heure de mise à jour peut être inexacte. Désactiver Définir intervalle Régler l\'heure @@ -297,7 +297,7 @@ Personnaliser l\'apparence du volet de navigation Changer les éléments du volet de navigation Choisir quels éléments apparaissent dans le volet de navigation - Définir ordre des abonnements + Définir l\'ordre des abonnements Change l\'ordre de vos abonnements Définir le compteur d\'abonnements Changer l\'information affichée par le compteur d\'abonnements @@ -340,8 +340,8 @@ Ajouter de nouveaux épisodes en tête de file Mettre au début de la file d\'attente Désactivé - Taille de la cache d\'image - Taille de l’espace disque pour stocker temporairement les images. + Taille du cache de l\'image + Taille de l’espace de stockage temporaire des images. Expérimental Lecteur multimédia Sonic Utiliser le lecteur multimédia interne Sonic au lieu de Prestissimo @@ -358,7 +358,7 @@ Recherche Trouvé dans le titre - Les fichiers OPML vous permettent de bouger vos podcasts d\'un logiciel à un autre. + Les fichiers OPML vous permettent d\'exporter vos podcasts d\'un logiciel à un autre. Option %1$d Choisir un chemin de fichier spécifique dans le système de fichiers local Utiliser une application tierce comme Dropbox, Google Drive ou votre gestionnaire de fichier favori pour ouvrir un fichier OPML @@ -383,7 +383,7 @@ Définir le minuteur d\'arrêt automatique Désactiver le minuteur d\'arrêt automatique Entrer l\'heure - Arrêt automatique + Minuteur de mise en veille Durée restante :\u0020 Entrée invalide, la durée doit être un nombre entier Quand le minuteur est sur le point de se terminer: @@ -416,7 +416,7 @@ Identifiant Mot de passe Choix de l\'appareil - Créez un nouvel appareil à utiliser pour votre compte gpodder.net ou choisissez un appareil existant : + Créer un nouvel appareil pour votre compte gpodder.net ou choisir un appareil existant : ID de l\'appareil :\u0020 Légende Créer un nouvel appareil @@ -492,7 +492,7 @@ Téléchargés Episodes téléchargés sélectionnés Non téléchargés - Les épisodes non téléchargés ont été sélectioné + Épisodes non téléchargés sélectionnés Trier par ... Titre (A \u2192 Z) Titre (Z \u2192 A) diff --git a/core/src/main/res/values-ja/strings.xml b/core/src/main/res/values-ja/strings.xml index a83b16ab9..f8e01c154 100644 --- a/core/src/main/res/values-ja/strings.xml +++ b/core/src/main/res/values-ja/strings.xml @@ -263,8 +263,8 @@ 自動削除 一定の秒数未満の再生時間がまだ残っている場合でも、エピソードを再生済としてマークします 再生済としてスマートマーク - エピソードをスキップしたときに、エピソードをキューから削除します - スキップでエピソードを削除 + エピソードをスキップした時に残しておきます + エピソードのスキップ時に残す 再生 ネットワーク 間隔または時間を更新 diff --git a/core/src/main/res/values-pt/strings.xml b/core/src/main/res/values-pt/strings.xml index b9752dd49..30fb28918 100644 --- a/core/src/main/res/values-pt/strings.xml +++ b/core/src/main/res/values-pt/strings.xml @@ -57,7 +57,7 @@ Erro Ocorreu um erro: Atualizar - Não existe um cartão SD. Certifique-se que inseriu o cartão corretamente. + Cartão SD não disponível. Certifique-se de que inseriu o cartão corretamente para que a aplicação funcione corretamente. Capítulos Notas Descrição @@ -88,7 +88,7 @@ URL da fonte - URL da fonte ou sítio web + URL da fonte ou do sítio web Adicionar podcast via URL Localizar podcasts no diretório Pode procurar por novos podcasts no gPodder.net e também na loja iTunes. Pode procurar por nome, categoria e popularidade. @@ -264,8 +264,8 @@ Eliminação automática Marcar episódios como reproduzidos mesmo que restem alguns segundos de reprodução Marcar como reproduzido (inteligente) - Remover episódios da fila quando forem ignorados - Remover episódios ao ignorar + Manter episódio mesmo se forem ignorados + Manter episódios ignorados Reprodução Rede Intervalo de atualização ou hora do dia diff --git a/core/src/main/res/values-sv-rSE/strings.xml b/core/src/main/res/values-sv-rSE/strings.xml index 9eabbf0c3..eafe998e0 100644 --- a/core/src/main/res/values-sv-rSE/strings.xml +++ b/core/src/main/res/values-sv-rSE/strings.xml @@ -5,8 +5,11 @@ Flöden Lägg till Podcast PODCASTS + Episoder Nya Episoder Alla Episoder + Alla + Favoriter Ny Väntelista Inställningar @@ -28,6 +31,7 @@ Lådinställningar Sortera efter räknare Sortera alfabetiskt + Sortera efter publiceringsdatum Antal nya och ospelade episoder Antal nya episoder Antal ospelade episoder @@ -68,11 +72,20 @@ Försök igen Inkludera i automatiska nedladdningar Applicera på Föregående Episoder + Den nya inställningen Automatisk Nedladdning kommer automatiskt att appliceras på nya episoder.\nVill du även applicera det på tidigare publicerade episoder? Ta automatiskt bort episod\n(åsidosätter global standardinställning) \u0020parallella nedladdningar Global Alltid Aldrig + Skicka... + Aldrig + Om inte köad + Efter avslutad + + 1 dag efter färdigspelad + %d dagar efter färdigspelad + Flödets URL URL till flöde eller webbsida @@ -122,6 +135,8 @@ Lägg till i kön Lägg till i Kö Ta bort från Kön + Lägg till i Favoriter + Ta bort från Favoriter Besök websidan Flattra det här Lägg till alla i kön @@ -130,6 +145,7 @@ Aktivera Automatisk Nedladdning Avaktivera Automatisk Nedladdning Nollställ Uppspelningspositionen + Borttagen lyckades misslyckades @@ -227,7 +243,9 @@ Ladda ner tillägg Tillägg ej installerat + För att variabel uppspelningshastighet ska funger måste du installera ett tredjepartsbibliotek eller aktivera den experimentella spelaren Sonic [Android 4.1+].\n\nTryck på \'Ladda ner Plugin\' för att ladda ner en gratis plugin från Play Store.\n\nAntennaPod ansvarar inte för eventualla problem som upptäcks vid användning av denna plugin och de bör rapporteras till pluginens ägare. Uppspelningshastigheter + Aktivera Sonic Det finns inget i denna lista. Du har inte prenumererat på något flöde ännu. @@ -237,6 +255,8 @@ Tjänster Flattr + Episodupprensning + Episoder som inte ligger i kön och inte är favoriter bör kunna tas bort om det behövs utrymme Pausa uppspelningen när hörlurarna bortkopplas Fortsätt uppspelningen när hörlurarna återansluts Hoppa till nästa i kön när uppspelningen är klar @@ -244,6 +264,8 @@ Automatisk borttagning Markera episoder som spelade även om mindre än ett visst antal sekunder är kvar Smart markering av uppspelat innehåll + Ta inte bort episoder när de hoppas över + Behåll Överhoppade Episoder Uppspelning Nätverk Uppdateringsintervall eller Tid på Dagen @@ -310,6 +332,8 @@ Expandera alltid notifieringen för att visa uppspelningskontrollerna. Bestående Uppspelningskontroller Behåll notifiering och kontroller på låsskärmen när uppspelningen pausas. + Sätt Låsskärmens Bakgrund + Sätt låsskärmens bakgrund till den spelade episodens bild. En bieffekt är att även tredjepartsappar kan visa bilden. Visa Nedladdningsrapport Visa en rapport med detaljer om felet när nedladdningar misslyckas. Androidversioner före 4.1 har inte stöd för expanderade notifieringar. @@ -318,6 +342,9 @@ Avaktiverad Bildcachestorlek Storleken på bildcachen på disken. + Experimentell + Sonic mediaspelare + Använd inbyggda mediaspelaren Sonic som en ersättning för Prestissimo Aktivera automatisk Flattring Flattra episoden så snart %d procent har spelats @@ -332,6 +359,7 @@ Hittad i titeln OPML-filer låter dig flytta dina podcasts från en podcatcher till en annan. + Val %1$d Välj en specifik sökväg från det lokala filsystemet. Använd en extern applikation som Dropbox, Google Drive eller ditt favoritval av filhanterare för att öppna en OPML fil. Flera applikationer som Google Mail, Dropbox, Google Drive och de flesta filhanterare kan öppna OPML filer med AntennaPod. @@ -358,6 +386,9 @@ Sömntimer Återstående tid:\u0020 Ogiltigt tal, tiden måste vara ett heltal + När timern är nära noll: + Skaka för att återställa + Vibrera sekunder minuter timmar diff --git a/core/src/main/res/values-uk-rUA/strings.xml b/core/src/main/res/values-uk-rUA/strings.xml index bb577baa4..85069cd22 100644 --- a/core/src/main/res/values-uk-rUA/strings.xml +++ b/core/src/main/res/values-uk-rUA/strings.xml @@ -265,8 +265,6 @@ Автовидалення Позначити епізоди як грані навіть якщо залишилось менш ніж зазначене число секунд до кінця відтворення Розумне позначення граних епізодів - Видаляти епізод з черги у разі його пропуска при прослуховуванні - Видалення епізода пропуском Відтворення Мережа Частота оновлень або оновлення в зазначений час -- cgit v1.2.3 From 3cc5eee0ff2d5eb650a71c78235229422322a3a6 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 31 Oct 2015 11:33:10 -0400 Subject: Have a different option for bluetooth reconnect. Vibrate when starting playback due to bluetooth reconnect. fixes AntennaPod/AntennaPod#1305 --- .../core/preferences/UserPreferences.java | 5 +++++ .../core/service/playback/PlaybackService.java | 21 ++++++++++++++++----- core/src/main/res/values/strings.xml | 4 +++- 3 files changed, 24 insertions(+), 6 deletions(-) (limited to 'core/src/main') 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 006c48b26..84e349535 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 @@ -60,6 +60,7 @@ public class UserPreferences { // Playback public static final String PREF_PAUSE_ON_HEADSET_DISCONNECT = "prefPauseOnHeadsetDisconnect"; public static final String PREF_UNPAUSE_ON_HEADSET_RECONNECT = "prefUnpauseOnHeadsetReconnect"; + public static final String PREF_UNPAUSE_ON_BLUETOOTH_RECONNECT = "prefUnpauseOnBluetoothReconnect"; public static final String PREF_FOLLOW_QUEUE = "prefFollowQueue"; public static final String PREF_SKIP_KEEPS_EPISODE = "prefSkipKeepsEpisode"; public static final String PREF_AUTO_DELETE = "prefAutoDelete"; @@ -221,6 +222,10 @@ public class UserPreferences { return prefs.getBoolean(PREF_UNPAUSE_ON_HEADSET_RECONNECT, true); } + public static boolean isUnpauseOnBluetoothReconnect() { + return prefs.getBoolean(PREF_UNPAUSE_ON_BLUETOOTH_RECONNECT, false); + } + public static boolean isFollowQueue() { return prefs.getBoolean(PREF_FOLLOW_QUEUE, true); diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index 5cef2fe79..ab78387a2 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 @@ -18,6 +18,7 @@ import android.media.MediaPlayer; import android.os.Binder; import android.os.Build; import android.os.IBinder; +import android.os.Vibrator; import android.preference.PreferenceManager; import android.support.v4.app.NotificationCompat; import android.util.Log; @@ -531,7 +532,7 @@ public class PlaybackService extends Service { @Override public boolean onMediaPlayerError(Object inObj, int what, int extra) { - final String TAG = "PlaybackService.onErrorListener"; + final String TAG = "PlaybackSvc.onErrorLtsn"; Log.w(TAG, "An error has occured: " + what + " " + extra); if (mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING) { mediaPlayer.pause(true, false); @@ -1022,7 +1023,7 @@ public class PlaybackService extends Service { pauseIfPauseOnDisconnect(); } else if (state == PLUGGED) { Log.d(TAG, "Headset was plugged in during playback."); - unpauseIfPauseOnDisconnect(); + unpauseIfPauseOnDisconnect(false); } } else { Log.e(TAG, "Received invalid ACTION_HEADSET_PLUG intent"); @@ -1038,7 +1039,7 @@ public class PlaybackService extends Service { int state = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, -1); if (state == BluetoothA2dp.STATE_CONNECTED) { Log.d(TAG, "Received bluetooth connection intent"); - unpauseIfPauseOnDisconnect(); + unpauseIfPauseOnDisconnect(true); } } } @@ -1071,10 +1072,20 @@ public class PlaybackService extends Service { } } - private void unpauseIfPauseOnDisconnect() { + /** + * @param bluetooth true if the event for unpausing came from bluetooth + */ + private void unpauseIfPauseOnDisconnect(boolean bluetooth) { if (transientPause) { transientPause = false; - if (UserPreferences.isPauseOnHeadsetDisconnect() && UserPreferences.isUnpauseOnHeadsetReconnect()) { + if (!bluetooth && UserPreferences.isUnpauseOnHeadsetReconnect()) { + mediaPlayer.resume(); + } else if (bluetooth && UserPreferences.isUnpauseOnBluetoothReconnect()){ + // let the user know we've started playback again... + Vibrator v = (Vibrator) getApplicationContext().getSystemService(Context.VIBRATOR_SERVICE); + if(v != null) { + v.vibrate(500); + } mediaPlayer.resume(); } } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index f50f271ed..0a8e95639 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -276,8 +276,9 @@ Flattr Episode Cleanup Episodes that aren\'t in the queue and aren\'t favorites should be eligible for removal if space is needed - Pause playback when the headphones are disconnected + Pause playback when the headphones or Bluetooth are disconnected Resume playback when the headphones are reconnected + Resume playback when bluetooth reconnects Jump to next queue item when playback completes Delete episode when playback completes Auto Delete @@ -298,6 +299,7 @@ WiFi media download Headphones Disconnect Headphones Reconnect + Bluetooth Reconnect Mobile Updates Allow updates over the mobile data connection Refreshing -- cgit v1.2.3 From b77ecd9a4e199e3173407be8c1e9696adfda6b97 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 31 Oct 2015 11:55:07 -0400 Subject: minor string updates --- core/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 0a8e95639..0c56e1d3e 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -276,7 +276,7 @@ Flattr Episode Cleanup Episodes that aren\'t in the queue and aren\'t favorites should be eligible for removal if space is needed - Pause playback when the headphones or Bluetooth are disconnected + Pause playback when headphones or bluetooth are disconnected Resume playback when the headphones are reconnected Resume playback when bluetooth reconnects Jump to next queue item when playback completes -- cgit v1.2.3 From 1c57e36dcb99e8b0989b37e2f665a9ccb7419074 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 1 Nov 2015 12:12:27 +0100 Subject: Fix --- .../antennapod/core/syndication/handler/TypeGetter.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/TypeGetter.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/TypeGetter.java index 32cd538d5..d3be1780d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/TypeGetter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/TypeGetter.java @@ -28,11 +28,13 @@ public class TypeGetter { public Type getType(Feed feed) throws UnsupportedFeedtypeException { XmlPullParserFactory factory; if (feed.getFile_url() != null) { + Reader reader = null; try { factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware(true); XmlPullParser xpp = factory.newPullParser(); - xpp.setInput(createReader(feed)); + reader = createReader(feed); + xpp.setInput(reader); int eventType = xpp.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { @@ -88,6 +90,14 @@ public class TypeGetter { } catch (IOException e) { e.printStackTrace(); + } finally { + if(reader != null) { + try { + reader.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } } } if (BuildConfig.DEBUG) -- cgit v1.2.3 From 7199daf81ae68025170e43dcd6e2258fdd832144 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 1 Nov 2015 12:12:51 +0100 Subject: Minor changes --- .../core/syndication/handler/TypeGetter.java | 26 ++++++++-------------- 1 file changed, 9 insertions(+), 17 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/TypeGetter.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/TypeGetter.java index d3be1780d..4d56e1365 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/TypeGetter.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/handler/TypeGetter.java @@ -1,8 +1,7 @@ package de.danoeh.antennapod.core.syndication.handler; import android.util.Log; -import de.danoeh.antennapod.core.BuildConfig; -import de.danoeh.antennapod.core.feed.Feed; + import org.apache.commons.io.input.XmlStreamReader; import org.jsoup.Jsoup; import org.xmlpull.v1.XmlPullParser; @@ -14,6 +13,8 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.Reader; +import de.danoeh.antennapod.core.feed.Feed; + /** Gets the type of a specific feed by reading the root element. */ public class TypeGetter { private static final String TAG = "TypeGetter"; @@ -42,38 +43,30 @@ public class TypeGetter { String tag = xpp.getName(); if (tag.equals(ATOM_ROOT)) { feed.setType(Feed.TYPE_ATOM1); - if (BuildConfig.DEBUG) - Log.d(TAG, "Recognized type Atom"); + Log.d(TAG, "Recognized type Atom"); return Type.ATOM; } else if (tag.equals(RSS_ROOT)) { - String strVersion = xpp.getAttributeValue(null, - "version"); + String strVersion = xpp.getAttributeValue(null, "version"); if (strVersion != null) { - if (strVersion.equals("2.0")) { feed.setType(Feed.TYPE_RSS2); - if (BuildConfig.DEBUG) - Log.d(TAG, "Recognized type RSS 2.0"); + Log.d(TAG, "Recognized type RSS 2.0"); return Type.RSS20; } else if (strVersion.equals("0.91") || strVersion.equals("0.92")) { - if (BuildConfig.DEBUG) - Log.d(TAG, - "Recognized type RSS 0.91/0.92"); + Log.d(TAG, "Recognized type RSS 0.91/0.92"); return Type.RSS091; } } throw new UnsupportedFeedtypeException(Type.INVALID); } else { - if (BuildConfig.DEBUG) - Log.d(TAG, "Type is invalid"); + Log.d(TAG, "Type is invalid"); throw new UnsupportedFeedtypeException(Type.INVALID, tag); } } else { eventType = xpp.next(); } } - } catch (XmlPullParserException e) { e.printStackTrace(); // XML document might actually be a HTML document -> try to parse as HTML @@ -100,8 +93,7 @@ public class TypeGetter { } } } - if (BuildConfig.DEBUG) - Log.d(TAG, "Type is invalid"); + Log.d(TAG, "Type is invalid"); throw new UnsupportedFeedtypeException(Type.INVALID); } -- cgit v1.2.3 From 7152b0e0ebffc70ce5c7b4cc40ea52902add588e Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 1 Nov 2015 14:33:07 +0100 Subject: Unused parameter --- .../java/de/danoeh/antennapod/core/preferences/UserPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') 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 006c48b26..5df345d62 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 @@ -420,7 +420,7 @@ public class UserPreferences { .apply(); } - public static void setHiddenDrawerItems(Context context, List items) { + public static void setHiddenDrawerItems(List items) { String str = StringUtils.join(items, ','); prefs.edit() .putString(PREF_HIDDEN_DRAWER_ITEMS, str) -- cgit v1.2.3 From 6c81a9fa913f83126659d1587f98a5f73b0bac61 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 1 Nov 2015 14:34:21 +0100 Subject: Don't use ugly callbacks when you have your own reference --- .../de/danoeh/antennapod/core/preferences/UserPreferences.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'core/src/main') 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 5df345d62..b9ce2db31 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 @@ -24,7 +24,6 @@ import java.util.LinkedList; import java.util.List; import java.util.concurrent.TimeUnit; -import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.receiver.FeedUpdateReceiver; import de.danoeh.antennapod.core.storage.APCleanupAlgorithm; @@ -623,8 +622,8 @@ public class UserPreferences { public static void restartUpdateIntervalAlarm(long triggerAtMillis, long intervalMillis) { Log.d(TAG, "Restarting update alarm."); AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - PendingIntent updateIntent = PendingIntent.getBroadcast(context, 0, - new Intent(ClientConfig.applicationCallbacks.getApplicationInstance(), FeedUpdateReceiver.class), 0); + Intent intent = new Intent(context, FeedUpdateReceiver.class); + PendingIntent updateIntent = PendingIntent.getBroadcast(context, 0, intent, 0); alarmManager.cancel(updateIntent); if (intervalMillis > 0) { alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, @@ -643,7 +642,7 @@ public class UserPreferences { Log.d(TAG, "Restarting update alarm."); AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); PendingIntent updateIntent = PendingIntent.getBroadcast(context, 0, - new Intent(ClientConfig.applicationCallbacks.getApplicationInstance(), FeedUpdateReceiver.class), 0); + new Intent(context, FeedUpdateReceiver.class), 0); alarmManager.cancel(updateIntent); Calendar now = Calendar.getInstance(); -- cgit v1.2.3 From d56af7e001f91ac17a320cd0c1b21887932dfb13 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 1 Nov 2015 14:34:44 +0100 Subject: Always use application context --- .../java/de/danoeh/antennapod/core/preferences/UserPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') 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 b9ce2db31..77db541fa 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 @@ -123,7 +123,7 @@ public class UserPreferences { Log.d(TAG, "Creating new instance of UserPreferences"); Validate.notNull(context); - UserPreferences.context = context; + UserPreferences.context = context.getApplicationContext(); UserPreferences.prefs = PreferenceManager.getDefaultSharedPreferences(context); createImportDirectory(); -- cgit v1.2.3 From 63094436b033fcfc104d712cf78cede0380f64e0 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 1 Nov 2015 14:58:19 +0100 Subject: Order feeds case-insensitive --- .../main/java/de/danoeh/antennapod/core/storage/DBReader.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index 7a8609b04..c0a4bcf69 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -950,10 +950,15 @@ public final class DBReader { }; } else if(feedOrder == UserPreferences.FEED_ORDER_ALPHABETICAL) { comparator = (lhs, rhs) -> { - if(lhs.getTitle() == null) { + String t1 = lhs.getTitle(); + String t2 = rhs.getTitle(); + if(t1 == null) { return 1; + } else if(t2 == null) { + return -1; + } else { + return t1.toLowerCase().compareTo(t2.toLowerCase()); } - return lhs.getTitle().compareTo(rhs.getTitle()); }; } else { comparator = (lhs, rhs) -> { -- cgit v1.2.3 From 68e6b2a957bacf6c149b500ed4a1f4a57ec8dc99 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 1 Nov 2015 16:19:34 -0500 Subject: persistent nofication should be the default --- .../java/de/danoeh/antennapod/core/preferences/UserPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main') 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 bd1061fad..d3c4d3ffd 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 @@ -183,7 +183,7 @@ public class UserPreferences { * @return {@code true} if notifications are persistent, {@code false} otherwise */ public static boolean isPersistNotify() { - return prefs.getBoolean(PREF_PERSISTENT_NOTIFICATION, false); + return prefs.getBoolean(PREF_PERSISTENT_NOTIFICATION, true); } /** -- cgit v1.2.3 From 08a3106f1172208daa93078de3e5a35bf59a69fc Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 1 Nov 2015 23:24:55 +0100 Subject: Check for null --- .../core/service/playback/PlaybackServiceTaskManager.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'core/src/main') 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 19ef6ef09..9c3ff4413 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 @@ -366,10 +366,14 @@ public class PlaybackServiceTaskManager { } if (waitingTime <= 0) { Log.d(TAG, "Sleep timer expired"); - shakeListener.pause(); - shakeListener = null; + if(shakeListener != null) { + shakeListener.pause(); + shakeListener = null; + } if (!Thread.currentThread().isInterrupted()) { callback.onSleepTimerExpired(); + } else { + Log.d(TAG, "Sleep timer interrupted"); } } } catch (InterruptedException e) { -- cgit v1.2.3 From 61ed1e8e3417b5a747a1c812af0bbf91f0d6d1a1 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Tue, 3 Nov 2015 13:33:26 +0100 Subject: Prefer iTunes image over everything else --- .../antennapod/core/syndication/namespace/NSITunes.java | 12 ++++++------ .../antennapod/core/syndication/namespace/NSRSS20.java | 16 ++++++++++++---- .../core/syndication/namespace/atom/NSAtom.java | 4 +++- 3 files changed, 21 insertions(+), 11 deletions(-) (limited to 'core/src/main') 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 ff9828eba..6406295c1 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 @@ -1,11 +1,12 @@ package de.danoeh.antennapod.core.syndication.namespace; -import de.danoeh.antennapod.core.feed.FeedImage; -import de.danoeh.antennapod.core.syndication.handler.HandlerState; import org.xml.sax.Attributes; import java.util.concurrent.TimeUnit; +import de.danoeh.antennapod.core.feed.FeedImage; +import de.danoeh.antennapod.core.syndication.handler.HandlerState; + public class NSITunes extends Namespace { public static final String NSTAG = "itunes"; public static final String NSURI = "http://www.itunes.com/dtds/podcast-1.0.dtd"; @@ -34,10 +35,9 @@ public class NSITunes extends Namespace { } else { // this is the feed image - if (state.getFeed().getImage() == null) { - image.setOwner(state.getFeed()); - state.getFeed().setImage(image); - } + // prefer to all other images + image.setOwner(state.getFeed()); + state.getFeed().setImage(image); } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java index 25a57f71b..7e19213be 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/NSRSS20.java @@ -5,6 +5,7 @@ import android.util.Log; import org.xml.sax.Attributes; import de.danoeh.antennapod.core.BuildConfig; +import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; @@ -73,8 +74,11 @@ public class NSRSS20 extends Namespace { if (state.getTagstack().size() >= 1) { String parent = state.getTagstack().peek().getName(); if (parent.equals(CHANNEL)) { - state.getFeed().setImage(new FeedImage()); - state.getFeed().getImage().setOwner(state.getFeed()); + Feed feed = state.getFeed(); + if(feed.getImage() == null) { + feed.setImage(new FeedImage()); + feed.getImage().setOwner(state.getFeed()); + } } } } @@ -126,7 +130,9 @@ public class NSRSS20 extends Namespace { state.getFeed().setTitle(title); } else if (second.equals(IMAGE) && third != null && third.equals(CHANNEL)) { - state.getFeed().getImage().setTitle(title); + if(state.getFeed().getImage().getTitle() == null) { + state.getFeed().getImage().setTitle(title); + } } } else if (top.equals(LINK)) { if (second.equals(CHANNEL)) { @@ -139,7 +145,9 @@ public class NSRSS20 extends Namespace { DateUtils.parse(content)); } else if (top.equals(URL) && second.equals(IMAGE) && third != null && third.equals(CHANNEL)) { - state.getFeed().getImage().setDownload_url(content); + if(state.getFeed().getImage().getDownload_url() == null) { // prefer itunes:image + state.getFeed().getImage().setDownload_url(content); + } } else if (localName.equals(DESCR)) { if (second.equals(CHANNEL)) { state.getFeed().setDescription(content); diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java index abff5b2db..a690e7646 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/NSAtom.java @@ -199,7 +199,9 @@ public class NSAtom extends Namespace { DateUtils.parse(content)); } } else if (top.equals(IMAGE)) { - state.getFeed().setImage(new FeedImage(state.getFeed(), content, null)); + if(state.getFeed().getImage() == null) { + state.getFeed().setImage(new FeedImage(state.getFeed(), content, null)); + } } } -- cgit v1.2.3 From 7c278223a4e4ca4216cea1cbd80893a6a6d850d9 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Tue, 3 Nov 2015 18:56:23 -0500 Subject: updated strings, added description and changelog to source control. --- core/src/main/res/values-az/strings.xml | 1 - core/src/main/res/values-ca/strings.xml | 1 - core/src/main/res/values-cs-rCZ/strings.xml | 4 +++- core/src/main/res/values-da/strings.xml | 1 - core/src/main/res/values-de/strings.xml | 8 +++++--- core/src/main/res/values-es-rES/strings.xml | 1 - core/src/main/res/values-es/strings.xml | 4 +++- core/src/main/res/values-fr/strings.xml | 1 - core/src/main/res/values-hi-rIN/strings.xml | 1 - core/src/main/res/values-it-rIT/strings.xml | 1 - core/src/main/res/values-iw-rIL/strings.xml | 1 - core/src/main/res/values-ja/strings.xml | 1 - core/src/main/res/values-ko/strings.xml | 1 - core/src/main/res/values-nl/strings.xml | 1 - core/src/main/res/values-pl-rPL/strings.xml | 1 - core/src/main/res/values-pt-rBR/strings.xml | 1 - core/src/main/res/values-pt/strings.xml | 4 +++- core/src/main/res/values-ro-rRO/strings.xml | 1 - core/src/main/res/values-ru/strings.xml | 1 - core/src/main/res/values-sv-rSE/strings.xml | 4 +++- core/src/main/res/values-tr/strings.xml | 1 - core/src/main/res/values-uk-rUA/strings.xml | 1 - core/src/main/res/values-zh-rCN/strings.xml | 1 - 23 files changed, 17 insertions(+), 25 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values-az/strings.xml b/core/src/main/res/values-az/strings.xml index 623c308b2..a88776ea3 100644 --- a/core/src/main/res/values-az/strings.xml +++ b/core/src/main/res/values-az/strings.xml @@ -128,7 +128,6 @@ Proqram haqqinda Növbə Flattr - Qulaqliqı ayiranda oynatma dayanacağ Oynatma başa çatanda növbədə irəlidəki epizodu oynat Oynatma Şəbəkə diff --git a/core/src/main/res/values-ca/strings.xml b/core/src/main/res/values-ca/strings.xml index 0352c1ab9..6dbc4d68f 100644 --- a/core/src/main/res/values-ca/strings.xml +++ b/core/src/main/res/values-ca/strings.xml @@ -257,7 +257,6 @@ Flattr Neteja l\'episodi Episodis que no estan a la cua i no són favorits haurien de ser escollits per eliminar-los si es requereix espai - Pausa la reproducció en desconnectar els auriculars. Continua la reproducció en connectar novament els auriculars Salta al següent element de la cua en acabar la reproducció Suprimeix l\'episodi quan s\'acabi de reproduir diff --git a/core/src/main/res/values-cs-rCZ/strings.xml b/core/src/main/res/values-cs-rCZ/strings.xml index 24479751b..143ecd1ef 100644 --- a/core/src/main/res/values-cs-rCZ/strings.xml +++ b/core/src/main/res/values-cs-rCZ/strings.xml @@ -259,8 +259,9 @@ Flattr Vyčistit epizody Epizody které nejsou ve frontě a nejsou označeny jako oblíbené lze smazat pro uvolnění místa - Při odpojení sluchátek pozastavit přehrávání. + Při odpojení sluchátek nebo bluetooth připojení pozastavit přehrávání. Pokračovat v přehrávání po připojení sluchátek + Pokračovat v přehrávání po připojení bluetooth Po přehrání položky z fronty přejít automaticky na další Smazat díl po jeho přehrání Automatické mazání @@ -281,6 +282,7 @@ WiFi stahování Sluchátka odpojena Sluchátka připojena + Bluetooth připojeno Mobilní aktualizace Povolit aktualizace pomocí mobilního připojení Obnovuji diff --git a/core/src/main/res/values-da/strings.xml b/core/src/main/res/values-da/strings.xml index 086e2f4b5..a43b6661b 100644 --- a/core/src/main/res/values-da/strings.xml +++ b/core/src/main/res/values-da/strings.xml @@ -187,7 +187,6 @@ Tjenester Flattr - Sæt afspilning på pause når hovedtelefoner afbrydes Genoptag afspilning når hovedtelefoner tilsluttes igen Hop til næste medie i køen når afspilning er færdig Slet episode når afspilningen er færdig diff --git a/core/src/main/res/values-de/strings.xml b/core/src/main/res/values-de/strings.xml index c984a932d..fbe8dec53 100644 --- a/core/src/main/res/values-de/strings.xml +++ b/core/src/main/res/values-de/strings.xml @@ -257,8 +257,9 @@ Flattr Episodenaufräumer Episoden, die nicht in der Abspielliste und nicht favorisiert sind, werden zum Aufräumen freigegeben, wenn Speicherplatz benötigt wird - Pausiere die Wiedergabe, wenn der Kopfhörer entfernt worden ist. - Wiedergabe fortsetzen, wenn Kopfhörer wieder reingesteckt werden + Wiedergabe pausieren, wenn Kopfhörer ausgesteckt oder Bluetooth getrennt wird + Wiedergabe fortsetzen, wenn Kopfhörer wieder eingesteckt werden + Wiedergabe fortsetzen, wenn Bluetooth wieder verbunden ist Springe zur nächsten Episode, wenn die vorherige Episode endet Episode löschen, wenn die Wiedergabe endet Automatisches Löschen @@ -279,6 +280,7 @@ WiFi Medien-Download Kopfhörer-Trennung Kopfhörer wieder eingesteckt + Bluetooth wieder verbunden Mobile Aktualisierungen Erlaube Aktualisierungen über die mobile Datenverbindung Aktualisiere @@ -444,7 +446,7 @@ Ordner ist nicht leer Der ausgewählte Ordner ist nicht leer. Medien-Downloads und andere Daten werden direkt in diesem Ordner gespeichert. Trotzdem fortfahren? Standardordner auswählen - Pausiere die Wiedergabe statt die Lautstärke zu reduzieren, wenn eine andere Anwendung Töne abspielt + Wiedergabe pausieren statt die Lautstärke zu reduzieren, wenn eine andere Anwendung Töne abspielt Bei Unterbrechungen pausieren Wiedergabe fortsetzen, wenn Anruf beendet ist Nach Anruf fortsetzen diff --git a/core/src/main/res/values-es-rES/strings.xml b/core/src/main/res/values-es-rES/strings.xml index cff89d3a7..2757d7eac 100644 --- a/core/src/main/res/values-es-rES/strings.xml +++ b/core/src/main/res/values-es-rES/strings.xml @@ -119,7 +119,6 @@ Otros Acerca de Cola - Pausar la reproducción al desconectar los auriculares Saltar al siguiente elemento de la cola al acabar la reproducción Reproducción Red diff --git a/core/src/main/res/values-es/strings.xml b/core/src/main/res/values-es/strings.xml index bd8abe3a2..e8a885817 100644 --- a/core/src/main/res/values-es/strings.xml +++ b/core/src/main/res/values-es/strings.xml @@ -257,8 +257,9 @@ Flattr Limpieza de episodios Los episodios que no están en la cola ni son favoritos serían candidatos a eliminarse si hace falta espacio - Pausar la reproducción al desconectar los auriculares + Pausar la reproducción al desconectar los auriculares o el bluetooth Reanudar reproducción cuando se reconecten los auriculares + Reanudar reproducción cuando se reconecte el bluetooth Saltar al siguiente elemento de la cola al acabar la reproducción Borrar episodio cuando finalice la reproducción Eliminar automáticamente @@ -279,6 +280,7 @@ Descarga de contenidos por WiFi Desconexión de los cascos Reconectar auriculares + Reconectar Bluetooth Actualizaciones por red móvil Permitir actualizaciones por red de datos móvil Actualizando diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml index 9b0685d68..2d025239f 100644 --- a/core/src/main/res/values-fr/strings.xml +++ b/core/src/main/res/values-fr/strings.xml @@ -257,7 +257,6 @@ Flattr Nettoyage des épisodes Les épisodes qui ne sont ni dans la liste ni dans les favoris peuvent être supprimés si l\'espace disque devient faible - Interrompre la lecture lorsque le casque est débranché Reprendre la lecture quand les écouteurs sont reconnectés Après la fin d\'un épisode, passer au suivant Supprimer l\'épisode quand la lecture est finie diff --git a/core/src/main/res/values-hi-rIN/strings.xml b/core/src/main/res/values-hi-rIN/strings.xml index a47178f60..1ac70679a 100644 --- a/core/src/main/res/values-hi-rIN/strings.xml +++ b/core/src/main/res/values-hi-rIN/strings.xml @@ -152,7 +152,6 @@ पंक्ति सेवाएं Flattr - प्लेबैक रोकें जब हेडफोन काट रहे हैं प्लेबैक के पूरा होने पर अगली पंक्ति आइटम के लिए जाएँ प्लेबैक संजाल diff --git a/core/src/main/res/values-it-rIT/strings.xml b/core/src/main/res/values-it-rIT/strings.xml index ba4ad9e38..4e052037c 100644 --- a/core/src/main/res/values-it-rIT/strings.xml +++ b/core/src/main/res/values-it-rIT/strings.xml @@ -239,7 +239,6 @@ Coda Servizi Flattr - Metti in pausa quanto le cuffie vengono disconnesse Riprendi la riproduzione quando vengono riconnesse le cuffie Passa al prossimo episodio in coda quanto si completa una riproduzione Elimina l\'episodio quando viene completata la riproduzione diff --git a/core/src/main/res/values-iw-rIL/strings.xml b/core/src/main/res/values-iw-rIL/strings.xml index 9f6b85c29..a84de71d4 100644 --- a/core/src/main/res/values-iw-rIL/strings.xml +++ b/core/src/main/res/values-iw-rIL/strings.xml @@ -204,7 +204,6 @@ תור שירותים Flattr - השהה השמעה בניתוק האוזניות המשך את הניגון כשהאוזניות מחוברות מחדש עבור לפריט הבא בתור כאשר הניגון מסתיים מחק פרק כהניגון מסתיים diff --git a/core/src/main/res/values-ja/strings.xml b/core/src/main/res/values-ja/strings.xml index f8e01c154..0d234da27 100644 --- a/core/src/main/res/values-ja/strings.xml +++ b/core/src/main/res/values-ja/strings.xml @@ -256,7 +256,6 @@ Flattr エピソード クリーンアップ 空き容量が必要な場合、キューに含まれていおらず、お気に入りでもないエピソードは、削除の対象になります - ヘッドフォンの接続が切断された時、再生を一時停止します ヘッドフォンが再接続された時に再生を再開します 再生が完了した時に次のキューのアイテムに移動します 再生が完了した時にエピソードを削除します diff --git a/core/src/main/res/values-ko/strings.xml b/core/src/main/res/values-ko/strings.xml index 38b2fa3be..606c849fc 100644 --- a/core/src/main/res/values-ko/strings.xml +++ b/core/src/main/res/values-ko/strings.xml @@ -237,7 +237,6 @@ 대기열 서비스 Flattr - 헤드폰의 연결이 끊어졌을 때 재생을 일시 중지 헤드폰 다시 연결할 때 재생 계속 재생을 마쳤을 때 다음 대기열로 이동 재생이 끝나면 에피소드 삭제 diff --git a/core/src/main/res/values-nl/strings.xml b/core/src/main/res/values-nl/strings.xml index 86c1399cf..b2da5ac89 100644 --- a/core/src/main/res/values-nl/strings.xml +++ b/core/src/main/res/values-nl/strings.xml @@ -257,7 +257,6 @@ Flattr Automatisch opschonen Afleveringen die niet in de wachtrij staan en niet zijn gemarkeerd zijn als favoriet, komen in aanmerking voor verwijdering bij automatisch opschonen. - Afspelen pauzeren wanneer de koptelefoon wordt losgekoppeld Afspelen hervatten wanneer de koptelefoon opnieuw wordt aangesloten Volgende item in de wachtrij afspelen als de aflevering voltooid is Afleveringen verwijderen als ze zijn afgespeeld diff --git a/core/src/main/res/values-pl-rPL/strings.xml b/core/src/main/res/values-pl-rPL/strings.xml index f61dd7c07..d94845fce 100644 --- a/core/src/main/res/values-pl-rPL/strings.xml +++ b/core/src/main/res/values-pl-rPL/strings.xml @@ -187,7 +187,6 @@ Kolejka Usługi Flattr - Wstrzymaj odtwarzanie kiedy słuchawki zostaną odłączone Wznów odtwarzanie kiedy słuchawki zostaną podłączone ponownie Przeskocz do następnego elementu kolejki po zakończeniu odtwarzania Usuń odcinek kiedy jego odtwarzanie zostanie zakończone diff --git a/core/src/main/res/values-pt-rBR/strings.xml b/core/src/main/res/values-pt-rBR/strings.xml index 63c3ffb18..1a9c0e6d0 100644 --- a/core/src/main/res/values-pt-rBR/strings.xml +++ b/core/src/main/res/values-pt-rBR/strings.xml @@ -185,7 +185,6 @@ Fila Serviços Flattr - Interromper a reprodução quando o fone de ouvido for desconectado Pular para próximo item da fila quando a reprodução terminar Reprodução Rede diff --git a/core/src/main/res/values-pt/strings.xml b/core/src/main/res/values-pt/strings.xml index 30fb28918..731c92e1a 100644 --- a/core/src/main/res/values-pt/strings.xml +++ b/core/src/main/res/values-pt/strings.xml @@ -257,8 +257,9 @@ Flattr Limpeza de episódios Os episódios que não estiverem na fila ou que não sejam favoritos são elegiveis para remoção se necessitar de espaço - Pausa na reprodução ao remover os auscultadores + Pausa na reprodução ao desligar os auscultadores ou o bluetooth Continuar reprodução ao ligar os auscultadores + Continuar reprodução ao estabelecer a ligação bluetooth Ir para a faixa seguinte ao terminar a reprodução Apagar episódio ao terminar a reprodução Eliminação automática @@ -279,6 +280,7 @@ Transferir por Wi-Fi Auscultadores removidos Auscultadores inseridos + Ligação bluetooth Atualizações móveis Permitir atualizações através da rede de dados móveis A atualizar diff --git a/core/src/main/res/values-ro-rRO/strings.xml b/core/src/main/res/values-ro-rRO/strings.xml index 620336586..973a737d2 100644 --- a/core/src/main/res/values-ro-rRO/strings.xml +++ b/core/src/main/res/values-ro-rRO/strings.xml @@ -134,7 +134,6 @@ Coadă Servicii Flattr - Pune pauză când căștile sunt deconectate Sari la următorul element din coadă cand se termină ascultarea Ascultare Rețea diff --git a/core/src/main/res/values-ru/strings.xml b/core/src/main/res/values-ru/strings.xml index 21d4dc2f7..cf7129b18 100644 --- a/core/src/main/res/values-ru/strings.xml +++ b/core/src/main/res/values-ru/strings.xml @@ -204,7 +204,6 @@ Очередь Сервисы Flattr - Приостановить воспроизведение, когда наушники отсоединены Продолжать воспроизведение после подключения наушников После завершения воспроизведения перейти к следующему в очереди Удалять эпизод после завершения воспроизведения diff --git a/core/src/main/res/values-sv-rSE/strings.xml b/core/src/main/res/values-sv-rSE/strings.xml index eafe998e0..b88a473c0 100644 --- a/core/src/main/res/values-sv-rSE/strings.xml +++ b/core/src/main/res/values-sv-rSE/strings.xml @@ -257,8 +257,9 @@ Flattr Episodupprensning Episoder som inte ligger i kön och inte är favoriter bör kunna tas bort om det behövs utrymme - Pausa uppspelningen när hörlurarna bortkopplas + Pausa uppspelningen när hörlurar eller bluetooth kopplas ifrån. Fortsätt uppspelningen när hörlurarna återansluts + Fortsätt uppspelningen när bluetooth återansluts Hoppa till nästa i kön när uppspelningen är klar Ta bort episoden när uppspelningen är klar Automatisk borttagning @@ -279,6 +280,7 @@ WiFi nedladdning Hörlurar Bortkopplade Hörlurar Återanslutna + Bluetooth återansluts Mobila Uppdateringar Tillåt uppdateringar via mobil dataanslutning Uppdaterar diff --git a/core/src/main/res/values-tr/strings.xml b/core/src/main/res/values-tr/strings.xml index deaa63080..5de69d11c 100644 --- a/core/src/main/res/values-tr/strings.xml +++ b/core/src/main/res/values-tr/strings.xml @@ -237,7 +237,6 @@ Kuyruk Servisler Flattr - Kulaklıklar çıkarıldığında çalmayı duraklat Kulaklıklar yeniden bağlandığında çalmaya devam et Çalma tamamlandığında kuyruktaki diğer öğeye geç Çalma bittiğinde bölümü sil diff --git a/core/src/main/res/values-uk-rUA/strings.xml b/core/src/main/res/values-uk-rUA/strings.xml index 85069cd22..bbee32385 100644 --- a/core/src/main/res/values-uk-rUA/strings.xml +++ b/core/src/main/res/values-uk-rUA/strings.xml @@ -258,7 +258,6 @@ Flattr Чищення епізодів У разі нестачі пам\'яті видалять епізоди які не знаходяться ні в списку улюблених ні в черзі. - Зупинятись коли навушники витягнуті Поновити відтворення коли навушники повторно під’єднано Перейти до наступного епізода в черзі коли поточний закінчено Видалити епізод після повного відтворення diff --git a/core/src/main/res/values-zh-rCN/strings.xml b/core/src/main/res/values-zh-rCN/strings.xml index 4c36ac734..8ef0eaec7 100644 --- a/core/src/main/res/values-zh-rCN/strings.xml +++ b/core/src/main/res/values-zh-rCN/strings.xml @@ -230,7 +230,6 @@ 播放列表 服务 Flattr - 耳机断开时暂停播放 当耳机重新连接时恢复播放 播放完成跳转到播放列表下一项 当播放完成后删除曲目 -- cgit v1.2.3 From d2717979be400e927a21edc0d7327bc1d9567571 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Thu, 5 Nov 2015 16:59:57 -0500 Subject: sort favorites by publication date --- .../src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'core/src/main') 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 7d1afc039..6ccb1d226 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 @@ -1052,8 +1052,8 @@ public class PodDBAdapter { TABLE_NAME_FEED_ITEMS, TABLE_NAME_FAVORITES, TABLE_NAME_FEED_ITEMS + "." + KEY_ID, TABLE_NAME_FAVORITES + "." + KEY_FEEDITEM, - TABLE_NAME_FAVORITES + "." + KEY_ID }; - String query = String.format("SELECT %s FROM %s INNER JOIN %s ON %s=%s ORDER BY %s", args); + TABLE_NAME_FEED_ITEMS + "." + KEY_PUBDATE }; + String query = String.format("SELECT %s FROM %s INNER JOIN %s ON %s=%s ORDER BY %s DESC", args); Cursor c = db.rawQuery(query, null); return c; } -- cgit v1.2.3 From 67d2287323260e0bcbfcd644a33da5402c29b383 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 5 Nov 2015 17:12:18 +0100 Subject: Queue: Replace DSVL with RecyclerView --- .../main/java/de/danoeh/antennapod/core/util/LongList.java | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/LongList.java b/core/src/main/java/de/danoeh/antennapod/core/util/LongList.java index 8934f3272..10ffd4bec 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/LongList.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/LongList.java @@ -30,6 +30,17 @@ public final class LongList { size = 0; } + public static LongList of(long... values) { + if(values == null || values.length == 0) { + return new LongList(0); + } + LongList result = new LongList(values.length); + for(long value : values) { + result.add(value); + } + return result; + } + @Override public int hashCode() { int hashCode = 1; -- cgit v1.2.3 From 383449e0078317b3fe179dec76964767e5c1f8e3 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 5 Nov 2015 17:13:16 +0100 Subject: Refactor events --- .../antennapod/core/event/FeedItemEvent.java | 43 +++++++ .../antennapod/core/event/FeedMediaEvent.java | 1 - .../danoeh/antennapod/core/event/QueueEvent.java | 46 +++++--- .../danoeh/antennapod/core/storage/DBWriter.java | 33 ++++-- .../danoeh/antennapod/core/util/FeedItemUtil.java | 68 +++++++++++ .../core/util/gui/UndoBarController.java | 127 --------------------- 6 files changed, 164 insertions(+), 154 deletions(-) create mode 100644 core/src/main/java/de/danoeh/antennapod/core/event/FeedItemEvent.java create mode 100644 core/src/main/java/de/danoeh/antennapod/core/util/FeedItemUtil.java delete mode 100644 core/src/main/java/de/danoeh/antennapod/core/util/gui/UndoBarController.java (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/FeedItemEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/FeedItemEvent.java new file mode 100644 index 000000000..a4a79187e --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/event/FeedItemEvent.java @@ -0,0 +1,43 @@ +package de.danoeh.antennapod.core.event; + + +import android.support.annotation.NonNull; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +import java.util.List; + +import de.danoeh.antennapod.core.feed.FeedItem; + +public class FeedItemEvent { + + public enum Action { + UPDATE, DELETE_MEDIA + } + + @NonNull public final Action action; + @NonNull public final List items; + + private FeedItemEvent(Action action, List items) { + this.action = action; + this.items = items; + } + + public static FeedItemEvent deletedMedia(List items) { + return new FeedItemEvent(Action.DELETE_MEDIA, items); + } + + public static FeedItemEvent updated(List items) { + return new FeedItemEvent(Action.UPDATE, items); + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) + .append("action", action) + .append("items", items) + .toString(); + } + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java index 94e186b7a..864d0a405 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java +++ b/core/src/main/java/de/danoeh/antennapod/core/event/FeedMediaEvent.java @@ -20,5 +20,4 @@ public class FeedMediaEvent { return new FeedMediaEvent(Action.UPDATE, media); } - } diff --git a/core/src/main/java/de/danoeh/antennapod/core/event/QueueEvent.java b/core/src/main/java/de/danoeh/antennapod/core/event/QueueEvent.java index 4992252d1..a84e8456f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/event/QueueEvent.java +++ b/core/src/main/java/de/danoeh/antennapod/core/event/QueueEvent.java @@ -1,5 +1,7 @@ package de.danoeh.antennapod.core.event; +import android.support.annotation.Nullable; + import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; @@ -10,7 +12,7 @@ import de.danoeh.antennapod.core.feed.FeedItem; public class QueueEvent { public enum Action { - ADDED, ADDED_ITEMS, REMOVED, IRREVERSIBLE_REMOVED, CLEARED, DELETED_MEDIA, SORTED, MOVED + ADDED, ADDED_ITEMS, SET_QUEUE, REMOVED, IRREVERSIBLE_REMOVED, CLEARED, DELETED_MEDIA, SORTED, MOVED } public final Action action; @@ -18,27 +20,43 @@ public class QueueEvent { public final int position; public final List items; - public QueueEvent(Action action) { - this(action, null, null, -1); + + private QueueEvent(Action action, + @Nullable FeedItem item, + @Nullable List items, + int position) { + this.action = action; + this.item = item; + this.items = items; + this.position = position; } - public QueueEvent(Action action, FeedItem item) { - this(action, item, null, -1); + public static QueueEvent added(FeedItem item, int position) { + return new QueueEvent(Action.ADDED, item, null, position); } - public QueueEvent(Action action, FeedItem item, int position) { - this(action, item, null, position); + public static QueueEvent setQueue(List queue) { + return new QueueEvent(Action.SET_QUEUE, null, queue, -1); } - public QueueEvent(Action action, List items) { - this(action, null, items, -1); + public static QueueEvent removed(FeedItem item) { + return new QueueEvent(Action.REMOVED, item, null, -1); } - private QueueEvent(Action action, FeedItem item, List items, int position) { - this.action = action; - this.item = item; - this.items = items; - this.position = position; + public static QueueEvent irreversibleRemoved(FeedItem item) { + return new QueueEvent(Action.IRREVERSIBLE_REMOVED, item, null, -1); + } + + public static QueueEvent cleared() { + return new QueueEvent(Action.CLEARED, null, null, -1); + } + + public static QueueEvent sorted(List sortedQueue) { + return new QueueEvent(Action.SORTED, null, sortedQueue, -1); + } + + public static QueueEvent moved(FeedItem item, int newPosition) { + return new QueueEvent(Action.MOVED, item, null, newPosition); } public boolean contains(long id) { 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 73584c40a..14683506e 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 @@ -14,6 +14,7 @@ import java.io.File; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Date; @@ -27,6 +28,8 @@ import de.danoeh.antennapod.core.BuildConfig; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.asynctask.FlattrClickWorker; import de.danoeh.antennapod.core.event.FavoritesEvent; +import de.danoeh.antennapod.core.event.FeedItemEvent; +import de.danoeh.antennapod.core.event.QueueEvent; import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedEvent; @@ -34,7 +37,6 @@ import de.danoeh.antennapod.core.feed.FeedImage; import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedMedia; import de.danoeh.antennapod.core.feed.FeedPreferences; -import de.danoeh.antennapod.core.event.QueueEvent; import de.danoeh.antennapod.core.gpoddernet.model.GpodnetEpisodeAction; import de.danoeh.antennapod.core.preferences.GpodnetPreferences; import de.danoeh.antennapod.core.preferences.PlaybackPreferences; @@ -131,7 +133,7 @@ public class DBWriter { } } Log.d(TAG, "Deleting File. Result: " + result); - EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.DELETED_MEDIA, media.getItem())); + EventBus.getDefault().post(FeedItemEvent.deletedMedia(Arrays.asList(media.getItem()))); EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); } }); @@ -210,8 +212,9 @@ public class DBWriter { adapter.open(); if (removed.size() > 0) { adapter.setQueue(queue); - EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.IRREVERSIBLE_REMOVED, - removed)); + for(FeedItem item : removed) { + EventBus.getDefault().post(QueueEvent.irreversibleRemoved(item)); + } } adapter.removeFeed(feed); adapter.close(); @@ -319,7 +322,7 @@ public class DBWriter { queue.add(index, item); adapter.setQueue(queue); item.addTag(FeedItem.TAG_QUEUE); - EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED, item, index)); + EventBus.getDefault().post(QueueEvent.added(item, index)); if (item.isNew()) { DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId()); } @@ -365,17 +368,21 @@ public class DBWriter { if (queue != null) { boolean queueModified = false; LongList markAsUnplayedIds = new LongList(); + List events = new ArrayList(); for (int i = 0; i < itemIds.length; i++) { if (!itemListContains(queue, itemIds[i])) { final FeedItem item = DBReader.getFeedItem(itemIds[i]); + if (item != null) { // add item to either front ot back of queue boolean addToFront = UserPreferences.enqueueAtFront(); if (addToFront) { queue.add(0 + i, item); + events.add(QueueEvent.added(item, 0 + i)); } else { queue.add(item); + events.add(QueueEvent.added(item, queue.size()-1)); } queueModified = true; if (item.isNew()) { @@ -386,7 +393,9 @@ public class DBWriter { } if (queueModified) { adapter.setQueue(queue); - EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.ADDED_ITEMS, queue)); + for(QueueEvent event : events) { + EventBus.getDefault().post(event); + } if (markAsUnplayedIds.size() > 0) { DBWriter.markItemPlayed(FeedItem.UNPLAYED, markAsUnplayedIds.toArray()); } @@ -411,7 +420,7 @@ public class DBWriter { adapter.clearQueue(); adapter.close(); - EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.CLEARED)); + EventBus.getDefault().post(QueueEvent.cleared()); }); } @@ -435,7 +444,7 @@ public class DBWriter { queue.remove(position); adapter.setQueue(queue); item.removeTag(FeedItem.TAG_QUEUE); - EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.REMOVED, item, position)); + EventBus.getDefault().post(QueueEvent.removed(item)); } else { Log.w(TAG, "Queue was not modified by call to removeQueueItem"); } @@ -512,9 +521,9 @@ public class DBWriter { return dbExec.submit(() -> { LongList queueIdList = DBReader.getQueueIDList(); int index = queueIdList.indexOf(itemId); - if(index >= 0) { + if (index >= 0) { moveQueueItemHelper(index, queueIdList.size() - 1, - broadcastUpdate); + broadcastUpdate); } else { Log.e(TAG, "moveQueueItemToBottom: item not found"); } @@ -561,7 +570,7 @@ public class DBWriter { adapter.setQueue(queue); if (broadcastUpdate) { - EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.MOVED, item, to)); + EventBus.getDefault().post(QueueEvent.moved(item, to)); } } } else { @@ -955,7 +964,7 @@ public class DBWriter { Collections.sort(queue, comparator); adapter.setQueue(queue); if (broadcastUpdate) { - EventBus.getDefault().post(new QueueEvent(QueueEvent.Action.SORTED)); + EventBus.getDefault().post(QueueEvent.sorted(queue)); } } else { Log.e(TAG, "sortQueue: Could not load queue"); diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/FeedItemUtil.java b/core/src/main/java/de/danoeh/antennapod/core/util/FeedItemUtil.java new file mode 100644 index 000000000..3817d3361 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/util/FeedItemUtil.java @@ -0,0 +1,68 @@ +package de.danoeh.antennapod.core.util; + +import java.util.List; + +import de.danoeh.antennapod.core.feed.FeedItem; + +public class FeedItemUtil { + + public static int indexOfItemWithDownloadUrl(List items, String downloadUrl) { + if(items == null) { + return -1; + } + for(int i=0; i < items.size(); i++) { + FeedItem item = items.get(i); + if(item.hasMedia() && item.getMedia().getDownload_url().equals(downloadUrl)) { + return i; + } + } + return -1; + } + + public static int indexOfItemWithId(List items, long id) { + for(int i=0; i < items.size(); i++) { + FeedItem item = items.get(i); + if(item != null && item.getId() == id) { + return i; + } + } + return -1; + } + + public static long[] getIds(FeedItem... items) { + if(items == null || items.length == 0) { + return new long[0]; + } + long[] result = new long[items.length]; + for(int i=0; i < items.length; i++) { + result[i] = items[i].getId(); + } + return result; + } + + public static long[] getIds(List items) { + if(items == null || items.size() == 0) { + return new long[0]; + } + long[] result = new long[items.size()]; + for(int i=0; i < items.size(); i++) { + result[i] = items.get(i).getId(); + } + return result; + } + + public static boolean containsAnyId(List items, long[] ids) { + if(items == null || items.size() == 0) { + return false; + } + for(FeedItem item : items) { + for(long id : ids) { + if(item.getId() == id) { + return true; + } + } + } + return false; + } + +} diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/gui/UndoBarController.java b/core/src/main/java/de/danoeh/antennapod/core/util/gui/UndoBarController.java deleted file mode 100644 index 5eaff6069..000000000 --- a/core/src/main/java/de/danoeh/antennapod/core/util/gui/UndoBarController.java +++ /dev/null @@ -1,127 +0,0 @@ -package de.danoeh.antennapod.core.util.gui; - -import android.os.Handler; -import android.view.View; -import android.widget.TextView; - -import com.nineoldandroids.animation.Animator; -import com.nineoldandroids.animation.AnimatorListenerAdapter; -import com.nineoldandroids.view.ViewHelper; -import com.nineoldandroids.view.ViewPropertyAnimator; - -import de.danoeh.antennapod.core.R; - -import static com.nineoldandroids.view.ViewPropertyAnimator.animate; - -public class UndoBarController { - private View mBarView; - private TextView mMessageView; - private ViewPropertyAnimator mBarAnimator; - private Handler mHideHandler = new Handler(); - - private UndoListener mUndoListener; - - // State objects - private T mUndoToken; - private CharSequence mUndoMessage; - - public interface UndoListener { - /** - * This callback function is called when the undo button is pressed - * - * @param token - */ - void onUndo(T token); - - /** - * - * This callback function is called when the bar fades out without button press - * - * @param token - */ - void onHide(T token); - } - - public UndoBarController(View undoBarView, UndoListener undoListener) { - mBarView = undoBarView; - mBarAnimator = animate(mBarView); - mUndoListener = undoListener; - - mMessageView = (TextView) mBarView.findViewById(R.id.undobar_message); - mBarView.findViewById(R.id.undobar_button) - .setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - hideUndoBar(false); - mUndoListener.onUndo(mUndoToken); - } - }); - - hideUndoBar(true); - } - - public void showUndoBar(boolean immediate, CharSequence message, T undoToken) { - mUndoToken = undoToken; - mUndoMessage = message; - mMessageView.setText(mUndoMessage); - - mHideHandler.removeCallbacks(mHideRunnable); - mHideHandler.postDelayed(mHideRunnable, - mBarView.getResources().getInteger(R.integer.undobar_hide_delay)); - - mBarView.setVisibility(View.VISIBLE); - if (immediate) { - ViewHelper.setAlpha(mBarView, 1); - } else { - mBarAnimator.cancel(); - mBarAnimator - .alpha(1) - .setDuration( - mBarView.getResources() - .getInteger(android.R.integer.config_shortAnimTime)) - .setListener(null); - } - } - - public boolean isShowing() { - return mBarView.getVisibility() == View.VISIBLE; - } - - public void close() { - hideUndoBar(true); - if(mUndoListener != null) { - mUndoListener.onHide(mUndoToken); - } - } - - public void hideUndoBar(boolean immediate) { - mHideHandler.removeCallbacks(mHideRunnable); - if (immediate) { - mBarView.setVisibility(View.GONE); - ViewHelper.setAlpha(mBarView, 0); - mUndoMessage = null; - } else { - mBarAnimator.cancel(); - mBarAnimator - .alpha(0) - .setDuration(mBarView.getResources() - .getInteger(android.R.integer.config_shortAnimTime)) - .setListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mBarView.setVisibility(View.GONE); - mUndoMessage = null; - mUndoToken = null; - } - }); - } - } - - private Runnable mHideRunnable = new Runnable() { - @Override - public void run() { - hideUndoBar(false); - mUndoListener.onHide(mUndoToken); - } - }; -} -- cgit v1.2.3 From 32a47d0f652a579007a9035a0c4ffe5aeeebdd31 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 5 Nov 2015 23:45:23 +0100 Subject: New drag handle --- core/src/main/res/drawable-hdpi/ic_drag_handle.9.png | Bin 268 -> 0 bytes core/src/main/res/drawable-hdpi/ic_drag_handle_dark.9.png | Bin 244 -> 0 bytes .../res/drawable-hdpi/ic_drag_vertical_grey600_48dp.png | Bin 0 -> 246 bytes .../res/drawable-hdpi/ic_drag_vertical_white_48dp.png | Bin 0 -> 242 bytes core/src/main/res/drawable-mdpi/ic_drag_handle.9.png | Bin 217 -> 0 bytes core/src/main/res/drawable-mdpi/ic_drag_handle_dark.9.png | Bin 188 -> 0 bytes .../res/drawable-mdpi/ic_drag_vertical_grey600_48dp.png | Bin 0 -> 197 bytes .../res/drawable-mdpi/ic_drag_vertical_white_48dp.png | Bin 0 -> 193 bytes core/src/main/res/drawable-xhdpi/ic_drag_handle.9.png | Bin 318 -> 0 bytes .../src/main/res/drawable-xhdpi/ic_drag_handle_dark.9.png | Bin 297 -> 0 bytes .../res/drawable-xhdpi/ic_drag_vertical_grey600_48dp.png | Bin 0 -> 291 bytes .../res/drawable-xhdpi/ic_drag_vertical_white_48dp.png | Bin 0 -> 286 bytes core/src/main/res/drawable-xxhdpi/ic_drag_handle.9.png | Bin 410 -> 0 bytes .../main/res/drawable-xxhdpi/ic_drag_handle_dark.9.png | Bin 380 -> 0 bytes .../res/drawable-xxhdpi/ic_drag_vertical_grey600_48dp.png | Bin 0 -> 389 bytes .../res/drawable-xxhdpi/ic_drag_vertical_white_48dp.png | Bin 0 -> 386 bytes .../drawable-xxxhdpi/ic_drag_vertical_grey600_48dp.png | Bin 0 -> 501 bytes .../res/drawable-xxxhdpi/ic_drag_vertical_white_48dp.png | Bin 0 -> 498 bytes core/src/main/res/values/styles.xml | 8 ++++---- 19 files changed, 4 insertions(+), 4 deletions(-) delete mode 100644 core/src/main/res/drawable-hdpi/ic_drag_handle.9.png delete mode 100644 core/src/main/res/drawable-hdpi/ic_drag_handle_dark.9.png create mode 100644 core/src/main/res/drawable-hdpi/ic_drag_vertical_grey600_48dp.png create mode 100644 core/src/main/res/drawable-hdpi/ic_drag_vertical_white_48dp.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_drag_handle.9.png delete mode 100644 core/src/main/res/drawable-mdpi/ic_drag_handle_dark.9.png create mode 100644 core/src/main/res/drawable-mdpi/ic_drag_vertical_grey600_48dp.png create mode 100644 core/src/main/res/drawable-mdpi/ic_drag_vertical_white_48dp.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_drag_handle.9.png delete mode 100644 core/src/main/res/drawable-xhdpi/ic_drag_handle_dark.9.png create mode 100644 core/src/main/res/drawable-xhdpi/ic_drag_vertical_grey600_48dp.png create mode 100644 core/src/main/res/drawable-xhdpi/ic_drag_vertical_white_48dp.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_drag_handle.9.png delete mode 100644 core/src/main/res/drawable-xxhdpi/ic_drag_handle_dark.9.png create mode 100644 core/src/main/res/drawable-xxhdpi/ic_drag_vertical_grey600_48dp.png create mode 100644 core/src/main/res/drawable-xxhdpi/ic_drag_vertical_white_48dp.png create mode 100644 core/src/main/res/drawable-xxxhdpi/ic_drag_vertical_grey600_48dp.png create mode 100644 core/src/main/res/drawable-xxxhdpi/ic_drag_vertical_white_48dp.png (limited to 'core/src/main') diff --git a/core/src/main/res/drawable-hdpi/ic_drag_handle.9.png b/core/src/main/res/drawable-hdpi/ic_drag_handle.9.png deleted file mode 100644 index 939454989..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_drag_handle.9.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_drag_handle_dark.9.png b/core/src/main/res/drawable-hdpi/ic_drag_handle_dark.9.png deleted file mode 100644 index 65b9ec1fa..000000000 Binary files a/core/src/main/res/drawable-hdpi/ic_drag_handle_dark.9.png and /dev/null differ diff --git a/core/src/main/res/drawable-hdpi/ic_drag_vertical_grey600_48dp.png b/core/src/main/res/drawable-hdpi/ic_drag_vertical_grey600_48dp.png new file mode 100644 index 000000000..17202c8d1 Binary files /dev/null and b/core/src/main/res/drawable-hdpi/ic_drag_vertical_grey600_48dp.png differ diff --git a/core/src/main/res/drawable-hdpi/ic_drag_vertical_white_48dp.png b/core/src/main/res/drawable-hdpi/ic_drag_vertical_white_48dp.png new file mode 100644 index 000000000..48e221b86 Binary files /dev/null and b/core/src/main/res/drawable-hdpi/ic_drag_vertical_white_48dp.png differ diff --git a/core/src/main/res/drawable-mdpi/ic_drag_handle.9.png b/core/src/main/res/drawable-mdpi/ic_drag_handle.9.png deleted file mode 100644 index 8de13a08b..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_drag_handle.9.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_drag_handle_dark.9.png b/core/src/main/res/drawable-mdpi/ic_drag_handle_dark.9.png deleted file mode 100644 index e24681d12..000000000 Binary files a/core/src/main/res/drawable-mdpi/ic_drag_handle_dark.9.png and /dev/null differ diff --git a/core/src/main/res/drawable-mdpi/ic_drag_vertical_grey600_48dp.png b/core/src/main/res/drawable-mdpi/ic_drag_vertical_grey600_48dp.png new file mode 100644 index 000000000..31ef36bde Binary files /dev/null and b/core/src/main/res/drawable-mdpi/ic_drag_vertical_grey600_48dp.png differ diff --git a/core/src/main/res/drawable-mdpi/ic_drag_vertical_white_48dp.png b/core/src/main/res/drawable-mdpi/ic_drag_vertical_white_48dp.png new file mode 100644 index 000000000..1c0e89e60 Binary files /dev/null and b/core/src/main/res/drawable-mdpi/ic_drag_vertical_white_48dp.png differ diff --git a/core/src/main/res/drawable-xhdpi/ic_drag_handle.9.png b/core/src/main/res/drawable-xhdpi/ic_drag_handle.9.png deleted file mode 100644 index 46b8a5ad8..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_drag_handle.9.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_drag_handle_dark.9.png b/core/src/main/res/drawable-xhdpi/ic_drag_handle_dark.9.png deleted file mode 100644 index 864fae9e8..000000000 Binary files a/core/src/main/res/drawable-xhdpi/ic_drag_handle_dark.9.png and /dev/null differ diff --git a/core/src/main/res/drawable-xhdpi/ic_drag_vertical_grey600_48dp.png b/core/src/main/res/drawable-xhdpi/ic_drag_vertical_grey600_48dp.png new file mode 100644 index 000000000..3fd70af80 Binary files /dev/null and b/core/src/main/res/drawable-xhdpi/ic_drag_vertical_grey600_48dp.png differ diff --git a/core/src/main/res/drawable-xhdpi/ic_drag_vertical_white_48dp.png b/core/src/main/res/drawable-xhdpi/ic_drag_vertical_white_48dp.png new file mode 100644 index 000000000..38a3dc3f4 Binary files /dev/null and b/core/src/main/res/drawable-xhdpi/ic_drag_vertical_white_48dp.png differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_drag_handle.9.png b/core/src/main/res/drawable-xxhdpi/ic_drag_handle.9.png deleted file mode 100644 index 0e99bde9e..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_drag_handle.9.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_drag_handle_dark.9.png b/core/src/main/res/drawable-xxhdpi/ic_drag_handle_dark.9.png deleted file mode 100644 index 0da191a69..000000000 Binary files a/core/src/main/res/drawable-xxhdpi/ic_drag_handle_dark.9.png and /dev/null differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_drag_vertical_grey600_48dp.png b/core/src/main/res/drawable-xxhdpi/ic_drag_vertical_grey600_48dp.png new file mode 100644 index 000000000..048b39f0e Binary files /dev/null and b/core/src/main/res/drawable-xxhdpi/ic_drag_vertical_grey600_48dp.png differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_drag_vertical_white_48dp.png b/core/src/main/res/drawable-xxhdpi/ic_drag_vertical_white_48dp.png new file mode 100644 index 000000000..1c79c9731 Binary files /dev/null and b/core/src/main/res/drawable-xxhdpi/ic_drag_vertical_white_48dp.png differ diff --git a/core/src/main/res/drawable-xxxhdpi/ic_drag_vertical_grey600_48dp.png b/core/src/main/res/drawable-xxxhdpi/ic_drag_vertical_grey600_48dp.png new file mode 100644 index 000000000..4819da3c1 Binary files /dev/null and b/core/src/main/res/drawable-xxxhdpi/ic_drag_vertical_grey600_48dp.png differ diff --git a/core/src/main/res/drawable-xxxhdpi/ic_drag_vertical_white_48dp.png b/core/src/main/res/drawable-xxxhdpi/ic_drag_vertical_white_48dp.png new file mode 100644 index 000000000..b5820d4fe Binary files /dev/null and b/core/src/main/res/drawable-xxxhdpi/ic_drag_vertical_white_48dp.png differ diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index ccaaf9c3c..5d1eac12d 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -33,7 +33,7 @@ @color/white @color/overlay_light @drawable/overlay_drawable - @drawable/ic_drag_handle + @drawable/ic_drag_vertical_grey600_48dp @color/white @color/white @drawable/ic_more_vert_grey600_24dp @@ -80,7 +80,7 @@ @color/black @color/overlay_dark @drawable/overlay_drawable_dark - @drawable/ic_drag_handle_dark + @drawable/ic_drag_vertical_white_48dp @color/black #3B3B3B @drawable/ic_more_vert_white_24dp @@ -129,7 +129,7 @@ @color/white @color/overlay_light @drawable/overlay_drawable - @drawable/ic_drag_handle + @drawable/ic_drag_vertical_grey600_48dp @color/white @color/white @drawable/ic_more_vert_grey600_24dp @@ -177,7 +177,7 @@ @color/black @color/overlay_dark @drawable/overlay_drawable_dark - @drawable/ic_drag_handle_dark + @drawable/ic_drag_vertical_white_48dp @color/black #3B3B3B @drawable/ic_more_vert_white_24dp -- cgit v1.2.3 From cbb7d4d14a8d9dac95498a1c6d7ea3e4306d64d1 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 6 Nov 2015 22:16:19 +0100 Subject: Prevent leaking the activity --- .../antennapod/core/asynctask/DownloadObserver.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java index 732fa2d27..2ce506c22 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/DownloadObserver.java @@ -15,6 +15,7 @@ import de.danoeh.antennapod.core.service.download.Downloader; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; /** * Provides access to the DownloadService's list of items that are currently being downloaded. @@ -39,6 +40,8 @@ public class DownloadObserver { private Thread refresherThread; private AtomicBoolean refresherThreadRunning = new AtomicBoolean(false); + private AtomicInteger users = new AtomicInteger(0); + /** * Creates a new download observer. @@ -59,13 +62,18 @@ public class DownloadObserver { } public void onResume() { - if (BuildConfig.DEBUG) Log.d(TAG, "DownloadObserver resumed"); - activity.registerReceiver(contentChangedReceiver, new IntentFilter(DownloadService.ACTION_DOWNLOADS_CONTENT_CHANGED)); - connectToDownloadService(); + Log.d(TAG, "DownloadObserver resumed"); + if(users.getAndIncrement() == 0) { + activity.registerReceiver(contentChangedReceiver, new IntentFilter(DownloadService.ACTION_DOWNLOADS_CONTENT_CHANGED)); + connectToDownloadService(); + } } public void onPause() { - if (BuildConfig.DEBUG) Log.d(TAG, "DownloadObserver paused"); + Log.d(TAG, "DownloadObserver paused"); + if(users.decrementAndGet() > 0) { + return; + } try { activity.unregisterReceiver(contentChangedReceiver); } catch (IllegalArgumentException e) { -- cgit v1.2.3 From baa2d6910df989ab7239375aee77bc7a383f07b6 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 7 Nov 2015 09:30:20 -0500 Subject: need to close the image cursor --- .../java/de/danoeh/antennapod/core/storage/DBReader.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index c0a4bcf69..a422a3b0c 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -849,13 +849,16 @@ public final class DBReader { */ static FeedImage getFeedImage(PodDBAdapter adapter, final long id) { Cursor cursor = adapter.getImageCursor(id); - if ((cursor.getCount() == 0) || !cursor.moveToFirst()) { - return null; + try { + if ((cursor.getCount() == 0) || !cursor.moveToFirst()) { + return null; + } + FeedImage image = FeedImage.fromCursor(cursor); + image.setId(id); + return image; + } finally { + cursor.close(); } - FeedImage image = FeedImage.fromCursor(cursor); - image.setId(id); - cursor.close(); - return image; } /** -- cgit v1.2.3 From 2197e9b7418baa3b7833f932a4cb652be1e43ba4 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 7 Nov 2015 17:09:36 +0100 Subject: If removing currently playing episode, (pause and) skip the same --- .../main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java | 7 +++++++ .../danoeh/antennapod/core/service/playback/PlaybackService.java | 2 +- core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java | 4 +--- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java index bea8d2afd..7ff622f34 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java +++ b/core/src/main/java/de/danoeh/antennapod/core/asynctask/FeedRemover.java @@ -3,12 +3,14 @@ package de.danoeh.antennapod.core.asynctask; import android.annotation.SuppressLint; import android.app.ProgressDialog; import android.content.Context; +import android.content.Intent; import android.os.AsyncTask; import java.util.concurrent.ExecutionException; import de.danoeh.antennapod.core.R; import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.storage.DBWriter; /** Removes a feed in the background. */ @@ -16,6 +18,7 @@ public class FeedRemover extends AsyncTask { Context context; ProgressDialog dialog; Feed feed; + public boolean skipOnCompletion = false; public FeedRemover(Context context, Feed feed) { super(); @@ -38,6 +41,10 @@ public class FeedRemover extends AsyncTask { @Override protected void onPostExecute(Void result) { dialog.dismiss(); + if(skipOnCompletion) { + context.sendBroadcast(new Intent( + PlaybackService.ACTION_SKIP_CURRENT_EPISODE)); + } } @Override 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 ab78387a2..2ce91645b 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 @@ -571,7 +571,7 @@ public class PlaybackService extends Service { try { final List queue = taskManager.getQueue(); isInQueue = QueueAccess.ItemListAccess(queue).contains(item.getId()); - nextItem = DBTasks.getQueueSuccessorOfItem(this, item.getId(), queue); + nextItem = DBTasks.getQueueSuccessorOfItem(item.getId(), queue); } catch (InterruptedException e) { e.printStackTrace(); // isInQueue remains false diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java index f54e13471..a8aee1961 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java @@ -394,14 +394,12 @@ public final class DBTasks { /** * Returns the successor of a FeedItem in the queue. * - * @param context Used for accessing the DB. * @param itemId ID of the FeedItem * @param queue Used for determining the successor of the item. If this parameter is null, the method will load * the queue from the database in the same thread. * @return Successor of the FeedItem or null if the FeedItem is not in the queue or has no successor. */ - public static FeedItem getQueueSuccessorOfItem(Context context, - final long itemId, List queue) { + public static FeedItem getQueueSuccessorOfItem(final long itemId, List queue) { FeedItem result = null; if (queue == null) { queue = DBReader.getQueue(); -- cgit v1.2.3 From 694e9209023dcdfd7e1f2ab41d92a0836059ae15 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 7 Nov 2015 12:06:21 -0500 Subject: updated strings --- core/src/main/res/values-tr/strings.xml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/res/values-tr/strings.xml b/core/src/main/res/values-tr/strings.xml index 5de69d11c..86ee24107 100644 --- a/core/src/main/res/values-tr/strings.xml +++ b/core/src/main/res/values-tr/strings.xml @@ -5,8 +5,11 @@ Beslemeler Cep yayını ekle CEP YAYINLARI + Bölümler Yeni bölümler Tüm bölümler + Tümü + Favoriler Yeni Bekleme listesi Ayarlar @@ -28,6 +31,7 @@ Çekmece Seçenekleri Sayaca göre sırala Alfabetik olarak sırala + Yayınlanma tarihine göre sırala Yeni ve çalınmamış bölümlerin sayısı Yeni bölümlerin sayısı Çalınmamış bölümlerin sayısı @@ -73,6 +77,14 @@ Genel Her zaman Hiçbir zaman + Gönder... + Hiçbir zaman + Sırada değilse + Bittikten sonra + + Bittikten 1 gün sonra + Bittikten %d gün sonra + Besleme Adresi www.example.com/feed @@ -122,6 +134,8 @@ Kuyruğa Ekle Kuyruğa Eklendi Kuyruktan Kaldır + Favorilere Ekle + Favorilerden Kaldır Siteyi Ziyaret Et Flattr ile destekle Hepsini kuyruğa ekle @@ -130,6 +144,7 @@ Otomatik indirmeyi etkinleştir Otomatik indirmeyi devre dışı bırak Çalme konumunu sıfırla + Öge kaldırıldı başarılı başarısız @@ -228,6 +243,7 @@ Eklentiyi İndir Eklenti Yüklenmedi Çalma hızları + Sonic\'i Etkinleştir Bu listede hiç öge yok. Henüz hiçbir beslemeye abone değilsiniz. @@ -237,7 +253,11 @@ Kuyruk Servisler Flattr + Bölüm Temizliği + Daha fazla yer gerektiğinde kuyrukta olmayan ve favorilere eklenmemiş bölümler kaldırılmak için uygundur + Kulaklıklar çıkarıldığında veya bluetooth bağlantısı kesildiğinde çalmayı duraklat Kulaklıklar yeniden bağlandığında çalmaya devam et + Bluetooth yeniden bağlandığında çalmaya devam et Çalma tamamlandığında kuyruktaki diğer öğeye geç Çalma bittiğinde bölümü sil Otomatik Silme -- cgit v1.2.3 From 87dffd45e1963475ea01fb85abdb9e3d03c6b068 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 7 Nov 2015 14:49:07 -0500 Subject: put ff and rewind buttons on the large notification. refs AntennaPod/AntennaPod#1268 --- .../core/service/playback/PlaybackService.java | 88 ++++++++++++---------- 1 file changed, 49 insertions(+), 39 deletions(-) (limited to 'core/src/main') 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 2ce91645b..0e306b452 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 @@ -836,42 +836,24 @@ public class PlaybackService extends Service { String contentTitle = info.playable.getFeedTitle(); Notification notification = null; - Intent pauseButtonIntent = new Intent( // pause button intent - PlaybackService.this, PlaybackService.class); - pauseButtonIntent.putExtra( - MediaButtonReceiver.EXTRA_KEYCODE, - KeyEvent.KEYCODE_MEDIA_PAUSE); - PendingIntent pauseButtonPendingIntent = PendingIntent - .getService(PlaybackService.this, 0, - pauseButtonIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - Intent playButtonIntent = new Intent( // play button intent - PlaybackService.this, PlaybackService.class); - playButtonIntent.putExtra( - MediaButtonReceiver.EXTRA_KEYCODE, - KeyEvent.KEYCODE_MEDIA_PLAY); - PendingIntent playButtonPendingIntent = PendingIntent - .getService(PlaybackService.this, 1, - playButtonIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - Intent stopButtonIntent = new Intent( // stop button intent - PlaybackService.this, PlaybackService.class); - stopButtonIntent.putExtra( - MediaButtonReceiver.EXTRA_KEYCODE, - KeyEvent.KEYCODE_MEDIA_STOP); - PendingIntent stopButtonPendingIntent = PendingIntent - .getService(PlaybackService.this, 2, - stopButtonIntent, - PendingIntent.FLAG_UPDATE_CURRENT); - Intent skipButtonIntent = new Intent( - PlaybackService.this, PlaybackService.class); - skipButtonIntent.putExtra( - MediaButtonReceiver.EXTRA_KEYCODE, - KeyEvent.KEYCODE_MEDIA_NEXT); - PendingIntent skipButtonPendingIntent = PendingIntent - .getService(PlaybackService.this, 3, - skipButtonIntent, - PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent pauseButtonPendingIntent = getPendingIntentForMediaAction( + KeyEvent.KEYCODE_MEDIA_PAUSE, 0); + + PendingIntent playButtonPendingIntent = getPendingIntentForMediaAction( + KeyEvent.KEYCODE_MEDIA_PLAY, 1); + + PendingIntent stopButtonPendingIntent = getPendingIntentForMediaAction( + KeyEvent.KEYCODE_MEDIA_STOP, 2); + + PendingIntent skipButtonPendingIntent = getPendingIntentForMediaAction( + KeyEvent.KEYCODE_MEDIA_NEXT, 3); + + PendingIntent ffButtonPendingIntent = getPendingIntentForMediaAction( + KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, 4); + + PendingIntent rewindButtonPendingIntent = getPendingIntentForMediaAction( + KeyEvent.KEYCODE_MEDIA_REWIND, 5); + NotificationCompat.Builder notificationBuilder = new android.support.v7.app.NotificationCompat.Builder( PlaybackService.this) .setContentTitle(contentTitle) @@ -883,22 +865,38 @@ public class PlaybackService extends Service { .setWhen(0) // we don't need the time .setPriority(UserPreferences.getNotifyPriority()); // set notification priority IntList actionList = new IntList(); + + + // always let them rewind + notificationBuilder.addAction(android.R.drawable.ic_media_rew, + getString(R.string.rewind_label), + rewindButtonPendingIntent); + + int numActions = 0; // we start and 0 and then increment by 1 for each call to addAction + if (playerStatus == PlayerStatus.PLAYING) { notificationBuilder.addAction(android.R.drawable.ic_media_pause, //pause action getString(R.string.pause_label), pauseButtonPendingIntent); - actionList.add(actionList.size()); + actionList.add(++numActions); } else { notificationBuilder.addAction(android.R.drawable.ic_media_play, //play action getString(R.string.play_label), playButtonPendingIntent); - actionList.add(actionList.size()); + actionList.add(++numActions); } + + // ff follows play, then we have skip (if it's present) + notificationBuilder.addAction(android.R.drawable.ic_media_ff, + getString(R.string.fast_forward_label), + ffButtonPendingIntent); + ++numActions; + if (UserPreferences.isFollowQueue()) { notificationBuilder.addAction(android.R.drawable.ic_media_next, getString(R.string.skip_episode_label), skipButtonPendingIntent); - actionList.add(actionList.size()); + actionList.add(++numActions); } notificationBuilder.setStyle(new android.support.v7.app.NotificationCompat.MediaStyle() @@ -928,6 +926,18 @@ public class PlaybackService extends Service { 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. * -- cgit v1.2.3 From d25899d858f3d217e5ecf21146d13dfac59b4329 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 7 Nov 2015 14:55:38 -0500 Subject: make action handling make somewhat more sense --- .../core/service/playback/PlaybackService.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'core/src/main') 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 0e306b452..115e7730a 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 @@ -864,44 +864,45 @@ public class PlaybackService extends Service { .setSmallIcon(smallIcon) .setWhen(0) // we don't need the time .setPriority(UserPreferences.getNotifyPriority()); // set notification priority - IntList actionList = new IntList(); + IntList compactActionList = new IntList(); + int numActions = 0; // we start and 0 and then increment by 1 for each call to addAction + // always let them rewind notificationBuilder.addAction(android.R.drawable.ic_media_rew, getString(R.string.rewind_label), rewindButtonPendingIntent); - - int numActions = 0; // we start and 0 and then increment by 1 for each call to addAction + numActions++; if (playerStatus == PlayerStatus.PLAYING) { notificationBuilder.addAction(android.R.drawable.ic_media_pause, //pause action getString(R.string.pause_label), pauseButtonPendingIntent); - actionList.add(++numActions); + compactActionList.add(numActions++); } else { notificationBuilder.addAction(android.R.drawable.ic_media_play, //play action getString(R.string.play_label), playButtonPendingIntent); - actionList.add(++numActions); + compactActionList.add(numActions++); } // ff follows play, then we have skip (if it's present) notificationBuilder.addAction(android.R.drawable.ic_media_ff, getString(R.string.fast_forward_label), ffButtonPendingIntent); - ++numActions; + numActions++; if (UserPreferences.isFollowQueue()) { notificationBuilder.addAction(android.R.drawable.ic_media_next, getString(R.string.skip_episode_label), skipButtonPendingIntent); - actionList.add(++numActions); + compactActionList.add(numActions++); } notificationBuilder.setStyle(new android.support.v7.app.NotificationCompat.MediaStyle() .setMediaSession(mediaPlayer.getSessionToken()) - .setShowActionsInCompactView(actionList.toArray()) + .setShowActionsInCompactView(compactActionList.toArray()) .setShowCancelButton(true) .setCancelButtonIntent(stopButtonPendingIntent)) .setVisibility(Notification.VISIBILITY_PUBLIC) -- cgit v1.2.3 From 72c2a46359b5b762ed5fb8cfc2e5c0b56f24b370 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 7 Nov 2015 15:14:49 -0500 Subject: slight code refactoring, also BluetoothA2dp.EXTRA_STATE isn't available until API 11 --- .../core/service/playback/PlaybackService.java | 42 +++++++++++++--------- 1 file changed, 25 insertions(+), 17 deletions(-) (limited to 'core/src/main') 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 115e7730a..a019f4a98 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 @@ -836,23 +836,17 @@ public class PlaybackService extends Service { String contentTitle = info.playable.getFeedTitle(); Notification notification = null; - PendingIntent pauseButtonPendingIntent = getPendingIntentForMediaAction( - KeyEvent.KEYCODE_MEDIA_PAUSE, 0); - PendingIntent playButtonPendingIntent = getPendingIntentForMediaAction( - KeyEvent.KEYCODE_MEDIA_PLAY, 1); - PendingIntent stopButtonPendingIntent = getPendingIntentForMediaAction( - KeyEvent.KEYCODE_MEDIA_STOP, 2); - PendingIntent skipButtonPendingIntent = getPendingIntentForMediaAction( - KeyEvent.KEYCODE_MEDIA_NEXT, 3); - PendingIntent ffButtonPendingIntent = getPendingIntentForMediaAction( - KeyEvent.KEYCODE_MEDIA_FAST_FORWARD, 4); - PendingIntent rewindButtonPendingIntent = getPendingIntentForMediaAction( - KeyEvent.KEYCODE_MEDIA_REWIND, 5); + + + + + + NotificationCompat.Builder notificationBuilder = new android.support.v7.app.NotificationCompat.Builder( PlaybackService.this) @@ -870,17 +864,23 @@ public class PlaybackService extends Service { int numActions = 0; // we start and 0 and then increment by 1 for each call to addAction // 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); 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); @@ -888,18 +888,24 @@ public class PlaybackService extends Service { } // 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); 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); compactActionList.add(numActions++); } + PendingIntent stopButtonPendingIntent = getPendingIntentForMediaAction( + KeyEvent.KEYCODE_MEDIA_STOP, numActions); notificationBuilder.setStyle(new android.support.v7.app.NotificationCompat.MediaStyle() .setMediaSession(mediaPlayer.getSessionToken()) .setShowActionsInCompactView(compactActionList.toArray()) @@ -1046,11 +1052,13 @@ public class PlaybackService extends Service { private BroadcastReceiver bluetoothStateUpdated = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - if (StringUtils.equals(intent.getAction(), BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) { - int state = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, -1); - if (state == BluetoothA2dp.STATE_CONNECTED) { - Log.d(TAG, "Received bluetooth connection intent"); - unpauseIfPauseOnDisconnect(true); + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + if (StringUtils.equals(intent.getAction(), BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)) { + int state = intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, -1); + if (state == BluetoothA2dp.STATE_CONNECTED) { + Log.d(TAG, "Received bluetooth connection intent"); + unpauseIfPauseOnDisconnect(true); + } } } } -- cgit v1.2.3 From 32e870aeb506cbac28e19973f2e1a93c4b3c8e4c Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 7 Nov 2015 15:16:37 -0500 Subject: get rid of whitespace. :( --- .../antennapod/core/service/playback/PlaybackService.java | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'core/src/main') 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 a019f4a98..c4e3b6f51 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 @@ -836,18 +836,6 @@ public class PlaybackService extends Service { String contentTitle = info.playable.getFeedTitle(); Notification notification = null; - - - - - - - - - - - - NotificationCompat.Builder notificationBuilder = new android.support.v7.app.NotificationCompat.Builder( PlaybackService.this) .setContentTitle(contentTitle) -- cgit v1.2.3 From 42e6dffc82fc6a51a24a6f971bd3f52476b5d764 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 7 Nov 2015 15:28:24 -0500 Subject: also check in register and unregister. make receivers final --- .../core/service/playback/PlaybackService.java | 27 +++++++++++----------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'core/src/main') 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 c4e3b6f51..ecb307196 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 @@ -1,6 +1,5 @@ package de.danoeh.antennapod.core.service.playback; -import android.annotation.SuppressLint; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -212,7 +211,6 @@ public class PlaybackService extends Service { return ClientConfig.playbackServiceCallbacks.getPlayerActivityIntent(context, mt); } - @SuppressLint("NewApi") @Override public void onCreate() { super.onCreate(); @@ -223,8 +221,10 @@ public class PlaybackService extends Service { Intent.ACTION_HEADSET_PLUG)); registerReceiver(shutdownReceiver, new IntentFilter( ACTION_SHUTDOWN_PLAYBACK_SERVICE)); - registerReceiver(bluetoothStateUpdated, new IntentFilter( - BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)); + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + registerReceiver(bluetoothStateUpdated, new IntentFilter( + BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED)); + } registerReceiver(audioBecomingNoisy, new IntentFilter( AudioManager.ACTION_AUDIO_BECOMING_NOISY)); registerReceiver(skipCurrentEpisodeReceiver, new IntentFilter( @@ -238,7 +238,6 @@ public class PlaybackService extends Service { } - @SuppressLint("NewApi") @Override public void onDestroy() { super.onDestroy(); @@ -249,7 +248,9 @@ public class PlaybackService extends Service { unregisterReceiver(headsetDisconnected); unregisterReceiver(shutdownReceiver); - unregisterReceiver(bluetoothStateUpdated); + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + unregisterReceiver(bluetoothStateUpdated); + } unregisterReceiver(audioBecomingNoisy); unregisterReceiver(skipCurrentEpisodeReceiver); unregisterReceiver(pausePlayCurrentEpisodeReceiver); @@ -1012,7 +1013,7 @@ public class PlaybackService extends Service { * Pauses playback when the headset is disconnected and the preference is * set */ - private BroadcastReceiver headsetDisconnected = new BroadcastReceiver() { + private final BroadcastReceiver headsetDisconnected = new BroadcastReceiver() { private static final String TAG = "headsetDisconnected"; private static final int UNPLUGGED = 0; private static final int PLUGGED = 1; @@ -1037,7 +1038,7 @@ public class PlaybackService extends Service { } }; - private BroadcastReceiver bluetoothStateUpdated = new BroadcastReceiver() { + private final BroadcastReceiver bluetoothStateUpdated = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { @@ -1052,7 +1053,7 @@ public class PlaybackService extends Service { } }; - private BroadcastReceiver audioBecomingNoisy = new BroadcastReceiver() { + private final BroadcastReceiver audioBecomingNoisy = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -1098,7 +1099,7 @@ public class PlaybackService extends Service { } } - private BroadcastReceiver shutdownReceiver = new BroadcastReceiver() { + private final BroadcastReceiver shutdownReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -1109,7 +1110,7 @@ public class PlaybackService extends Service { }; - private BroadcastReceiver skipCurrentEpisodeReceiver = new BroadcastReceiver() { + private final BroadcastReceiver skipCurrentEpisodeReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (StringUtils.equals(intent.getAction(), ACTION_SKIP_CURRENT_EPISODE)) { @@ -1119,7 +1120,7 @@ public class PlaybackService extends Service { } }; - private BroadcastReceiver pauseResumeCurrentEpisodeReceiver = new BroadcastReceiver() { + private final BroadcastReceiver pauseResumeCurrentEpisodeReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (StringUtils.equals(intent.getAction(), ACTION_RESUME_PLAY_CURRENT_EPISODE)) { @@ -1129,7 +1130,7 @@ public class PlaybackService extends Service { } }; - private BroadcastReceiver pausePlayCurrentEpisodeReceiver = new BroadcastReceiver() { + private final BroadcastReceiver pausePlayCurrentEpisodeReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (StringUtils.equals(intent.getAction(), ACTION_PAUSE_PLAY_CURRENT_EPISODE)) { -- cgit v1.2.3 From 3b13ff1faab6de7a97ee08b64142cde5b29d89b3 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sat, 7 Nov 2015 15:32:21 -0500 Subject: missed a SuppressLint --- .../java/de/danoeh/antennapod/core/service/playback/PlaybackService.java | 1 - 1 file changed, 1 deletion(-) (limited to 'core/src/main') 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 ecb307196..5e0738cb8 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 @@ -786,7 +786,6 @@ public class PlaybackService extends Service { /** * Prepares notification and starts the service in the foreground. */ - @SuppressLint("NewApi") private void setupNotification(final PlaybackServiceMediaPlayer.PSMPInfo info) { final PendingIntent pIntent = PendingIntent.getActivity(this, 0, PlaybackService.getPlayerActivityIntent(this), -- cgit v1.2.3 From 8de90b7948569ef946979efa26c3c5f928a50b9c Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 8 Nov 2015 18:05:19 +0100 Subject: AlertDialog -> v7 AlertDialog --- .../main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java | 2 +- .../antennapod/core/dialog/DownloadRequestErrorDialogCreator.java | 3 ++- .../main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java b/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java index fea2bbb2b..abb75e5e7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java +++ b/core/src/main/java/de/danoeh/antennapod/core/dialog/ConfirmationDialog.java @@ -1,8 +1,8 @@ package de.danoeh.antennapod.core.dialog; -import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; +import android.support.v7.app.AlertDialog; import android.util.Log; import de.danoeh.antennapod.core.R; diff --git a/core/src/main/java/de/danoeh/antennapod/core/dialog/DownloadRequestErrorDialogCreator.java b/core/src/main/java/de/danoeh/antennapod/core/dialog/DownloadRequestErrorDialogCreator.java index 3d174bd8e..b7e79431d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/dialog/DownloadRequestErrorDialogCreator.java +++ b/core/src/main/java/de/danoeh/antennapod/core/dialog/DownloadRequestErrorDialogCreator.java @@ -1,8 +1,9 @@ package de.danoeh.antennapod.core.dialog; -import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; +import android.support.v7.app.AlertDialog; + import de.danoeh.antennapod.core.R; /** Creates Alert Dialogs if a DownloadRequestException has happened. */ diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java index f37933876..318839e1d 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/flattr/FlattrUtils.java @@ -1,6 +1,5 @@ package de.danoeh.antennapod.core.util.flattr; -import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; @@ -8,6 +7,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.net.Uri; import android.preference.PreferenceManager; +import android.support.v7.app.AlertDialog; import android.util.Log; import org.apache.commons.lang3.StringUtils; -- cgit v1.2.3 From 27aab0b0a0cf1cd82d176e65b31aea8b56ba357e Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Sun, 8 Nov 2015 14:13:18 -0500 Subject: updated strings --- core/src/main/res/values-fr/strings.xml | 3 +++ core/src/main/res/values-ja/strings.xml | 3 +++ core/src/main/res/values-uk-rUA/strings.xml | 5 +++++ 3 files changed, 11 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml index 2d025239f..5aa1b3697 100644 --- a/core/src/main/res/values-fr/strings.xml +++ b/core/src/main/res/values-fr/strings.xml @@ -257,7 +257,9 @@ Flattr Nettoyage des épisodes Les épisodes qui ne sont ni dans la liste ni dans les favoris peuvent être supprimés si l\'espace disque devient faible + Interrompre la lecture lorsque le casque ou le bluetooth sont déconnectés Reprendre la lecture quand les écouteurs sont reconnectés + Reprendre la lecture quand le bluetooth se connecte Après la fin d\'un épisode, passer au suivant Supprimer l\'épisode quand la lecture est finie Suppression automatique @@ -278,6 +280,7 @@ Téléchargement en Wi-Fi Déconnexion du casque Reconnexion du casque + Connection bluetooth Mises à jour mobile Autoriser les mises à jour à travers la connexion de données mobile Mise à jour en cours diff --git a/core/src/main/res/values-ja/strings.xml b/core/src/main/res/values-ja/strings.xml index 0d234da27..46556cabe 100644 --- a/core/src/main/res/values-ja/strings.xml +++ b/core/src/main/res/values-ja/strings.xml @@ -256,7 +256,9 @@ Flattr エピソード クリーンアップ 空き容量が必要な場合、キューに含まれていおらず、お気に入りでもないエピソードは、削除の対象になります + ヘッドフォンまたはBluetoothの接続が切断された時、再生を一時停止します ヘッドフォンが再接続された時に再生を再開します + Bluetoothが再接続された時に再生を再開します 再生が完了した時に次のキューのアイテムに移動します 再生が完了した時にエピソードを削除します 自動削除 @@ -277,6 +279,7 @@ WiFiメディアダウンロード ヘッドフォン切断 ヘッドフォン再接続 + Bluetooth再接続 モバイル更新 モバイルデータ接続時に更新を許可します 更新中 diff --git a/core/src/main/res/values-uk-rUA/strings.xml b/core/src/main/res/values-uk-rUA/strings.xml index bbee32385..c1d56a29a 100644 --- a/core/src/main/res/values-uk-rUA/strings.xml +++ b/core/src/main/res/values-uk-rUA/strings.xml @@ -258,12 +258,16 @@ Flattr Чищення епізодів У разі нестачі пам\'яті видалять епізоди які не знаходяться ні в списку улюблених ні в черзі. + Зупинятись коли навушники або блютуз від’єднано Поновити відтворення коли навушники повторно під’єднано + Поновити відтворення коли блютуз повторно під’єднано Перейти до наступного епізода в черзі коли поточний закінчено Видалити епізод після повного відтворення Автовидалення Позначити епізоди як грані навіть якщо залишилось менш ніж зазначене число секунд до кінця відтворення Розумне позначення граних епізодів + Зберігати епізоди що пропущені при програванні + Зберігати пропущені при програванні епізоди Відтворення Мережа Частота оновлень або оновлення в зазначений час @@ -277,6 +281,7 @@ Завантаження через Wifi Навушники витягнуті Повторне під’єднання навушників + Повторне під’єднання блютуз Мобільне оновлення Дозволити оновлення через оператора зв\'язку Оновлення -- cgit v1.2.3 From 059ef16dc237d26861813cac3a43ba6723fd9556 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sun, 8 Nov 2015 20:49:59 +0100 Subject: Fix dialog colors --- core/src/main/res/values-v16/styles.xml | 2 +- core/src/main/res/values/colors.xml | 6 +-- core/src/main/res/values/styles.xml | 68 ++++++++++----------------------- 3 files changed, 25 insertions(+), 51 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values-v16/styles.xml b/core/src/main/res/values-v16/styles.xml index e7c56b5f5..a92790152 100644 --- a/core/src/main/res/values-v16/styles.xml +++ b/core/src/main/res/values-v16/styles.xml @@ -9,7 +9,7 @@ - - - - - - - - - + + + + + + -- cgit v1.2.3 From a2104964e7576930e85afb289b620aa0c770544a Mon Sep 17 00:00:00 2001 From: recalculated Date: Thu, 7 Jan 2016 20:35:04 -0600 Subject: Add queue lock/unlock snackbar message --- core/src/main/res/values/strings.xml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 443a1a8a8..69acdcc4a 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -217,6 +217,8 @@ Lock Queue Unlock Queue + Queue locked + Queue unlocked Clear Queue Undo Item removed -- cgit v1.2.3 From 4f864ab2deb8b3dfb6364a17f2a09f57bb09f5a0 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Fri, 8 Jan 2016 18:21:35 +0100 Subject: Disable auto download when HTTP_NOT_FOUND (404) --- .../antennapod/core/service/download/DownloadService.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'core/src/main') 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 29c44207d..bb7ff29d4 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 @@ -26,6 +26,7 @@ import org.xml.sax.SAXException; import java.io.File; import java.io.IOException; +import java.net.HttpURLConnection; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -196,11 +197,20 @@ public class DownloadService extends Service { saveDownloadStatus(status); handleFailedDownload(status, downloader.getDownloadRequest()); - // to make lists reload the failed item, we fake an item update if(type == FeedMedia.FEEDFILETYPE_FEEDMEDIA) { long id = status.getFeedfileId(); FeedMedia media = DBReader.getFeedMedia(id); - EventBus.getDefault().post(FeedItemEvent.updated(media.getItem())); + if(media == null || media.getItem() == null) { + return; + } + FeedItem item = media.getItem(); + if (status.getReason() == DownloadError.ERROR_HTTP_DATA_ERROR && + Integer.valueOf(status.getReasonDetailed()) == HttpURLConnection.HTTP_NOT_FOUND) { + item.setAutoDownload(false); // for event bus + DBWriter.setFeedItemAutoDownload(item, false); + } + // to make lists reload the failed item, we fake an item update + EventBus.getDefault().post(FeedItemEvent.updated(item)); } } } else { -- cgit v1.2.3 From 2caaa0f9dd3e84d0e3b34725674a8f7475a8f891 Mon Sep 17 00:00:00 2001 From: Tom Hennen Date: Fri, 8 Jan 2016 16:35:24 -0500 Subject: updated translations 2016-01-08 --- core/src/main/res/values-cs-rCZ/strings.xml | 4 ++-- core/src/main/res/values-de/strings.xml | 4 ++-- core/src/main/res/values-es/strings.xml | 15 +++++++++++++++ core/src/main/res/values-fr/strings.xml | 10 +++++----- core/src/main/res/values-ja/strings.xml | 15 +++++++++++++++ core/src/main/res/values-ru/strings.xml | 9 +++++++++ core/src/main/res/values-sv-rSE/strings.xml | 4 ++-- core/src/main/res/values-tr/strings.xml | 19 +++++++++++++++++++ 8 files changed, 69 insertions(+), 11 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values-cs-rCZ/strings.xml b/core/src/main/res/values-cs-rCZ/strings.xml index e220432b9..987b2e7b5 100644 --- a/core/src/main/res/values-cs-rCZ/strings.xml +++ b/core/src/main/res/values-cs-rCZ/strings.xml @@ -22,7 +22,7 @@ Historie přehrávání gpodder.net Login pro gpodder.net - %1$s volných + %1$s volné Nedávno zveřejněné Zobrazit pouze nové epizody @@ -264,7 +264,7 @@ Pokračovat v přehrávání po připojení sluchátek Pokračovat v přehrávání po připojení bluetooth Přeskočit tlačítkem vpřed - Po stlačení hardwarového tlačítka pro posun vpřed přeskočit na další skladbu + Po stlačení hardwarového tlačítka pro posun vpřed místo přetočení vpřed přeskočit na další epizodu Po přehrání položky z fronty přejít automaticky na další Smazat díl po jeho přehrání Automatické mazání diff --git a/core/src/main/res/values-de/strings.xml b/core/src/main/res/values-de/strings.xml index 7cdd15146..001f869aa 100644 --- a/core/src/main/res/values-de/strings.xml +++ b/core/src/main/res/values-de/strings.xml @@ -16,7 +16,7 @@ Podcast hinzufügen Downloads Aktiv - Abgeschlossen + Beendet Log Download abbrechen Zuletzt gespielt @@ -513,7 +513,7 @@ Dauer (kurz \u2192 lang) Dauer (lang \u2192 kurz) - Magst du AntennaPod? + Gefällt dir AntennaPod? Wir würden uns freuen, wenn du dir kurz die Zeit nimmst, AntennaPod zu bewerten. Lass mich in Ruhe Erinnere mich später diff --git a/core/src/main/res/values-es/strings.xml b/core/src/main/res/values-es/strings.xml index 0bed13e34..a99a052d4 100644 --- a/core/src/main/res/values-es/strings.xml +++ b/core/src/main/res/values-es/strings.xml @@ -22,6 +22,7 @@ Historial de reproducciones gpodder.net Iniciar sesión en gpodder.net + %1$s libre Publicados recientemente Mostrar solo episodios nuevos @@ -260,6 +261,8 @@ Pausar la reproducción al desconectar los auriculares o el bluetooth Reanudar reproducción cuando se reconecten los auriculares Reanudar reproducción cuando se reconecte el bluetooth + Saltar episodio con botón + Al pulsar el botón físico de avanzar se saltará al siguiente episodio en lugar de sólo avanzar Saltar al siguiente elemento de la cola al acabar la reproducción Borrar episodio cuando finalice la reproducción Eliminar automáticamente @@ -344,6 +347,9 @@ Deshabilitado Tamaño de la caché de imágenes Tamaño de la caché en disco para imágenes. + Informe de fallo + Enviar el último informe de fallo por e-mail + Enviar e-mail Experimental Sonic media player Usar sonic media player integrado como sustitución de Prestissimo @@ -438,11 +444,15 @@ Carpeta seleccionada Crear carpeta Elegir carpeta de datos + Por favor elige la raíz de la carpeta de datos. AntennaPod creará los subdirectorios apropiados. ¿Crear carpeta con nombre «%1$s»? Carpeta creada No se puede escribir a esta carpeta Ya existe la carpeta No se ha podido crear la carpeta + \"%1$s\" no existe + \"%1$s\" no se puede leer + \"%1$s\" no se puede modificar La carpeta no está vacía La carpeta elegida no está vacía. Las descargas y otros archivos se copiarán directamente en esta carpeta. ¿Continuar igualmente? Elegir carpeta predeterminada @@ -503,4 +513,9 @@ Duración (Corto \u2192 Largo) Duración (Largo \u2192 Corto) + ¿Te gusta AntennaPod? + Estaríamos muy agradecidos si nos dedicas un tiempo para puntuar AntennaPod + Déjame en paz + Recuérdamelo después + ¡Venga, hagámoslo! diff --git a/core/src/main/res/values-fr/strings.xml b/core/src/main/res/values-fr/strings.xml index bd3d1406f..c1a8a03fe 100644 --- a/core/src/main/res/values-fr/strings.xml +++ b/core/src/main/res/values-fr/strings.xml @@ -22,7 +22,7 @@ Journal des lectures gpodder.net Identifiants gpodder.net - \"%1$s libre + %1$s libre Publié récemment N\'afficher que les nouveaux épisodes @@ -260,9 +260,9 @@ Les épisodes qui ne sont ni dans la liste ni dans les favoris peuvent être supprimés si l\'espace disque devient faible Interrompre la lecture lorsque le casque ou le bluetooth sont déconnectés Reprendre la lecture quand les écouteurs sont reconnectés - Reprendre la lecture quand le bluetooth se reconnecte + Reprendre la lecture quand le Bluetooth se reconnecte Le bouton piste suivante saute l\'épisode - Au lieu de faire un saut avant passer à l\'épisode suivant quand un bouton physique pour passer à la piste suivante est pressé + Passer à l\'épisode suivant au lieu de faire un saut avant quand il est pressé un bouton physique pour avancer à la piste suivante Après la fin d\'un épisode, passer au suivant Supprimer l\'épisode quand la lecture est finie Suppression automatique @@ -283,7 +283,7 @@ Téléchargement en Wi-Fi Déconnexion du casque Reconnexion du casque - Connection bluetooth + Reconnexion Bluetooth Mises à jour mobile Autoriser les mises à jour à travers la connexion de données mobile Mise à jour en cours @@ -517,5 +517,5 @@ Nous vous serions reconnaissant de prendre un peu de temps pour noter AntennaPod. Laissez moi tranquille Rappelez le moi plus tard - Okay, faisons ça ! + Okay, c\'est parti ! diff --git a/core/src/main/res/values-ja/strings.xml b/core/src/main/res/values-ja/strings.xml index f58e90597..0bedd912f 100644 --- a/core/src/main/res/values-ja/strings.xml +++ b/core/src/main/res/values-ja/strings.xml @@ -22,6 +22,7 @@ 再生履歴 gpodder.net gpodder.net ログイン + %1$s 空き 最近公開された 新しいエピソードのみ表示 @@ -259,6 +260,8 @@ ヘッドフォンまたはBluetoothの接続が切断された時、再生を一時停止します ヘッドフォンが再接続された時に再生を再開します Bluetoothが再接続された時に再生を再開します + 早送りボタンでスキップ + ハードウェアの早送りボタンを押したときに、早送りの代わりに次のエピソードにスキップします 再生が完了した時に次のキューのアイテムに移動します 再生が完了した時にエピソードを削除します 自動削除 @@ -343,6 +346,9 @@ 無効 画像キャッシュサイズ 画像のディスクキャッシュのサイズ。 + クラッシュレポート + メールで最新のクラッシュレポートを送信します + メールを送信 実験的 Sonic メディアプレーヤー Prestissimo の代わりに、内蔵の Sonic メディアプレーヤーを使用します @@ -434,11 +440,15 @@ 選択したフォルダー: フォルダーを作成 データ フォルダーを選択 + 基本のデータフォルダーを選択してください。 AntennaPodは、適切なサブディレクトリを作成します。 名前 \"%1$s\" で新しいフォルダーを作成しますか? 新しいフォルダーを作成しました このフォルダーに書き込みできません フォルダーは既に存在します フォルダーを作成できません + \"%1$s\" は存在しません + \"%1$s\" は読み込みできません + \"%1$s\" は書き込みできません フォルダーが空ではありません 選択したフォルダは空ではありません。メディアのダウンロードやその他のファイルはこのフォルダに直接配置されます。続けますか? デフォルトのフォルダーを選択 @@ -499,4 +509,9 @@ 期間 (短 \u2192 長) 期間 (長 \u2192 短) + AntennaPod は気に入りましたか? + AntennaPodを評価する時間をいただければ幸いです。 + 構わないで + 後で確認する + もちろん、します! diff --git a/core/src/main/res/values-ru/strings.xml b/core/src/main/res/values-ru/strings.xml index 4ad4d3561..a3aee0f03 100644 --- a/core/src/main/res/values-ru/strings.xml +++ b/core/src/main/res/values-ru/strings.xml @@ -339,6 +339,7 @@ Отключено Размер кэша для изображений Размер дискового кэша для изображений + Отчет о сбое Экспериментальные настройки Проигрыватель Sonic Использовать встроенный проигрыватель Sonic вместо Prestissimo. @@ -426,6 +427,9 @@ Запись в эту папку невозможна Папка уже существует Невозможно создать папку + \"%1$s\" не существует + \"%1$s\" недоступен для чтения + \"%1$s\" недоступен для записи Папка не пуста Выбранная папка не пуста. Загрузки и прочие файлы будут сохранены в эту папку. Продолжить? Выберите папку по умолчанию @@ -486,4 +490,9 @@ Продолжительности (Короткие \u2192 Длинные) Продолжительности (Длинные \u2192 Короткие) + Нравится AntennaPod? + Мы будем благодарны, если вы оцените AntennaPod. + Отстань от меня + Напомни позже + Конечно, давай! diff --git a/core/src/main/res/values-sv-rSE/strings.xml b/core/src/main/res/values-sv-rSE/strings.xml index a618e257f..51a75a3e7 100644 --- a/core/src/main/res/values-sv-rSE/strings.xml +++ b/core/src/main/res/values-sv-rSE/strings.xml @@ -22,7 +22,7 @@ Uppspelningshistorik gpodder.net Inloggning till gpodder.net - \"%1$s oanvänt + %1$s kvar Nyligen publicerade Visa bara nya Episoder @@ -262,7 +262,7 @@ Fortsätt uppspelningen när hörlurarna återansluts Fortsätt uppspelningen när bluetooth återansluts Framåt-knappen hoppar - När den fysiska framåt-knappen trycks in, hoppa till nästa episod istället för att spola framåt + Hoppa till nästa episod istället för att snabbspola vid tryck på hårdvaruknappen Hoppa till nästa i kön när uppspelningen är klar Ta bort episoden när uppspelningen är klar Automatisk Borttagning diff --git a/core/src/main/res/values-tr/strings.xml b/core/src/main/res/values-tr/strings.xml index 6a59248f6..5494dd48c 100644 --- a/core/src/main/res/values-tr/strings.xml +++ b/core/src/main/res/values-tr/strings.xml @@ -332,6 +332,12 @@ Devre dışı Görüntü Önbelleği Boyutu Görüntüler için diskte tutulacak önbelleğin boyutu. + Çökme Raporu + En son çökme raporunu e-posta ile gönder + E-posta gönder + Deneysel + Sonic ortam yürütücüsü + Prestissimo yerine sonic ortam yürütücüsünü kullan Otomatik Flattr\'lamayı etkinleştir Bölümün yüzde %d kısmı oynatıldığında Flattr\'la @@ -346,6 +352,7 @@ Başlıkta bulundu OPML dosyaları cep yayınlarını bir cihazdan diğerine aktarmanıza yarar. + Seçenek %1$d Yerel dosya sisteminden belirli bir yol seçin. OPML dosyasını açmak için harici uygulamalardan Dropbox, Google Drive veya kendi favori dosya yöneticinizi kullanın. Google Mail, Dropbox, Google Drive gibi birçok uygulama ve çoğu dosya yöneticisi OPML dosyalarını AntennaPod ile açabilir. @@ -372,6 +379,9 @@ Zamanlayıcı Kalan süre:\u0020 Geçersiz giriş, zaman bir tam sayı olmalıdır + Zamanlayıcı süresi dolduğunda: + Zamanyacıyı sıfırlamak için salla + Titret saniye dakika saat @@ -419,11 +429,15 @@ Seçilen dizin: Dizin yarat Veri dizinini seç + Lütfen verileriniz için ana klasörü seçin. AntennaPod gerekli alt-klasörleri oluşturacaktır. \"%1$s\" isminde yeni dizin oluştur? Yeni dizin yaratıldı Bu dizine yazılamadı Dizin zaten var Dizin yaratılamadı + \"%1$s\" adlı klasör yok + \"%1$s\" klasörü okunabilir değil + \"%1$s\" klasörü yazılabilir değil Dizin boş değil Seçtiğiniz dizin dolu. Medya indirmeleri ve diğer dosyalar doğrudan bu dizine yerleştirilecek. Devam edilsin mi? Vaysayılan dizini seç @@ -484,4 +498,9 @@ Süre (Kısa \u2192 Uzun) Süre (Uzun \u2192 Kısa) + AntennaPod\'u beğendiniz mi? + Eğer AntennaPod\'a oy vermek için biraz zamanını ayırırsanız memnun oluruz. + Bir daha gösterme + Daha sonra hatırlat + Evet, şimdi yapalım! -- cgit v1.2.3 From 30e963fc3e4f1f49369e79ae131143c835d1a3fd Mon Sep 17 00:00:00 2001 From: recalculated Date: Fri, 8 Jan 2016 17:42:05 -0600 Subject: Make progress bar theme-specific --- .../src/main/res/drawable-v21/progress_bar_horizontal.xml | 10 ---------- core/src/main/res/drawable/progress_bar_horizontal.xml | 10 ---------- .../main/res/drawable/progress_bar_horizontal_dark.xml | 15 +++++++++++++++ .../main/res/drawable/progress_bar_horizontal_light.xml | 15 +++++++++++++++ core/src/main/res/values/attrs.xml | 1 + core/src/main/res/values/styles.xml | 13 +++++++++++-- 6 files changed, 42 insertions(+), 22 deletions(-) delete mode 100644 core/src/main/res/drawable-v21/progress_bar_horizontal.xml delete mode 100644 core/src/main/res/drawable/progress_bar_horizontal.xml create mode 100644 core/src/main/res/drawable/progress_bar_horizontal_dark.xml create mode 100644 core/src/main/res/drawable/progress_bar_horizontal_light.xml (limited to 'core/src/main') diff --git a/core/src/main/res/drawable-v21/progress_bar_horizontal.xml b/core/src/main/res/drawable-v21/progress_bar_horizontal.xml deleted file mode 100644 index 2c0c18182..000000000 --- a/core/src/main/res/drawable-v21/progress_bar_horizontal.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/core/src/main/res/drawable/progress_bar_horizontal.xml b/core/src/main/res/drawable/progress_bar_horizontal.xml deleted file mode 100644 index f96a1c3e0..000000000 --- a/core/src/main/res/drawable/progress_bar_horizontal.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/core/src/main/res/drawable/progress_bar_horizontal_dark.xml b/core/src/main/res/drawable/progress_bar_horizontal_dark.xml new file mode 100644 index 000000000..73ad5b37c --- /dev/null +++ b/core/src/main/res/drawable/progress_bar_horizontal_dark.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/core/src/main/res/drawable/progress_bar_horizontal_light.xml b/core/src/main/res/drawable/progress_bar_horizontal_light.xml new file mode 100644 index 000000000..a1a7129e9 --- /dev/null +++ b/core/src/main/res/drawable/progress_bar_horizontal_light.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/core/src/main/res/values/attrs.xml b/core/src/main/res/values/attrs.xml index de641f518..4e444c990 100644 --- a/core/src/main/res/values/attrs.xml +++ b/core/src/main/res/values/attrs.xml @@ -41,6 +41,7 @@ + diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index b006f31b9..1f73fbba2 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -4,6 +4,7 @@ - + + -- cgit v1.2.3 From e5b7f12732794ec6f40a3dd2dda42cd7ddee5b76 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Wed, 6 Jan 2016 20:15:07 +0100 Subject: Indicate that episode cache is exhausted --- core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index fe5b177ab..e8fd960f8 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -1015,6 +1015,8 @@ public final class DBReader { Collections.sort(feeds, comparator); int queueSize = adapter.getQueueSize(); int numNewItems = adapter.getNumberOfNewItems(); + int numDownloadedItems = adapter.getNumberOfDownloadedEpisodes(); + NavDrawerData result = new NavDrawerData(feeds, queueSize, numNewItems, feedCounters); adapter.close(); return result; @@ -1024,6 +1026,7 @@ public final class DBReader { public List feeds; public int queueSize; public int numNewItems; + public int numDownloadedItems; public LongIntMap feedCounters; public NavDrawerData(List feeds, -- cgit v1.2.3 From ec9ecb1af0570febc50e3571e1f5510090ae7974 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 9 Jan 2016 18:26:59 +0100 Subject: More smark options --- core/src/main/res/values/arrays.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 341a7e520..6e885c0bb 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -11,8 +11,9 @@ 0 15 30 - 45 60 + 120 + 300 -- cgit v1.2.3 From 55f1efd74da572de1964e19d2c8fce775dc5e513 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 9 Jan 2016 22:08:58 +0100 Subject: Explanation dialog --- core/src/main/res/values/strings.xml | 2 ++ 1 file changed, 2 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 69acdcc4a..30b29df91 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -26,6 +26,8 @@ gpodder.net gpodder.net Login %1$s free + Episode cache full + The episode cache limit has been reached. You can increase the cache size in the Settings. Recently published -- cgit v1.2.3 From 1348ab83ff91ad6efb7ef826916ae189fc2eb079 Mon Sep 17 00:00:00 2001 From: recalculated Date: Sun, 10 Jan 2016 11:01:48 -0600 Subject: Replace ... with … (ellipsis character) --- core/src/main/res/values/strings.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 69acdcc4a..278c6b420 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -75,7 +75,7 @@ Length:\u0020 Size:\u0020 Processing - Loading... + Loading… Save username and password Close Retry @@ -87,7 +87,7 @@ Global Always Never - Send... + Send… Never When not in queue After finishing @@ -112,7 +112,7 @@ Mark all as seen Show information Remove Podcast - Share... + Share… Share Link Share Link with Position Share Feed URL @@ -402,11 +402,11 @@ The import directory is empty. Select all Deselect all - Select ... + Select… From local filesystem Use external application OPML export - Exporting... + Exporting… Export error OPML Export successful. The .opml file was written to:\u0020 @@ -494,7 +494,7 @@ Subscribe Subscribed - Downloading... + Downloading… Show chapters @@ -529,7 +529,7 @@ Importing subscriptions from single-purpose apps… Search iTunes - Select ... + Select… All Selected all Episodes None @@ -542,7 +542,7 @@ Selected downloaded Episodes Not downloaded Selected not downloaded Episodes - Sort by ... + Sort by… Title (A \u2192 Z) Title (Z \u2192 A) Date (New \u2192 Old) -- cgit v1.2.3 From f6d5c780e59687509fd0d96c3a31e5ca69697fba Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Thu, 14 Jan 2016 19:52:54 +0100 Subject: Auto Download: Exponential backoff when file 404s --- .../de/danoeh/antennapod/core/feed/FeedItem.java | 44 +++++++++++++++++----- .../core/service/download/DownloadService.java | 3 +- .../danoeh/antennapod/core/storage/DBWriter.java | 27 ++++++++++++- .../antennapod/core/storage/PodDBAdapter.java | 2 +- 4 files changed, 62 insertions(+), 14 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java index c54cc1d5b..00b32de5f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java +++ b/core/src/main/java/de/danoeh/antennapod/core/feed/FeedItem.java @@ -11,6 +11,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; import de.danoeh.antennapod.core.asynctask.ImageResource; import de.danoeh.antennapod.core.storage.DBReader; @@ -75,7 +76,13 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr private List chapters; private FeedImage image; - private boolean autoDownload = true; + /* + * 0: auto download disabled + * 1: auto download enabled + * > 1: auto download enabled, (approx.) timestamp of the last failed attempt + * where last digit denotes the number of failed attempts + */ + private long autoDownload = 0; /** * Any tags assigned to this item @@ -93,7 +100,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr * */ public FeedItem(long id, String title, String link, Date pubDate, String paymentLink, long feedId, FlattrStatus flattrStatus, boolean hasChapters, FeedImage image, int state, - String itemIdentifier, boolean autoDownload) { + String itemIdentifier, long autoDownload) { this.id = id; this.title = title; this.link = link; @@ -162,7 +169,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr FlattrStatus flattrStatus = new FlattrStatus(cursor.getLong(indexFlattrStatus)); int state = cursor.getInt(indexRead); String itemIdentifier = cursor.getString(indexItemIdentifier); - boolean autoDownload = cursor.getInt(indexAutoDownload) > 0; + long autoDownload = cursor.getLong(indexAutoDownload); FeedItem item = new FeedItem(id, title, link, pubDate, paymentLink, feedId, flattrStatus, hasChapters, null, state, itemIdentifier, autoDownload); @@ -449,18 +456,37 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr } public void setAutoDownload(boolean autoDownload) { - this.autoDownload = autoDownload; + this.autoDownload = autoDownload ? 1 : 0; } public boolean getAutoDownload() { - return this.autoDownload; + return this.autoDownload > 0; + } + + public int getFailedAutoDownloadAttempts() { + if (autoDownload <= 1) { + return 0; + } + int failedAttempts = (int)(autoDownload % 10); + if (failedAttempts == 0) { + failedAttempts = 10; + } + return failedAttempts; } public boolean isAutoDownloadable() { - return this.hasMedia() && - false == this.getMedia().isPlaying() && - false == this.getMedia().isDownloaded() && - this.getAutoDownload(); + if (media == null || media.isPlaying() || media.isDownloaded() || autoDownload == 0) { + return false; + } + if (autoDownload == 1) { + return true; + } + int failedAttempts = getFailedAutoDownloadAttempts(); + double magicValue = 1.767; // 1.767^(10[=#maxNumAttempts]-1) = 168 hours / 7 days + int millisecondsInHour = 3600000; + long waitingTime = (long) (Math.pow(magicValue, failedAttempts - 1) * millisecondsInHour); + long grace = TimeUnit.MINUTES.toMillis(5); + return System.currentTimeMillis() > (autoDownload + waitingTime - grace); } /** 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 bb7ff29d4..c3afff276 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 @@ -206,8 +206,7 @@ public class DownloadService extends Service { FeedItem item = media.getItem(); if (status.getReason() == DownloadError.ERROR_HTTP_DATA_ERROR && Integer.valueOf(status.getReasonDetailed()) == HttpURLConnection.HTTP_NOT_FOUND) { - item.setAutoDownload(false); // for event bus - DBWriter.setFeedItemAutoDownload(item, false); + DBWriter.saveFeedItemAutoDownloadFailed(item).get(); } // to make lists reload the failed item, we fake an item update EventBus.getDefault().post(FeedItemEvent.updated(item)); diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java index f74064cfc..d1d6bd750 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 @@ -977,11 +977,33 @@ public class DBWriter { * Sets the 'auto_download'-attribute of specific FeedItem. * * @param feedItem FeedItem. + * @param autoDownload true enables auto download, false disables it */ public static Future setFeedItemAutoDownload(final FeedItem feedItem, final boolean autoDownload) { - Log.d(TAG, "FeedItem[id=" + feedItem.getId() + "] SET auto_download " + autoDownload); return dbExec.submit(() -> { + final PodDBAdapter adapter = PodDBAdapter.getInstance(); + adapter.open(); + adapter.setFeedItemAutoDownload(feedItem, autoDownload ? 1 : 0); + adapter.close(); + EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast(); + }); + } + + public static Future saveFeedItemAutoDownloadFailed(final FeedItem feedItem) { + return dbExec.submit(() -> { + int failedAttempts = feedItem.getFailedAutoDownloadAttempts() + 1; + Log.d(TAG, "failedAttempts: " + failedAttempts); + long autoDownload; + if(!feedItem.getAutoDownload() || failedAttempts >= 10) { + autoDownload = 0; // giving up, disable auto download + feedItem.setAutoDownload(false); + } else { + long now = System.currentTimeMillis(); + autoDownload = (now / 10) * 10 + failedAttempts; + Log.d(TAG, "now: " + now); + Log.d(TAG, "autoDownload: " + autoDownload); + } final PodDBAdapter adapter = PodDBAdapter.getInstance(); adapter.open(); adapter.setFeedItemAutoDownload(feedItem, autoDownload); @@ -992,7 +1014,8 @@ public class DBWriter { /** * Sets the 'auto_download'-attribute of specific FeedItem. - * @param feed This feed's episodes will be processed. + * + * @param feed This feed's episodes will be processed. * @param autoDownload If true, auto download will be enabled for the feed's episodes. Else, */ public static Future setFeedsItemsAutoDownload(final Feed feed, diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java index 629b73668..915ca14c7 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 @@ -794,7 +794,7 @@ public class PodDBAdapter { return status.getId(); } - public void setFeedItemAutoDownload(FeedItem feedItem, boolean autoDownload) { + public void setFeedItemAutoDownload(FeedItem feedItem, long autoDownload) { ContentValues values = new ContentValues(); values.put(KEY_AUTO_DOWNLOAD, autoDownload); db.update(TABLE_NAME_FEED_ITEMS, values, KEY_ID + "=?", -- cgit v1.2.3 From 102363c97f0fbda6fc7f82c8c8c134996a743c3e Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 16 Jan 2016 11:04:09 +0100 Subject: Check that image url is not empty --- .../de/danoeh/antennapod/core/syndication/namespace/NSITunes.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'core/src/main') 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 6406295c1..9b9849c49 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 @@ -1,5 +1,7 @@ package de.danoeh.antennapod.core.syndication.namespace; +import android.text.TextUtils; + import org.xml.sax.Attributes; import java.util.concurrent.TimeUnit; @@ -36,8 +38,10 @@ public class NSITunes extends Namespace { } else { // this is the feed image // prefer to all other images - image.setOwner(state.getFeed()); - state.getFeed().setImage(image); + if(!TextUtils.isEmpty(image.getDownload_url())) { + image.setOwner(state.getFeed()); + state.getFeed().setImage(image); + } } } -- cgit v1.2.3 From dc06b9c873a623a513e45a3e361eb607bb47354c Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Sat, 16 Jan 2016 20:39:05 +0100 Subject: And now also set it... --- core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'core/src/main') diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java index e8fd960f8..16e65f9f3 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java +++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBReader.java @@ -1017,7 +1017,7 @@ public final class DBReader { int numNewItems = adapter.getNumberOfNewItems(); int numDownloadedItems = adapter.getNumberOfDownloadedEpisodes(); - NavDrawerData result = new NavDrawerData(feeds, queueSize, numNewItems, feedCounters); + NavDrawerData result = new NavDrawerData(feeds, queueSize, numNewItems, numDownloadedItems, feedCounters); adapter.close(); return result; } @@ -1032,10 +1032,12 @@ public final class DBReader { public NavDrawerData(List feeds, int queueSize, int numNewItems, + int numDownloadedItems, LongIntMap feedIndicatorValues) { this.feeds = feeds; this.queueSize = queueSize; this.numNewItems = numNewItems; + this.numDownloadedItems = numDownloadedItems; this.feedCounters = feedIndicatorValues; } } -- cgit v1.2.3 From 99d7992dc8af74ba8937dfd4cef2e78bacb8b9c2 Mon Sep 17 00:00:00 2001 From: Martin Fietz Date: Mon, 2 Nov 2015 15:24:18 +0100 Subject: Audio player redesign Sleep timer and audio effects (e.g. balance) accessible from actionbar, fragment pager --- .../core/preferences/UserPreferences.java | 47 ++++++++++- .../core/service/playback/PlaybackService.java | 28 +++++-- .../playback/PlaybackServiceMediaPlayer.java | 58 ++++++++----- .../antennapod/core/util/playback/AudioPlayer.java | 5 ++ .../antennapod/core/util/playback/IPlayer.java | 4 + .../core/util/playback/PlaybackController.java | 90 ++++++++++++--------- .../antennapod/core/util/playback/Timeline.java | 2 +- .../antennapod/core/util/playback/VideoPlayer.java | 11 +++ .../res/drawable-hdpi/ic_skip_grey600_36dp.png | Bin 0 -> 302 bytes .../main/res/drawable-hdpi/ic_skip_white_36dp.png | Bin 0 -> 304 bytes .../res/drawable-hdpi/ic_sleep_grey600_24dp.png | Bin 0 -> 421 bytes .../drawable-hdpi/ic_sleep_off_grey600_24dp.png | Bin 0 -> 659 bytes .../res/drawable-hdpi/ic_sleep_off_white_24dp.png | Bin 0 -> 431 bytes .../main/res/drawable-hdpi/ic_sleep_white_24dp.png | Bin 0 -> 361 bytes .../drawable-hdpi/ic_star_border_grey600_24dp.png | Bin 0 -> 637 bytes .../drawable-hdpi/ic_star_border_white_24dp.png | Bin 0 -> 637 bytes .../res/drawable-hdpi/ic_star_grey600_24dp.png | Bin 0 -> 460 bytes .../main/res/drawable-hdpi/ic_star_white_24dp.png | Bin 0 -> 454 bytes .../res/drawable-mdpi/ic_skip_grey600_36dp.png | Bin 0 -> 218 bytes .../main/res/drawable-mdpi/ic_skip_white_36dp.png | Bin 0 -> 216 bytes .../res/drawable-mdpi/ic_sleep_grey600_24dp.png | Bin 0 -> 336 bytes .../drawable-mdpi/ic_sleep_off_grey600_24dp.png | Bin 0 -> 472 bytes .../res/drawable-mdpi/ic_sleep_off_white_24dp.png | Bin 0 -> 323 bytes .../main/res/drawable-mdpi/ic_sleep_white_24dp.png | Bin 0 -> 252 bytes .../drawable-mdpi/ic_star_border_grey600_24dp.png | Bin 0 -> 410 bytes .../drawable-mdpi/ic_star_border_white_24dp.png | Bin 0 -> 410 bytes .../res/drawable-mdpi/ic_star_grey600_24dp.png | Bin 0 -> 307 bytes .../main/res/drawable-mdpi/ic_star_white_24dp.png | Bin 0 -> 302 bytes .../res/drawable-xhdpi/ic_skip_grey600_36dp.png | Bin 0 -> 364 bytes .../main/res/drawable-xhdpi/ic_skip_white_36dp.png | Bin 0 -> 368 bytes .../res/drawable-xhdpi/ic_sleep_grey600_24dp.png | Bin 0 -> 494 bytes .../drawable-xhdpi/ic_sleep_off_grey600_24dp.png | Bin 0 -> 769 bytes .../res/drawable-xhdpi/ic_sleep_off_white_24dp.png | Bin 0 -> 486 bytes .../res/drawable-xhdpi/ic_sleep_white_24dp.png | Bin 0 -> 367 bytes .../drawable-xhdpi/ic_star_border_grey600_24dp.png | Bin 0 -> 828 bytes .../drawable-xhdpi/ic_star_border_white_24dp.png | Bin 0 -> 821 bytes .../res/drawable-xhdpi/ic_star_grey600_24dp.png | Bin 0 -> 593 bytes .../main/res/drawable-xhdpi/ic_star_white_24dp.png | Bin 0 -> 582 bytes .../res/drawable-xxhdpi/ic_skip_grey600_36dp.png | Bin 0 -> 533 bytes .../res/drawable-xxhdpi/ic_skip_white_36dp.png | Bin 0 -> 543 bytes .../res/drawable-xxhdpi/ic_sleep_grey600_24dp.png | Bin 0 -> 737 bytes .../drawable-xxhdpi/ic_sleep_off_grey600_24dp.png | Bin 0 -> 1113 bytes .../drawable-xxhdpi/ic_sleep_off_white_24dp.png | Bin 0 -> 664 bytes .../res/drawable-xxhdpi/ic_sleep_white_24dp.png | Bin 0 -> 509 bytes .../ic_star_border_grey600_24dp.png | Bin 0 -> 1227 bytes .../drawable-xxhdpi/ic_star_border_white_24dp.png | Bin 0 -> 1222 bytes .../res/drawable-xxhdpi/ic_star_grey600_24dp.png | Bin 0 -> 877 bytes .../res/drawable-xxhdpi/ic_star_white_24dp.png | Bin 0 -> 870 bytes .../res/drawable-xxxhdpi/ic_skip_grey600_36dp.png | Bin 0 -> 737 bytes .../res/drawable-xxxhdpi/ic_skip_white_36dp.png | Bin 0 -> 749 bytes .../res/drawable-xxxhdpi/ic_sleep_grey600_24dp.png | Bin 0 -> 955 bytes .../drawable-xxxhdpi/ic_sleep_off_grey600_24dp.png | Bin 0 -> 1514 bytes .../drawable-xxxhdpi/ic_sleep_off_white_24dp.png | Bin 0 -> 882 bytes .../res/drawable-xxxhdpi/ic_sleep_white_24dp.png | Bin 0 -> 647 bytes .../ic_star_border_grey600_24dp.png | Bin 0 -> 1675 bytes .../drawable-xxxhdpi/ic_star_border_white_24dp.png | Bin 0 -> 1684 bytes .../res/drawable-xxxhdpi/ic_star_grey600_24dp.png | Bin 0 -> 1179 bytes .../res/drawable-xxxhdpi/ic_star_white_24dp.png | Bin 0 -> 1183 bytes core/src/main/res/values/arrays.xml | 12 +-- core/src/main/res/values/attrs.xml | 8 +- core/src/main/res/values/dimens.xml | 4 +- core/src/main/res/values/strings.xml | 13 +++ core/src/main/res/values/styles.xml | 25 +++++- 63 files changed, 230 insertions(+), 77 deletions(-) create mode 100644 core/src/main/res/drawable-hdpi/ic_skip_grey600_36dp.png create mode 100644 core/src/main/res/drawable-hdpi/ic_skip_white_36dp.png create mode 100644 core/src/main/res/drawable-hdpi/ic_sleep_grey600_24dp.png create mode 100644 core/src/main/res/drawable-hdpi/ic_sleep_off_grey600_24dp.png create mode 100644 core/src/main/res/drawable-hdpi/ic_sleep_off_white_24dp.png create mode 100644 core/src/main/res/drawable-hdpi/ic_sleep_white_24dp.png create mode 100644 core/src/main/res/drawable-hdpi/ic_star_border_grey600_24dp.png create mode 100644 core/src/main/res/drawable-hdpi/ic_star_border_white_24dp.png create mode 100644 core/src/main/res/drawable-hdpi/ic_star_grey600_24dp.png create mode 100644 core/src/main/res/drawable-hdpi/ic_star_white_24dp.png create mode 100644 core/src/main/res/drawable-mdpi/ic_skip_grey600_36dp.png create mode 100644 core/src/main/res/drawable-mdpi/ic_skip_white_36dp.png create mode 100644 core/src/main/res/drawable-mdpi/ic_sleep_grey600_24dp.png create mode 100644 core/src/main/res/drawable-mdpi/ic_sleep_off_grey600_24dp.png create mode 100644 core/src/main/res/drawable-mdpi/ic_sleep_off_white_24dp.png create mode 100644 core/src/main/res/drawable-mdpi/ic_sleep_white_24dp.png create mode 100644 core/src/main/res/drawable-mdpi/ic_star_border_grey600_24dp.png create mode 100644 core/src/main/res/drawable-mdpi/ic_star_border_white_24dp.png create mode 100644 core/src/main/res/drawable-mdpi/ic_star_grey600_24dp.png create mode 100644 core/src/main/res/drawable-mdpi/ic_star_white_24dp.png create mode 100644 core/src/main/res/drawable-xhdpi/ic_skip_grey600_36dp.png create mode 100644 core/src/main/res/drawable-xhdpi/ic_skip_white_36dp.png create mode 100644 core/src/main/res/drawable-xhdpi/ic_sleep_grey600_24dp.png create mode 100644 core/src/main/res/drawable-xhdpi/ic_sleep_off_grey600_24dp.png create mode 100644 core/src/main/res/drawable-xhdpi/ic_sleep_off_white_24dp.png create mode 100644 core/src/main/res/drawable-xhdpi/ic_sleep_white_24dp.png create mode 100644 core/src/main/res/drawable-xhdpi/ic_star_border_grey600_24dp.png create mode 100644 core/src/main/res/drawable-xhdpi/ic_star_border_white_24dp.png create mode 100644 core/src/main/res/drawable-xhdpi/ic_star_grey600_24dp.png create mode 100644 core/src/main/res/drawable-xhdpi/ic_star_white_24dp.png create mode 100644 core/src/main/res/drawable-xxhdpi/ic_skip_grey600_36dp.png create mode 100644 core/src/main/res/drawable-xxhdpi/ic_skip_white_36dp.png create mode 100644 core/src/main/res/drawable-xxhdpi/ic_sleep_grey600_24dp.png create mode 100644 core/src/main/res/drawable-xxhdpi/ic_sleep_off_grey600_24dp.png create mode 100644 core/src/main/res/drawable-xxhdpi/ic_sleep_off_white_24dp.png create mode 100644 core/src/main/res/drawable-xxhdpi/ic_sleep_white_24dp.png create mode 100644 core/src/main/res/drawable-xxhdpi/ic_star_border_grey600_24dp.png create mode 100644 core/src/main/res/drawable-xxhdpi/ic_star_border_white_24dp.png create mode 100644 core/src/main/res/drawable-xxhdpi/ic_star_grey600_24dp.png create mode 100644 core/src/main/res/drawable-xxhdpi/ic_star_white_24dp.png create mode 100644 core/src/main/res/drawable-xxxhdpi/ic_skip_grey600_36dp.png create mode 100644 core/src/main/res/drawable-xxxhdpi/ic_skip_white_36dp.png create mode 100644 core/src/main/res/drawable-xxxhdpi/ic_sleep_grey600_24dp.png create mode 100644 core/src/main/res/drawable-xxxhdpi/ic_sleep_off_grey600_24dp.png create mode 100644 core/src/main/res/drawable-xxxhdpi/ic_sleep_off_white_24dp.png create mode 100644 core/src/main/res/drawable-xxxhdpi/ic_sleep_white_24dp.png create mode 100644 core/src/main/res/drawable-xxxhdpi/ic_star_border_grey600_24dp.png create mode 100644 core/src/main/res/drawable-xxxhdpi/ic_star_border_white_24dp.png create mode 100644 core/src/main/res/drawable-xxxhdpi/ic_star_grey600_24dp.png create mode 100644 core/src/main/res/drawable-xxxhdpi/ic_star_white_24dp.png (limited to 'core/src/main') 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 d6ac8496b..6c0aff15e 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 @@ -20,7 +20,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; -import java.util.LinkedList; import java.util.List; import java.util.concurrent.TimeUnit; @@ -95,9 +94,12 @@ public class UserPreferences { public static final String PREF_QUEUE_LOCKED = "prefQueueLocked"; public static final String IMAGE_CACHE_DEFAULT_VALUE = "100"; public static final int IMAGE_CACHE_SIZE_MINIMUM = 20; + public static final String PREF_LEFT_VOLUME = "prefLeftVolume"; + public static final String PREF_RIGHT_VOLUME = "prefRightVolume"; // Experimental public static final String PREF_SONIC = "prefSonic"; + public static final String PREF_STEREO_TO_MONO = "PrefStereoToMono"; public static final String PREF_NORMALIZER = "prefNormalizer"; public static final int EPISODE_CLEANUP_QUEUE = -1; public static final int EPISODE_CLEANUP_NULL = -2; @@ -249,17 +251,37 @@ public class UserPreferences { } public static String getPlaybackSpeed() { - return prefs.getString(PREF_PLAYBACK_SPEED, "1.0"); + return prefs.getString(PREF_PLAYBACK_SPEED, "1.00"); } public static String[] getPlaybackSpeedArray() { return readPlaybackSpeedArray(prefs.getString(PREF_PLAYBACK_SPEED_ARRAY, null)); } + public static float getLeftVolume() { + int volume = prefs.getInt(PREF_LEFT_VOLUME, 100); + if(volume == 100) { + return 1.0f; + } else { + return (float) (1 - (Math.log(100 - volume) / Math.log(100))); + } + } + + public static float getRightVolume() { + int volume = prefs.getInt(PREF_RIGHT_VOLUME, 100); + if(volume == 100) { + return 1.0f; + } else { + return (float) (1 - (Math.log(100 - volume) / Math.log(100))); + } + } + public static boolean shouldPauseForFocusLoss() { return prefs.getBoolean(PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS, false); } + + public static long getUpdateInterval() { String updateInterval = prefs.getString(PREF_UPDATE_INTERVAL, "0"); if(false == updateInterval.contains(":")) { @@ -385,6 +407,15 @@ public class UserPreferences { .apply(); } + public static void setVolume(int leftVolume, int rightVolume) { + assert(0 <= leftVolume && leftVolume <= 100); + assert(0 <= rightVolume && rightVolume <= 100); + prefs.edit() + .putInt(PREF_LEFT_VOLUME, leftVolume) + .putInt(PREF_RIGHT_VOLUME, rightVolume) + .apply(); + } + public static void setAutodownloadSelectedNetworks(String[] value) { prefs.edit() .putString(PREF_AUTODL_SELECTED_NETWORKS, TextUtils.join(",", value)) @@ -472,7 +503,7 @@ public class UserPreferences { // If this preference hasn't been set yet, return the default options if (valueFromPrefs == null) { String[] allSpeeds = context.getResources().getStringArray(R.array.playback_speed_values); - List speedList = new LinkedList(); + List speedList = new ArrayList<>(); for (String speedStr : allSpeeds) { float speed = Float.parseFloat(speedStr); if (speed < 2.0001 && speed * 10 % 1 == 0) { @@ -505,6 +536,16 @@ public class UserPreferences { .apply(); } + public static boolean stereoToMono() { + return prefs.getBoolean(PREF_STEREO_TO_MONO, false); + } + + public static void stereoToMono(boolean enable) { + prefs.edit() + .putBoolean(PREF_STEREO_TO_MONO, enable) + .apply(); + } + public static EpisodeCleanupAlgorithm getEpisodeCleanupAlgorithm() { int cleanupValue = Integer.valueOf(prefs.getString(PREF_EPISODE_CLEANUP, "-1")); 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 129055f92..2be075a92 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 @@ -398,19 +398,25 @@ public class PlaybackService extends Service { @Override public void onSleepTimerAlmostExpired() { - mediaPlayer.setVolume(0.1f); + float leftVolume = 0.1f * UserPreferences.getLeftVolume(); + float rightVolume = 0.1f * UserPreferences.getRightVolume(); + mediaPlayer.setVolume(leftVolume, rightVolume); } @Override public void onSleepTimerExpired() { mediaPlayer.pause(true, true); - mediaPlayer.setVolume(1.0f); + float leftVolume = UserPreferences.getLeftVolume(); + float rightVolume = UserPreferences.getRightVolume(); + mediaPlayer.setVolume(leftVolume, rightVolume); sendNotificationBroadcast(NOTIFICATION_TYPE_SLEEPTIMER_UPDATE, 0); } @Override public void onSleepTimerReset() { - mediaPlayer.setVolume(1.0f); + float leftVolume = UserPreferences.getLeftVolume(); + float rightVolume = UserPreferences.getRightVolume(); + mediaPlayer.setVolume(leftVolume, rightVolume); } @Override @@ -1165,18 +1171,30 @@ public class PlaybackService extends Service { public Playable getPlayable() { return mediaPlayer.getPlayable(); } + public boolean canSetSpeed() { + return mediaPlayer.canSetSpeed(); + } + public void setSpeed(float speed) { mediaPlayer.setSpeed(speed); } - public boolean canSetSpeed() { - return mediaPlayer.canSetSpeed(); + public void setVolume(float leftVolume, float rightVolume) { + mediaPlayer.setVolume(leftVolume, rightVolume); } public float getCurrentPlaybackSpeed() { return mediaPlayer.getPlaybackSpeed(); } + public boolean canDownmix() { + return mediaPlayer.canDownmix(); + } + + public void setDownmix(boolean enable) { + mediaPlayer.setDownmix(enable); + } + public boolean isStartWhenPrepared() { return mediaPlayer.isStartWhenPrepared(); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java index e26ee32cb..aa73b17a7 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackServiceMediaPlayer.java @@ -24,6 +24,7 @@ import android.view.SurfaceHolder; import android.view.WindowManager; import com.bumptech.glide.Glide; +import com.bumptech.glide.request.target.Target; import java.io.IOException; import java.util.concurrent.CountDownLatch; @@ -293,6 +294,7 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre builder.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, p.getDuration()); builder.putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, p.getEpisodeTitle()); builder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, p.getFeedTitle()); + if (p.getImageUri() != null && UserPreferences.setLockscreenBackground()) { builder.putString(MediaMetadataCompat.METADATA_KEY_ART_URI, p.getImageUri().toString()); try { @@ -322,13 +324,10 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre * This method is executed on an internal executor service. */ public void resume() { - executor.submit(new Runnable() { - @Override - public void run() { - playerLock.lock(); - resumeSync(); - playerLock.unlock(); - } + executor.submit(() -> { + playerLock.lock(); + resumeSync(); + playerLock.unlock(); }); } @@ -339,7 +338,15 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre AudioManager.AUDIOFOCUS_GAIN); if (focusGained == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { acquireWifiLockIfNecessary(); - setSpeed(Float.parseFloat(UserPreferences.getPlaybackSpeed())); + float speed = 1.0f; + try { + speed = Float.parseFloat(UserPreferences.getPlaybackSpeed()); + } catch(NumberFormatException e) { + Log.e(TAG, Log.getStackTraceString(e)); + UserPreferences.setPlaybackSpeed(String.valueOf(speed)); + } + setSpeed(speed); + setVolume(UserPreferences.getLeftVolume(), UserPreferences.getRightVolume()); if (playerStatus == PlayerStatus.PREPARED && media.getPosition() > 0) { int newPosition = RewindAfterPauseUtils.calculatePositionWithRewind( @@ -690,24 +697,39 @@ public class PlaybackServiceMediaPlayer implements SharedPreferences.OnSharedPre * Sets the playback speed. * This method is executed on an internal executor service. */ - public void setVolume(final float volume) { - executor.submit(new Runnable() { - @Override - public void run() { - setVolumeSync(volume); - } - }); + public void setVolume(final float volumeLeft, float volumeRight) { + executor.submit(() -> setVolumeSync(volumeLeft, volumeRight)); } /** * Sets the playback speed. * This method is executed on the caller's thread. */ - private void setVolumeSync(float volume) { + private void setVolumeSync(float volumeLeft, float volumeRight) { + playerLock.lock(); + if (media != null && media.getMediaType() == MediaType.AUDIO) { + mediaPlayer.setVolume(volumeLeft, volumeRight); + Log.d(TAG, "Media player volume was set to " + volumeLeft + " " + volumeRight); + } + playerLock.unlock(); + } + + /** + * Returns true if the mediaplayer can mix stereo down to mono + */ + public boolean canDownmix() { + boolean retVal = false; + if (mediaPlayer != null && media != null && media.getMediaType() == MediaType.AUDIO) { + retVal = mediaPlayer.canDownmix(); + } + return retVal; + } + + public void setDownmix(boolean enable) { playerLock.lock(); if (media != null && media.getMediaType() == MediaType.AUDIO) { - mediaPlayer.setVolume(volume, volume); - Log.d(TAG, "Media player volume was set to " + volume); + mediaPlayer.setDownmix(enable); + Log.d(TAG, "Media player downmix was set to " + enable); } playerLock.unlock(); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java index b6beb5bf1..f0850e6df 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/AudioPlayer.java @@ -37,4 +37,9 @@ public class AudioPlayer extends MediaPlayer implements IPlayer { protected boolean useSonic() { return UserPreferences.useSonic(); } + + @Override + protected boolean downmix() { + return UserPreferences.stereoToMono(); + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/IPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/IPlayer.java index 147c7848d..d67153a4e 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/IPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/IPlayer.java @@ -10,6 +10,8 @@ public interface IPlayer { boolean canSetSpeed(); + boolean canDownmix(); + float getCurrentPitchStepsAdjustment(); int getCurrentPosition(); @@ -57,6 +59,8 @@ public interface IPlayer { void setPlaybackSpeed(float f); + void setDownmix(boolean enable); + void setVolume(float left, float right); void start(); 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 a519fb555..1952c068f 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 @@ -27,7 +27,6 @@ import android.widget.TextView; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -48,6 +47,7 @@ import de.danoeh.antennapod.core.util.playback.Playable.PlayableUtils; * control playback instead of communicating with the PlaybackService directly. */ public abstract class PlaybackController { + private static final String TAG = "PlaybackController"; public static final int INVALID_TIME = -1; @@ -78,23 +78,18 @@ public abstract class PlaybackController { this.activity = activity; this.reinitOnPause = reinitOnPause; schedExecutor = new ScheduledThreadPoolExecutor(SCHED_EX_POOLSIZE, - new ThreadFactory() { - - @Override - public Thread newThread(Runnable r) { - Thread t = new Thread(r); - t.setPriority(Thread.MIN_PRIORITY); - return t; - } - }, new RejectedExecutionHandler() { - - @Override - public void rejectedExecution(Runnable r, - ThreadPoolExecutor executor) { - Log.w(TAG, + r -> { + Thread t = new Thread(r); + t.setPriority(Thread.MIN_PRIORITY); + return t; + }, new RejectedExecutionHandler() { + @Override + public void rejectedExecution(Runnable r, + ThreadPoolExecutor executor) { + Log.w(TAG, "Rejected execution of runnable in schedExecutor"); + } } - } ); } @@ -104,10 +99,10 @@ public abstract class PlaybackController { */ public void init() { activity.registerReceiver(statusUpdate, new IntentFilter( - PlaybackService.ACTION_PLAYER_STATUS_CHANGED)); + PlaybackService.ACTION_PLAYER_STATUS_CHANGED)); activity.registerReceiver(notificationReceiver, new IntentFilter( - PlaybackService.ACTION_PLAYER_NOTIFICATION)); + PlaybackService.ACTION_PLAYER_NOTIFICATION)); activity.registerReceiver(shutdownReceiver, new IntentFilter( PlaybackService.ACTION_SHUTDOWN_PLAYBACK_SERVICE)); @@ -239,7 +234,7 @@ public abstract class PlaybackController { return null; } - public abstract void setupGUI(); + private void setupPositionObserver() { if ((positionObserverFuture != null && positionObserverFuture @@ -263,8 +258,6 @@ public abstract class PlaybackController { } } - public abstract void onPositionObserverUpdate(); - private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { playbackService = ((PlaybackService.LocalBinder) service) @@ -367,26 +360,31 @@ public abstract class PlaybackController { } }; - public abstract void onPlaybackSpeedChange(); + public void setupGUI() {}; + + public void onPositionObserverUpdate() {}; + - public abstract void onShutdownNotification(); + public void onPlaybackSpeedChange() {}; + + public void onShutdownNotification() {}; /** * Called when the currently displayed information should be refreshed. */ - public abstract void onReloadNotification(int code); + public void onReloadNotification(int code) {}; - public abstract void onBufferStart(); + public void onBufferStart() {}; - public abstract void onBufferEnd(); + public void onBufferEnd() {}; - public abstract void onBufferUpdate(float progress); + public void onBufferUpdate(float progress) {}; - public abstract void onSleepTimerUpdate(); + public void onSleepTimerUpdate() {}; - public abstract void handleError(int code); + public void handleError(int code) {}; - public abstract void onPlaybackEnd(); + public void onPlaybackEnd() {}; public void repeatHandleStatus() { if (status != null && playbackService != null) { @@ -484,15 +482,19 @@ public abstract class PlaybackController { } } - public abstract ImageButton getPlayButton(); + public ImageButton getPlayButton() { + return null; + }; - public abstract void postStatusMsg(int msg); + public void postStatusMsg(int msg) {}; - public abstract void clearStatusMsg(); + public void clearStatusMsg() {}; - public abstract boolean loadMediaInfo(); + public boolean loadMediaInfo() { + return false; + }; - public abstract void onAwaitingVideoSurface(); + public void onAwaitingVideoSurface() {}; /** * Called when connection to playback service has been established or @@ -526,7 +528,7 @@ public abstract class PlaybackController { } } - public abstract void onServiceQueried(); + public void onServiceQueried() {}; /** * Should be used by classes which implement the OnSeekBarChanged interface. @@ -691,6 +693,12 @@ public abstract class PlaybackController { } } + public void setVolume(float leftVolume, float rightVolume) { + if (playbackService != null) { + playbackService.setVolume(leftVolume, rightVolume); + } + } + public float getCurrentPlaybackSpeedMultiplier() { if (canSetPlaybackSpeed()) { return playbackService.getCurrentPlaybackSpeed(); @@ -699,6 +707,16 @@ public abstract class PlaybackController { } } + public boolean canDownmix() { + return playbackService != null && playbackService.canDownmix(); + } + + public void setDownmix(boolean enable) { + if(playbackService != null) { + playbackService.setDownmix(enable); + } + } + public boolean isPlayingVideo() { if (playbackService != null) { return PlaybackService.getCurrentMediaType() == MediaType.VIDEO; diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java index 00f2e6f57..2eee1ac87 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/Timeline.java @@ -88,7 +88,7 @@ public class Timeline { } // replace ASCII line breaks with HTML ones if shownotes don't contain HTML line breaks already - if(!LINE_BREAK_REGEX.matcher(shownotes).find()) { + if(!LINE_BREAK_REGEX.matcher(shownotes).find() && !shownotes.contains("

")) { shownotes = shownotes.replace("\n", "
"); } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/playback/VideoPlayer.java b/core/src/main/java/de/danoeh/antennapod/core/util/playback/VideoPlayer.java index dc5270d8f..368379509 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/playback/VideoPlayer.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/playback/VideoPlayer.java @@ -16,6 +16,11 @@ public class VideoPlayer extends MediaPlayer implements IPlayer { return false; } + @Override + public boolean canDownmix() { + return false; + } + @Override public float getCurrentPitchStepsAdjustment() { return 1; @@ -60,6 +65,12 @@ public class VideoPlayer extends MediaPlayer implements IPlayer { throw new UnsupportedOperationException("Setting playback speed unsupported in video player"); } + @Override + public void setDownmix(boolean b) { + Log.e(TAG, "Setting downmix unsupported in video player"); + throw new UnsupportedOperationException("Setting downmix unsupported in video player"); + } + @Override public void setVideoScalingMode(int mode) { super.setVideoScalingMode(mode); diff --git a/core/src/main/res/drawable-hdpi/ic_skip_grey600_36dp.png b/core/src/main/res/drawable-hdpi/ic_skip_grey600_36dp.png new file mode 100644 index 000000000..edbc95b05 Binary files /dev/null and b/core/src/main/res/drawable-hdpi/ic_skip_grey600_36dp.png differ diff --git a/core/src/main/res/drawable-hdpi/ic_skip_white_36dp.png b/core/src/main/res/drawable-hdpi/ic_skip_white_36dp.png new file mode 100644 index 000000000..cbfb262d8 Binary files /dev/null and b/core/src/main/res/drawable-hdpi/ic_skip_white_36dp.png differ diff --git a/core/src/main/res/drawable-hdpi/ic_sleep_grey600_24dp.png b/core/src/main/res/drawable-hdpi/ic_sleep_grey600_24dp.png new file mode 100644 index 000000000..809066499 Binary files /dev/null and b/core/src/main/res/drawable-hdpi/ic_sleep_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-hdpi/ic_sleep_off_grey600_24dp.png b/core/src/main/res/drawable-hdpi/ic_sleep_off_grey600_24dp.png new file mode 100644 index 000000000..4496a320d Binary files /dev/null and b/core/src/main/res/drawable-hdpi/ic_sleep_off_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-hdpi/ic_sleep_off_white_24dp.png b/core/src/main/res/drawable-hdpi/ic_sleep_off_white_24dp.png new file mode 100644 index 000000000..79684ab65 Binary files /dev/null and b/core/src/main/res/drawable-hdpi/ic_sleep_off_white_24dp.png differ diff --git a/core/src/main/res/drawable-hdpi/ic_sleep_white_24dp.png b/core/src/main/res/drawable-hdpi/ic_sleep_white_24dp.png new file mode 100644 index 000000000..f0df6032c Binary files /dev/null and b/core/src/main/res/drawable-hdpi/ic_sleep_white_24dp.png differ diff --git a/core/src/main/res/drawable-hdpi/ic_star_border_grey600_24dp.png b/core/src/main/res/drawable-hdpi/ic_star_border_grey600_24dp.png new file mode 100644 index 000000000..006410bc3 Binary files /dev/null and b/core/src/main/res/drawable-hdpi/ic_star_border_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-hdpi/ic_star_border_white_24dp.png b/core/src/main/res/drawable-hdpi/ic_star_border_white_24dp.png new file mode 100644 index 000000000..27831192f Binary files /dev/null and b/core/src/main/res/drawable-hdpi/ic_star_border_white_24dp.png differ diff --git a/core/src/main/res/drawable-hdpi/ic_star_grey600_24dp.png b/core/src/main/res/drawable-hdpi/ic_star_grey600_24dp.png new file mode 100644 index 000000000..93f70a024 Binary files /dev/null and b/core/src/main/res/drawable-hdpi/ic_star_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-hdpi/ic_star_white_24dp.png b/core/src/main/res/drawable-hdpi/ic_star_white_24dp.png new file mode 100644 index 000000000..e8619b780 Binary files /dev/null and b/core/src/main/res/drawable-hdpi/ic_star_white_24dp.png differ diff --git a/core/src/main/res/drawable-mdpi/ic_skip_grey600_36dp.png b/core/src/main/res/drawable-mdpi/ic_skip_grey600_36dp.png new file mode 100644 index 000000000..be0fcc765 Binary files /dev/null and b/core/src/main/res/drawable-mdpi/ic_skip_grey600_36dp.png differ diff --git a/core/src/main/res/drawable-mdpi/ic_skip_white_36dp.png b/core/src/main/res/drawable-mdpi/ic_skip_white_36dp.png new file mode 100644 index 000000000..893cf2c64 Binary files /dev/null and b/core/src/main/res/drawable-mdpi/ic_skip_white_36dp.png differ diff --git a/core/src/main/res/drawable-mdpi/ic_sleep_grey600_24dp.png b/core/src/main/res/drawable-mdpi/ic_sleep_grey600_24dp.png new file mode 100644 index 000000000..ea511bf2a Binary files /dev/null and b/core/src/main/res/drawable-mdpi/ic_sleep_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-mdpi/ic_sleep_off_grey600_24dp.png b/core/src/main/res/drawable-mdpi/ic_sleep_off_grey600_24dp.png new file mode 100644 index 000000000..7f631ad86 Binary files /dev/null and b/core/src/main/res/drawable-mdpi/ic_sleep_off_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-mdpi/ic_sleep_off_white_24dp.png b/core/src/main/res/drawable-mdpi/ic_sleep_off_white_24dp.png new file mode 100644 index 000000000..795e318e3 Binary files /dev/null and b/core/src/main/res/drawable-mdpi/ic_sleep_off_white_24dp.png differ diff --git a/core/src/main/res/drawable-mdpi/ic_sleep_white_24dp.png b/core/src/main/res/drawable-mdpi/ic_sleep_white_24dp.png new file mode 100644 index 000000000..4304a6bca Binary files /dev/null and b/core/src/main/res/drawable-mdpi/ic_sleep_white_24dp.png differ diff --git a/core/src/main/res/drawable-mdpi/ic_star_border_grey600_24dp.png b/core/src/main/res/drawable-mdpi/ic_star_border_grey600_24dp.png new file mode 100644 index 000000000..dd9d11ba0 Binary files /dev/null and b/core/src/main/res/drawable-mdpi/ic_star_border_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-mdpi/ic_star_border_white_24dp.png b/core/src/main/res/drawable-mdpi/ic_star_border_white_24dp.png new file mode 100644 index 000000000..104fb3c9d Binary files /dev/null and b/core/src/main/res/drawable-mdpi/ic_star_border_white_24dp.png differ diff --git a/core/src/main/res/drawable-mdpi/ic_star_grey600_24dp.png b/core/src/main/res/drawable-mdpi/ic_star_grey600_24dp.png new file mode 100644 index 000000000..af84b71f2 Binary files /dev/null and b/core/src/main/res/drawable-mdpi/ic_star_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-mdpi/ic_star_white_24dp.png b/core/src/main/res/drawable-mdpi/ic_star_white_24dp.png new file mode 100644 index 000000000..0ccebc7c8 Binary files /dev/null and b/core/src/main/res/drawable-mdpi/ic_star_white_24dp.png differ diff --git a/core/src/main/res/drawable-xhdpi/ic_skip_grey600_36dp.png b/core/src/main/res/drawable-xhdpi/ic_skip_grey600_36dp.png new file mode 100644 index 000000000..2e291dd19 Binary files /dev/null and b/core/src/main/res/drawable-xhdpi/ic_skip_grey600_36dp.png differ diff --git a/core/src/main/res/drawable-xhdpi/ic_skip_white_36dp.png b/core/src/main/res/drawable-xhdpi/ic_skip_white_36dp.png new file mode 100644 index 000000000..fa85f1899 Binary files /dev/null and b/core/src/main/res/drawable-xhdpi/ic_skip_white_36dp.png differ diff --git a/core/src/main/res/drawable-xhdpi/ic_sleep_grey600_24dp.png b/core/src/main/res/drawable-xhdpi/ic_sleep_grey600_24dp.png new file mode 100644 index 000000000..ae0787a26 Binary files /dev/null and b/core/src/main/res/drawable-xhdpi/ic_sleep_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-xhdpi/ic_sleep_off_grey600_24dp.png b/core/src/main/res/drawable-xhdpi/ic_sleep_off_grey600_24dp.png new file mode 100644 index 000000000..026224c5e Binary files /dev/null and b/core/src/main/res/drawable-xhdpi/ic_sleep_off_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-xhdpi/ic_sleep_off_white_24dp.png b/core/src/main/res/drawable-xhdpi/ic_sleep_off_white_24dp.png new file mode 100644 index 000000000..ef39d7279 Binary files /dev/null and b/core/src/main/res/drawable-xhdpi/ic_sleep_off_white_24dp.png differ diff --git a/core/src/main/res/drawable-xhdpi/ic_sleep_white_24dp.png b/core/src/main/res/drawable-xhdpi/ic_sleep_white_24dp.png new file mode 100644 index 000000000..07e156172 Binary files /dev/null and b/core/src/main/res/drawable-xhdpi/ic_sleep_white_24dp.png differ diff --git a/core/src/main/res/drawable-xhdpi/ic_star_border_grey600_24dp.png b/core/src/main/res/drawable-xhdpi/ic_star_border_grey600_24dp.png new file mode 100644 index 000000000..5160319b5 Binary files /dev/null and b/core/src/main/res/drawable-xhdpi/ic_star_border_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-xhdpi/ic_star_border_white_24dp.png b/core/src/main/res/drawable-xhdpi/ic_star_border_white_24dp.png new file mode 100644 index 000000000..33f9727d3 Binary files /dev/null and b/core/src/main/res/drawable-xhdpi/ic_star_border_white_24dp.png differ diff --git a/core/src/main/res/drawable-xhdpi/ic_star_grey600_24dp.png b/core/src/main/res/drawable-xhdpi/ic_star_grey600_24dp.png new file mode 100644 index 000000000..7a09ebc33 Binary files /dev/null and b/core/src/main/res/drawable-xhdpi/ic_star_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-xhdpi/ic_star_white_24dp.png b/core/src/main/res/drawable-xhdpi/ic_star_white_24dp.png new file mode 100644 index 000000000..288799f93 Binary files /dev/null and b/core/src/main/res/drawable-xhdpi/ic_star_white_24dp.png differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_skip_grey600_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_skip_grey600_36dp.png new file mode 100644 index 000000000..00a55a0f8 Binary files /dev/null and b/core/src/main/res/drawable-xxhdpi/ic_skip_grey600_36dp.png differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_skip_white_36dp.png b/core/src/main/res/drawable-xxhdpi/ic_skip_white_36dp.png new file mode 100644 index 000000000..ac38e6d42 Binary files /dev/null and b/core/src/main/res/drawable-xxhdpi/ic_skip_white_36dp.png differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_sleep_grey600_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_sleep_grey600_24dp.png new file mode 100644 index 000000000..f4bd9e94d Binary files /dev/null and b/core/src/main/res/drawable-xxhdpi/ic_sleep_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_sleep_off_grey600_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_sleep_off_grey600_24dp.png new file mode 100644 index 000000000..6c42d6051 Binary files /dev/null and b/core/src/main/res/drawable-xxhdpi/ic_sleep_off_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_sleep_off_white_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_sleep_off_white_24dp.png new file mode 100644 index 000000000..b8e06f9b3 Binary files /dev/null and b/core/src/main/res/drawable-xxhdpi/ic_sleep_off_white_24dp.png differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_sleep_white_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_sleep_white_24dp.png new file mode 100644 index 000000000..e2249c357 Binary files /dev/null and b/core/src/main/res/drawable-xxhdpi/ic_sleep_white_24dp.png differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_star_border_grey600_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_star_border_grey600_24dp.png new file mode 100644 index 000000000..6348e1997 Binary files /dev/null and b/core/src/main/res/drawable-xxhdpi/ic_star_border_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_star_border_white_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_star_border_white_24dp.png new file mode 100644 index 000000000..aab4831ff Binary files /dev/null and b/core/src/main/res/drawable-xxhdpi/ic_star_border_white_24dp.png differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_star_grey600_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_star_grey600_24dp.png new file mode 100644 index 000000000..ef0294931 Binary files /dev/null and b/core/src/main/res/drawable-xxhdpi/ic_star_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-xxhdpi/ic_star_white_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_star_white_24dp.png new file mode 100644 index 000000000..de4b7b29d Binary files /dev/null and b/core/src/main/res/drawable-xxhdpi/ic_star_white_24dp.png differ diff --git a/core/src/main/res/drawable-xxxhdpi/ic_skip_grey600_36dp.png b/core/src/main/res/drawable-xxxhdpi/ic_skip_grey600_36dp.png new file mode 100644 index 000000000..94836e0c8 Binary files /dev/null and b/core/src/main/res/drawable-xxxhdpi/ic_skip_grey600_36dp.png differ diff --git a/core/src/main/res/drawable-xxxhdpi/ic_skip_white_36dp.png b/core/src/main/res/drawable-xxxhdpi/ic_skip_white_36dp.png new file mode 100644 index 000000000..a84f34228 Binary files /dev/null and b/core/src/main/res/drawable-xxxhdpi/ic_skip_white_36dp.png differ diff --git a/core/src/main/res/drawable-xxxhdpi/ic_sleep_grey600_24dp.png b/core/src/main/res/drawable-xxxhdpi/ic_sleep_grey600_24dp.png new file mode 100644 index 000000000..9c0116c60 Binary files /dev/null and b/core/src/main/res/drawable-xxxhdpi/ic_sleep_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-xxxhdpi/ic_sleep_off_grey600_24dp.png b/core/src/main/res/drawable-xxxhdpi/ic_sleep_off_grey600_24dp.png new file mode 100644 index 000000000..e8141d0df Binary files /dev/null and b/core/src/main/res/drawable-xxxhdpi/ic_sleep_off_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-xxxhdpi/ic_sleep_off_white_24dp.png b/core/src/main/res/drawable-xxxhdpi/ic_sleep_off_white_24dp.png new file mode 100644 index 000000000..ca41ad5e6 Binary files /dev/null and b/core/src/main/res/drawable-xxxhdpi/ic_sleep_off_white_24dp.png differ diff --git a/core/src/main/res/drawable-xxxhdpi/ic_sleep_white_24dp.png b/core/src/main/res/drawable-xxxhdpi/ic_sleep_white_24dp.png new file mode 100644 index 000000000..29782e155 Binary files /dev/null and b/core/src/main/res/drawable-xxxhdpi/ic_sleep_white_24dp.png differ diff --git a/core/src/main/res/drawable-xxxhdpi/ic_star_border_grey600_24dp.png b/core/src/main/res/drawable-xxxhdpi/ic_star_border_grey600_24dp.png new file mode 100644 index 000000000..1109e95c8 Binary files /dev/null and b/core/src/main/res/drawable-xxxhdpi/ic_star_border_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-xxxhdpi/ic_star_border_white_24dp.png b/core/src/main/res/drawable-xxxhdpi/ic_star_border_white_24dp.png new file mode 100644 index 000000000..086cb677c Binary files /dev/null and b/core/src/main/res/drawable-xxxhdpi/ic_star_border_white_24dp.png differ diff --git a/core/src/main/res/drawable-xxxhdpi/ic_star_grey600_24dp.png b/core/src/main/res/drawable-xxxhdpi/ic_star_grey600_24dp.png new file mode 100644 index 000000000..dda3262ed Binary files /dev/null and b/core/src/main/res/drawable-xxxhdpi/ic_star_grey600_24dp.png differ diff --git a/core/src/main/res/drawable-xxxhdpi/ic_star_white_24dp.png b/core/src/main/res/drawable-xxxhdpi/ic_star_white_24dp.png new file mode 100644 index 000000000..ba29292b0 Binary files /dev/null and b/core/src/main/res/drawable-xxxhdpi/ic_star_white_24dp.png differ diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 341a7e520..80e3d57f5 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -75,15 +75,15 @@ - 0.5 - 0.6 - 0.7 + 0.50 + 0.60 + 0.70 0.75 - 0.8 + 0.80 0.85 - 0.9 + 0.90 0.95 - 1.0 + 1.00 1.05 1.10 1.15 diff --git a/core/src/main/res/values/attrs.xml b/core/src/main/res/values/attrs.xml index 4e444c990..7adf8295b 100644 --- a/core/src/main/res/values/attrs.xml +++ b/core/src/main/res/values/attrs.xml @@ -13,7 +13,6 @@ - @@ -37,15 +36,20 @@ + + + + + - \ No newline at end of file + diff --git a/core/src/main/res/values/dimens.xml b/core/src/main/res/values/dimens.xml index aa57e3051..9aafd14e3 100644 --- a/core/src/main/res/values/dimens.xml +++ b/core/src/main/res/values/dimens.xml @@ -33,6 +33,6 @@ 16dp 16dp - 64dp + 48dp - \ No newline at end of file + diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 443a1a8a8..fa54ad22e 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -148,7 +148,9 @@ Added to Queue Remove from Queue Add to Favorites + Added to Favorites Remove from Favorites + Removed from Favorites Visit Website Flattr this Enqueue all @@ -268,6 +270,7 @@ There are no items in this list. You haven\'t subscribed to any feeds yet. + This episode has no chapters. Other @@ -555,4 +558,14 @@ Remind me later Sure, let\'s do this! + + Audio controls + Playback Speed + Volume + L + R + Audio Effects + Downmix: Stereo to mono + Sonic only + diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index 1f73fbba2..45e1206b7 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -18,7 +18,6 @@ @drawable/ic_fast_rewind_grey600_24dp @drawable/ic_delete_grey600_24dp @drawable/ic_add_grey600_24dp - @drawable/ic_timer_grey600_24dp @drawable/ic_feed_grey600_24dp @drawable/ic_web_grey600_24dp @drawable/ic_done_grey600_24dp @@ -45,10 +44,16 @@ @drawable/ic_pause_grey600_36dp @drawable/ic_fast_forward_grey600_36dp @drawable/ic_fast_rewind_grey600_36dp + @drawable/ic_skip_grey600_36dp + @drawable/ic_star_border_grey600_24dp + @drawable/ic_star_grey600_24dp @drawable/ic_settings_grey600_24dp @drawable/ic_lock_open_grey600_24dp @drawable/ic_lock_closed_grey600_24dp @drawable/ic_filter_grey600_24dp + @drawable/ic_sleep_grey600_24dp + @drawable/ic_sleep_off_grey600_24dp + + +