summaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
Diffstat (limited to 'app/src')
-rw-r--r--app/src/androidTest/java/de/test/antennapod/feed/FeedItemTest.java37
-rw-r--r--app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java10
-rw-r--r--app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java32
-rw-r--r--app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java2
-rw-r--r--app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java2
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBCleanupTests.java12
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBQueueCleanupAlgorithmTest.java1
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java6
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java2
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java191
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java12
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java4
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java4
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java63
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java33
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java6
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java5
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/RewindAfterPauseUtilTest.java4
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/URIUtilTest.java1
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/URLCheckerTest.java1
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/service/download/HTTPBin.java2
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/service/download/NanoHTTPD.java132
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/syndication/FeedDiscovererTest.java4
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/AtomGenerator.java2
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/FeedGenerator.java6
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/GeneratorUtil.java2
-rw-r--r--app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/RSS2Generator.java8
-rw-r--r--app/src/free/java/de/danoeh/antennapod/config/CastCallbackImpl.java2
-rw-r--r--app/src/free/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java2
-rw-r--r--app/src/main/AndroidManifest.xml39
-rw-r--r--app/src/main/assets/LICENSE_SIL.txt91
-rwxr-xr-xapp/src/main/assets/logo.pngbin58799 -> 60183 bytes
-rw-r--r--app/src/main/java/de/danoeh/antennapod/PodcastApp.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java140
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java24
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java49
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java248
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/FeedSettingsActivity.java370
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/FlattrAuthActivity.java7
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/ImportExportActivity.java188
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java65
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java167
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java51
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java102
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java95
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java97
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java49
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java181
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java8
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonCallback.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java32
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java7
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java1
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java22
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java12
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java12
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java17
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java27
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java12
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java18
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java3
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java1
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java12
-rw-r--r--app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java12
-rw-r--r--app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java7
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java10
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java1
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java81
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java13
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java82
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java19
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java31
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java12
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java112
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java35
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java50
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java53
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java35
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java63
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java51
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java10
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastTopListFragment.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java10
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java3
-rw-r--r--app/src/main/java/de/danoeh/antennapod/preferences/MasterSwitchPreference.java47
-rw-r--r--app/src/main/java/de/danoeh/antennapod/preferences/NumberPickerPreference.java106
-rw-r--r--app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java743
-rw-r--r--app/src/main/java/de/danoeh/antennapod/preferences/SwitchCompatPreference.java37
-rw-r--r--app/src/main/java/de/danoeh/antennapod/receiver/PlayerWidget.java80
-rw-r--r--app/src/main/java/de/danoeh/antennapod/receiver/SPAReceiver.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/service/PlayerWidgetService.java245
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/AspectRatioVideoView.java22
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/SquareImageView.java5
-rw-r--r--app/src/main/play/ar/listing/fulldescription2
-rw-r--r--app/src/main/play/bg/listing/fulldescription43
-rw-r--r--app/src/main/play/ca/listing/fulldescription68
-rw-r--r--app/src/main/play/ca/listing/video0
-rw-r--r--app/src/main/play/contactPhone0
-rw-r--r--app/src/main/play/cs-CZ/listing/video0
-rw-r--r--app/src/main/play/da-DK/listing/video0
-rw-r--r--app/src/main/play/de-DE/listing/video0
-rw-r--r--app/src/main/play/de/listing/fulldescription4
-rw-r--r--app/src/main/play/el/listing/fulldescription26
-rw-r--r--app/src/main/play/en-US/listing/featureGraphic/feature-graphic.pngbin0 -> 60183 bytes
-rw-r--r--app/src/main/play/en-US/listing/video0
-rw-r--r--app/src/main/play/es-ES/listing/video0
-rw-r--r--app/src/main/play/es/listing/fulldescription2
-rw-r--r--app/src/main/play/fa/listing/fulldescription4
-rw-r--r--app/src/main/play/fr-FR/listing/video0
-rw-r--r--app/src/main/play/he_IL/listing/fulldescription62
-rw-r--r--app/src/main/play/hi-IN/listing/video0
-rw-r--r--app/src/main/play/it-IT/listing/video0
-rw-r--r--app/src/main/play/it/listing/fulldescription38
-rw-r--r--app/src/main/play/it_IT/listing/fulldescription24
-rw-r--r--app/src/main/play/iw-IL/listing/video0
-rw-r--r--app/src/main/play/ja-JP/listing/video0
-rw-r--r--app/src/main/play/ko-KR/listing/video0
-rw-r--r--app/src/main/play/ms_MY/listing/fulldescription43
-rw-r--r--app/src/main/play/nb_NO/listing/fulldescription8
-rw-r--r--app/src/main/play/nl-NL/listing/video0
-rw-r--r--app/src/main/play/pl-PL/listing/video0
-rw-r--r--app/src/main/play/pt-BR/listing/video0
-rw-r--r--app/src/main/play/pt-PT/listing/video0
-rw-r--r--app/src/main/play/ro/listing/video0
-rw-r--r--app/src/main/play/ru-RU/listing/video0
-rw-r--r--app/src/main/play/sl_SI/listing/fulldescription43
-rw-r--r--app/src/main/play/sv-SE/listing/video0
-rw-r--r--app/src/main/play/tr-TR/listing/video0
-rw-r--r--app/src/main/play/uk/listing/video0
-rw-r--r--app/src/main/play/vi/listing/fulldescription8
-rw-r--r--app/src/main/play/zh-CN/listing/video0
-rw-r--r--app/src/main/res/layout-v14/authentication_dialog.xml87
-rw-r--r--app/src/main/res/layout-v14/directory_chooser.xml114
-rw-r--r--app/src/main/res/layout-v14/download_authentication_activity.xml98
-rw-r--r--app/src/main/res/layout-v14/opml_selection.xml61
-rw-r--r--app/src/main/res/layout-v14/time_dialog.xml67
-rw-r--r--app/src/main/res/layout/about.xml4
-rw-r--r--app/src/main/res/layout/all_episodes_fragment.xml6
-rw-r--r--app/src/main/res/layout/authentication_dialog.xml57
-rw-r--r--app/src/main/res/layout/cover_fragment.xml3
-rw-r--r--app/src/main/res/layout/directory_chooser.xml59
-rw-r--r--app/src/main/res/layout/download_authentication_activity.xml51
-rw-r--r--app/src/main/res/layout/downloaded_episodeslist_item.xml85
-rw-r--r--app/src/main/res/layout/downloadlist_item.xml4
-rw-r--r--app/src/main/res/layout/downloadlog_item.xml5
-rw-r--r--app/src/main/res/layout/ellipsize_start_listitem.xml1
-rw-r--r--app/src/main/res/layout/external_player_fragment.xml152
-rw-r--r--app/src/main/res/layout/feedinfo.xml246
-rw-r--r--app/src/main/res/layout/feeditemlist_header.xml25
-rw-r--r--app/src/main/res/layout/feeditemlist_item.xml11
-rw-r--r--app/src/main/res/layout/feedsettings.xml215
-rw-r--r--app/src/main/res/layout/import_export_activity.xml34
-rw-r--r--app/src/main/res/layout/main.xml2
-rw-r--r--app/src/main/res/layout/mediaplayerinfo_activity.xml5
-rw-r--r--app/src/main/res/layout/nav_list.xml7
-rw-r--r--app/src/main/res/layout/new_episodes_listitem.xml35
-rw-r--r--app/src/main/res/layout/numberpicker.xml16
-rw-r--r--app/src/main/res/layout/opml_import.xml2
-rw-r--r--app/src/main/res/layout/opml_selection.xml50
-rw-r--r--app/src/main/res/layout/player_widget.xml52
-rw-r--r--app/src/main/res/layout/preference_switch_layout.xml9
-rw-r--r--app/src/main/res/layout/queue_listitem.xml7
-rw-r--r--app/src/main/res/layout/searchlist_item.xml9
-rw-r--r--app/src/main/res/layout/secondary_action.xml3
-rw-r--r--app/src/main/res/layout/simplechapter_item.xml2
-rw-r--r--app/src/main/res/layout/splash.xml14
-rw-r--r--app/src/main/res/layout/subscription_item.xml2
-rw-r--r--app/src/main/res/layout/time_dialog.xml9
-rw-r--r--app/src/main/res/layout/videoplayer_activity.xml4
-rw-r--r--app/src/main/res/menu/allepisodes_context.xml6
-rw-r--r--app/src/main/res/menu/downloads_completed.xml3
-rw-r--r--app/src/main/res/menu/feedlist.xml3
-rw-r--r--app/src/main/res/menu/mediaplayer.xml8
-rw-r--r--app/src/main/res/menu/queue.xml19
-rw-r--r--app/src/main/res/xml/preferences.xml361
-rw-r--r--app/src/main/res/xml/preferences_autodownload.xml41
-rw-r--r--app/src/main/res/xml/preferences_flattr.xml21
-rw-r--r--app/src/main/res/xml/preferences_gpodder.xml35
-rw-r--r--app/src/main/res/xml/preferences_integrations.xml16
-rw-r--r--app/src/main/res/xml/preferences_network.xml42
-rw-r--r--app/src/main/res/xml/preferences_playback.xml130
-rw-r--r--app/src/main/res/xml/preferences_storage.xml43
-rw-r--r--app/src/main/res/xml/preferences_user_interface.xml60
-rw-r--r--app/src/main/templates/about.html100
-rw-r--r--app/src/play/java/de/danoeh/antennapod/dialog/CustomMRControllerDialog.java7
205 files changed, 4087 insertions, 3596 deletions
diff --git a/app/src/androidTest/java/de/test/antennapod/feed/FeedItemTest.java b/app/src/androidTest/java/de/test/antennapod/feed/FeedItemTest.java
new file mode 100644
index 000000000..db463132d
--- /dev/null
+++ b/app/src/androidTest/java/de/test/antennapod/feed/FeedItemTest.java
@@ -0,0 +1,37 @@
+package de.test.antennapod.feed;
+
+import android.test.AndroidTestCase;
+import de.danoeh.antennapod.core.feed.FeedItem;
+
+public class FeedItemTest extends AndroidTestCase {
+ private static final String TEXT_LONG = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
+ private static final String TEXT_SHORT = "Lorem ipsum";
+
+ /**
+ * If one of `description` or `content:encoded` is null, use the other one.
+ */
+ public void testShownotesNullValues() throws Exception {
+ testShownotes(null, TEXT_LONG);
+ testShownotes(TEXT_LONG, null);
+ }
+
+ /**
+ * If `description` is reasonably longer than `content:encoded`, use `description`.
+ */
+ public void testShownotesLength() throws Exception {
+ testShownotes(TEXT_SHORT, TEXT_LONG);
+ testShownotes(TEXT_LONG, TEXT_SHORT);
+ }
+
+ /**
+ * Checks if the shownotes equal TEXT_LONG, using the given `description` and `content:encoded`
+ * @param description Description of the feed item
+ * @param contentEncoded `content:encoded` of the feed item
+ */
+ private void testShownotes(String description, String contentEncoded) throws Exception {
+ FeedItem item = new FeedItem();
+ item.setDescription(description);
+ item.setContentEncoded(contentEncoded);
+ assertEquals(TEXT_LONG, item.loadShownotes().call());
+ }
+}
diff --git a/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java b/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java
index 88e05942b..a880c330b 100644
--- a/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/gpodnet/GPodnetServiceTest.java
@@ -2,14 +2,16 @@ package de.test.antennapod.gpodnet;
import android.test.AndroidTestCase;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
import de.danoeh.antennapod.core.gpoddernet.GpodnetService;
import de.danoeh.antennapod.core.gpoddernet.GpodnetServiceException;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetDevice;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetTag;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
+import static java.util.Collections.singletonList;
/**
* Test class for GpodnetService
@@ -55,7 +57,7 @@ public class GPodnetServiceTest extends AndroidTestCase {
authenticate();
String[] URLS = {"http://bitsundso.de/feed", "http://gamesundso.de/feed", "http://cre.fm/feed/mp3/", "http://freakshow.fm/feed/m4a/"};
List<String> subscriptions = Arrays.asList(URLS[0], URLS[1]);
- List<String> removed = Arrays.asList(URLS[0]);
+ List<String> removed = singletonList(URLS[0]);
List<String> added = Arrays.asList(URLS[2], URLS[3]);
service.uploadSubscriptions(USER, "radio", subscriptions);
service.uploadChanges(USER, "radio", added, removed);
diff --git a/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java b/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java
index ee454ce8a..6908e2ec7 100644
--- a/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/handler/FeedHandlerTest.java
@@ -17,7 +17,6 @@ import javax.xml.parsers.ParserConfigurationException;
import de.danoeh.antennapod.core.feed.Chapter;
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.syndication.handler.FeedHandler;
@@ -32,8 +31,8 @@ import de.test.antennapod.util.syndication.feedgenerator.RSS2Generator;
public class FeedHandlerTest extends InstrumentationTestCase {
private static final String FEEDS_DIR = "testfeeds";
- File file = null;
- OutputStream outputStream = null;
+ private File file = null;
+ private OutputStream outputStream = null;
protected void setUp() throws Exception {
super.setUp();
@@ -82,15 +81,7 @@ public class FeedHandlerTest extends InstrumentationTestCase {
assertEquals(feed.getLink(), parsedFeed.getLink());
assertEquals(feed.getDescription(), parsedFeed.getDescription());
assertEquals(feed.getPaymentLink(), parsedFeed.getPaymentLink());
-
- if (feed.getImage() != null) {
- FeedImage image = feed.getImage();
- FeedImage parsedImage = parsedFeed.getImage();
- assertNotNull(parsedImage);
-
- assertEquals(image.getTitle(), parsedImage.getTitle());
- assertEquals(image.getDownload_url(), parsedImage.getDownload_url());
- }
+ assertEquals(feed.getImageUrl(), parsedFeed.getImageUrl());
if (feed.getItems() != null) {
assertNotNull(parsedFeed.getItems());
@@ -119,14 +110,7 @@ public class FeedHandlerTest extends InstrumentationTestCase {
assertEquals(media.getMime_type(), parsedMedia.getMime_type());
}
- if (item.hasItemImage()) {
- assertTrue(parsedItem.hasItemImage());
- FeedImage image = item.getImage();
- FeedImage parsedImage = parsedItem.getImage();
-
- assertEquals(image.getTitle(), parsedImage.getTitle());
- assertEquals(image.getDownload_url(), parsedImage.getDownload_url());
- }
+ assertEquals(item.getImageUrl(), parsedFeed.getImageUrl());
if (item.getChapters() != null) {
assertNotNull(parsedItem.getChapters());
@@ -158,14 +142,10 @@ public class FeedHandlerTest extends InstrumentationTestCase {
}
private Feed createTestFeed(int numItems, boolean withImage, boolean withFeedMedia, boolean withChapters) {
- FeedImage image = null;
- if (withImage) {
- image = new FeedImage(0, "image", null, "http://example.com/picture", false);
- }
Feed feed = new Feed(0, null, "title", "http://example.com", "This is the description",
- "http://example.com/payment", "Daniel", "en", null, "http://example.com/feed", image, file.getAbsolutePath(),
+ "http://example.com/payment", "Daniel", "en", null, "http://example.com/feed", "http://example.com/picture", file.getAbsolutePath(),
"http://example.com/feed", true);
- feed.setItems(new ArrayList<FeedItem>());
+ feed.setItems(new ArrayList<>());
for (int i = 0; i < numItems; i++) {
FeedItem item = new FeedItem(0, "item-" + i, "http://example.com/item-" + i,
diff --git a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java
index 9ac92c2f9..2f53ea8a6 100644
--- a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java
@@ -23,8 +23,8 @@ 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.MediaType;
-import de.danoeh.antennapod.core.service.playback.PlaybackServiceMediaPlayer;
import de.danoeh.antennapod.core.service.playback.LocalPSMP;
+import de.danoeh.antennapod.core.service.playback.PlaybackServiceMediaPlayer;
import de.danoeh.antennapod.core.service.playback.PlayerStatus;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.core.util.playback.Playable;
diff --git a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java
index 6ab6e5c61..8be57a074 100644
--- a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java
@@ -9,10 +9,10 @@ import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+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.FeedItem;
-import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.service.playback.PlaybackServiceTaskManager;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.core.util.playback.Playable;
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBCleanupTests.java b/app/src/androidTest/java/de/test/antennapod/storage/DBCleanupTests.java
index 09533208f..5cd4e9906 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBCleanupTests.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBCleanupTests.java
@@ -27,12 +27,12 @@ import static de.test.antennapod.storage.DBTestUtils.saveFeedlist;
public class DBCleanupTests extends InstrumentationTestCase {
private static final String TAG = "DBTasksTest";
- protected static final int EPISODE_CACHE_SIZE = 5;
+ static final int EPISODE_CACHE_SIZE = 5;
private final int cleanupAlgorithm;
- protected Context context;
+ Context context;
- protected File destFolder;
+ private File destFolder;
public DBCleanupTests() {
this.cleanupAlgorithm = UserPreferences.EPISODE_CLEANUP_DEFAULT;
@@ -104,9 +104,9 @@ public class DBCleanupTests extends InstrumentationTestCase {
}
}
- protected void populateItems(final int numItems, Feed feed, List<FeedItem> items,
- List<File> files, int itemState, boolean addToQueue,
- boolean addToFavorites) throws IOException {
+ void populateItems(final int numItems, Feed feed, List<FeedItem> items,
+ List<File> files, int itemState, boolean addToQueue,
+ boolean addToFavorites) throws IOException {
for (int i = 0; i < numItems; i++) {
Date itemDate = new Date(numItems - i);
Date playbackCompletionDate = null;
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBQueueCleanupAlgorithmTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBQueueCleanupAlgorithmTest.java
index 3bd508eaf..d602d150b 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBQueueCleanupAlgorithmTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBQueueCleanupAlgorithmTest.java
@@ -5,7 +5,6 @@ import android.test.FlakyTest;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Date;
import java.util.List;
import de.danoeh.antennapod.core.feed.Feed;
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java
index 13cf56ff4..93a9408b7 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java
@@ -18,6 +18,8 @@ import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
+import static java.util.Collections.singletonList;
+
/**
* Test class for DBTasks
*/
@@ -125,7 +127,7 @@ public class DBTasksTest extends InstrumentationTestCase {
public void testUpdateFeedMediaUrlResetState() {
final Feed feed = new Feed("url", null, "title");
FeedItem item = new FeedItem(0, "item", "id", "link", new Date(), FeedItem.PLAYED, feed);
- feed.setItems(Arrays.asList(item));
+ feed.setItems(singletonList(item));
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
@@ -138,7 +140,7 @@ public class DBTasksTest extends InstrumentationTestCase {
FeedMedia media = new FeedMedia(item, "url", 1024, "mime/type");
item.setMedia(media);
- feed.setItems(Arrays.asList(item));
+ feed.setItems(singletonList(item));
final Feed newFeed = DBTasks.updateFeed(context, feed)[0];
assertTrue(feed != newFeed);
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java b/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java
index 30f465784..a577e5e36 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBTestUtils.java
@@ -19,7 +19,7 @@ import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
/**
* Utility methods for DB* tests.
*/
-public class DBTestUtils {
+class DBTestUtils {
private DBTestUtils(){}
/**
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java
index 7095d50b1..387ab91b3 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java
@@ -15,9 +15,7 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.feed.SimpleChapter;
@@ -124,89 +122,13 @@ public class DBWriterTest extends InstrumentationTestCase {
assertNull(media.getFile_url());
}
- public void testDeleteFeed() throws IOException, ExecutionException, InterruptedException, TimeoutException {
+ public void testDeleteFeed() throws ExecutionException, InterruptedException, IOException, TimeoutException {
File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
assertNotNull(destFolder);
Feed feed = new Feed("url", null, "title");
feed.setItems(new ArrayList<>());
- // create Feed image
- File imgFile = new File(destFolder, "image");
- assertTrue(imgFile.createNewFile());
- FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
- image.setOwner(feed);
- feed.setImage(image);
-
- List<File> itemFiles = new ArrayList<>();
- // create items with downloaded media files
- for (int i = 0; i < 10; i++) {
- FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), FeedItem.PLAYED, feed, true);
- feed.getItems().add(item);
-
- File enc = new File(destFolder, "file " + i);
- assertTrue(enc.createNewFile());
- itemFiles.add(enc);
-
- FeedMedia media = new FeedMedia(0, item, 1, 1, 1, "mime_type", enc.getAbsolutePath(), "download_url", true, null, 0, 0);
- item.setMedia(media);
-
- item.setChapters(new ArrayList<Chapter>());
- item.getChapters().add(new SimpleChapter(0, "item " + i, item, "example.com"));
- }
-
- PodDBAdapter adapter = PodDBAdapter.getInstance();
- adapter.open();
- adapter.setCompleteFeed(feed);
- adapter.close();
-
- assertTrue(feed.getId() != 0);
- assertTrue(feed.getImage().getId() != 0);
- for (FeedItem item : feed.getItems()) {
- assertTrue(item.getId() != 0);
- assertTrue(item.getMedia().getId() != 0);
- assertTrue(item.getChapters().get(0).getId() != 0);
- }
-
- DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
-
- // check if files still exist
- assertFalse(imgFile.exists());
- for (File f : itemFiles) {
- assertFalse(f.exists());
- }
-
- adapter = PodDBAdapter.getInstance();
- adapter.open();
- Cursor c = adapter.getFeedCursor(feed.getId());
- assertEquals(0, c.getCount());
- c.close();
- c = adapter.getImageCursor(String.valueOf(image.getId()));
- assertEquals(0, c.getCount());
- c.close();
- for (FeedItem item : feed.getItems()) {
- c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
- assertEquals(0, c.getCount());
- c.close();
- c = adapter.getSingleFeedMediaCursor(item.getMedia().getId());
- assertEquals(0, c.getCount());
- c.close();
- c = adapter.getSimpleChaptersOfFeedItemCursor(item);
- assertEquals(0, c.getCount());
- c.close();
- }
- adapter.close();
- }
-
- public void testDeleteFeedNoImage() throws ExecutionException, InterruptedException, IOException, TimeoutException {
- File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
- assertNotNull(destFolder);
-
- Feed feed = new Feed("url", null, "title");
- feed.setItems(new ArrayList<>());
-
- feed.setImage(null);
-
List<File> itemFiles = new ArrayList<>();
// create items with downloaded media files
for (int i = 0; i < 10; i++) {
@@ -261,13 +183,7 @@ public class DBWriterTest extends InstrumentationTestCase {
Feed feed = new Feed("url", null, "title");
feed.setItems(null);
-
- // create Feed image
- File imgFile = new File(destFolder, "image");
- assertTrue(imgFile.createNewFile());
- FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
- image.setOwner(feed);
- feed.setImage(image);
+ feed.setImageUrl("url");
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
@@ -275,21 +191,14 @@ public class DBWriterTest extends InstrumentationTestCase {
adapter.close();
assertTrue(feed.getId() != 0);
- assertTrue(feed.getImage().getId() != 0);
DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
- // check if files still exist
- assertFalse(imgFile.exists());
-
adapter = PodDBAdapter.getInstance();
adapter.open();
Cursor c = adapter.getFeedCursor(feed.getId());
assertTrue(c.getCount() == 0);
c.close();
- c = adapter.getImageCursor(String.valueOf(image.getId()));
- assertTrue(c.getCount() == 0);
- c.close();
adapter.close();
}
@@ -300,12 +209,7 @@ public class DBWriterTest extends InstrumentationTestCase {
Feed feed = new Feed("url", null, "title");
feed.setItems(new ArrayList<>());
- // create Feed image
- File imgFile = new File(destFolder, "image");
- assertTrue(imgFile.createNewFile());
- FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
- image.setOwner(feed);
- feed.setImage(image);
+ feed.setImageUrl("url");
// create items
for (int i = 0; i < 10; i++) {
@@ -320,24 +224,18 @@ public class DBWriterTest extends InstrumentationTestCase {
adapter.close();
assertTrue(feed.getId() != 0);
- assertTrue(feed.getImage().getId() != 0);
for (FeedItem item : feed.getItems()) {
assertTrue(item.getId() != 0);
}
DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
- // check if files still exist
- assertFalse(imgFile.exists());
adapter = PodDBAdapter.getInstance();
adapter.open();
Cursor c = adapter.getFeedCursor(feed.getId());
assertTrue(c.getCount() == 0);
c.close();
- c = adapter.getImageCursor(String.valueOf(image.getId()));
- assertTrue(c.getCount() == 0);
- c.close();
for (FeedItem item : feed.getItems()) {
c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
assertTrue(c.getCount() == 0);
@@ -346,65 +244,6 @@ public class DBWriterTest extends InstrumentationTestCase {
adapter.close();
}
- public void testDeleteFeedWithItemImages() throws InterruptedException, ExecutionException, TimeoutException, IOException {
- File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
- assertNotNull(destFolder);
-
- Feed feed = new Feed("url", null, "title");
- feed.setItems(new ArrayList<>());
-
- // create Feed image
- File imgFile = new File(destFolder, "image");
- assertTrue(imgFile.createNewFile());
- FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
- image.setOwner(feed);
- feed.setImage(image);
-
- // create items with images
- for (int i = 0; i < 10; i++) {
- FeedItem item = new FeedItem(0, "Item " + i, "Item" + i, "url", new Date(), FeedItem.PLAYED, feed);
- feed.getItems().add(item);
- File itemImageFile = new File(destFolder, "item-image-" + i);
- FeedImage itemImage = new FeedImage(0, "item-image" + i, itemImageFile.getAbsolutePath(), "url", true);
- item.setImage(itemImage);
- }
-
- PodDBAdapter adapter = PodDBAdapter.getInstance();
- adapter.open();
- adapter.setCompleteFeed(feed);
- adapter.close();
-
- assertTrue(feed.getId() != 0);
- assertTrue(feed.getImage().getId() != 0);
- for (FeedItem item : feed.getItems()) {
- assertTrue(item.getId() != 0);
- assertTrue(item.getImage().getId() != 0);
- }
-
- DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(TIMEOUT, TimeUnit.SECONDS);
-
- // check if files still exist
- assertFalse(imgFile.exists());
-
- adapter = PodDBAdapter.getInstance();
- adapter.open();
- Cursor c = adapter.getFeedCursor(feed.getId());
- assertTrue(c.getCount() == 0);
- c.close();
- c = adapter.getImageCursor(String.valueOf(image.getId()));
- assertTrue(c.getCount() == 0);
- c.close();
- for (FeedItem item : feed.getItems()) {
- c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
- assertTrue(c.getCount() == 0);
- c.close();
- c = adapter.getImageCursor(String.valueOf(item.getImage().getId()));
- assertEquals(0, c.getCount());
- c.close();
- }
- adapter.close();
- }
-
public void testDeleteFeedWithQueueItems() throws ExecutionException, InterruptedException, TimeoutException {
File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
assertNotNull(destFolder);
@@ -412,11 +251,7 @@ public class DBWriterTest extends InstrumentationTestCase {
Feed feed = new Feed("url", null, "title");
feed.setItems(new ArrayList<>());
- // create Feed image
- File imgFile = new File(destFolder, "image");
- FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
- image.setOwner(feed);
- feed.setImage(image);
+ feed.setImageUrl("url");
List<File> itemFiles = new ArrayList<>();
// create items with downloaded media files
@@ -437,7 +272,6 @@ public class DBWriterTest extends InstrumentationTestCase {
adapter.close();
assertTrue(feed.getId() != 0);
- assertTrue(feed.getImage().getId() != 0);
for (FeedItem item : feed.getItems()) {
assertTrue(item.getId() != 0);
assertTrue(item.getMedia().getId() != 0);
@@ -460,9 +294,6 @@ public class DBWriterTest extends InstrumentationTestCase {
Cursor c = adapter.getFeedCursor(feed.getId());
assertTrue(c.getCount() == 0);
c.close();
- c = adapter.getImageCursor(String.valueOf(image.getId()));
- assertTrue(c.getCount() == 0);
- c.close();
for (FeedItem item : feed.getItems()) {
c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
assertTrue(c.getCount() == 0);
@@ -484,11 +315,7 @@ public class DBWriterTest extends InstrumentationTestCase {
Feed feed = new Feed("url", null, "title");
feed.setItems(new ArrayList<>());
- // create Feed image
- File imgFile = new File(destFolder, "image");
- FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
- image.setOwner(feed);
- feed.setImage(image);
+ feed.setImageUrl("url");
List<File> itemFiles = new ArrayList<>();
// create items with downloaded media files
@@ -509,7 +336,6 @@ public class DBWriterTest extends InstrumentationTestCase {
adapter.close();
assertTrue(feed.getId() != 0);
- assertTrue(feed.getImage().getId() != 0);
for (FeedItem item : feed.getItems()) {
assertTrue(item.getId() != 0);
assertTrue(item.getMedia().getId() != 0);
@@ -522,9 +348,6 @@ public class DBWriterTest extends InstrumentationTestCase {
Cursor c = adapter.getFeedCursor(feed.getId());
assertTrue(c.getCount() == 0);
c.close();
- c = adapter.getImageCursor(String.valueOf(image.getId()));
- assertTrue(c.getCount() == 0);
- c.close();
for (FeedItem item : feed.getItems()) {
c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
assertTrue(c.getCount() == 0);
@@ -539,7 +362,7 @@ public class DBWriterTest extends InstrumentationTestCase {
private FeedMedia playbackHistorySetup(Date playbackCompletionDate) {
final Context context = getInstrumentation().getTargetContext();
Feed feed = new Feed("url", null, "title");
- feed.setItems(new ArrayList<FeedItem>());
+ feed.setItems(new ArrayList<>());
FeedItem item = new FeedItem(0, "title", "id", "link", new Date(), FeedItem.PLAYED, feed);
FeedMedia media = new FeedMedia(0, item, 10, 0, 1, "mime", null, "url", false, playbackCompletionDate, 0, 0);
feed.getItems().add(item);
@@ -791,7 +614,7 @@ public class DBWriterTest extends InstrumentationTestCase {
public void testMarkFeedRead() throws InterruptedException, ExecutionException, TimeoutException {
final int NUM_ITEMS = 10;
Feed feed = new Feed("url", null, "title");
- feed.setItems(new ArrayList<FeedItem>());
+ feed.setItems(new ArrayList<>());
for (int i = 0; i < NUM_ITEMS; i++) {
FeedItem item = new FeedItem(0, "title " + i, "id " + i, "link " + i, new Date(), FeedItem.UNPLAYED, feed);
feed.getItems().add(item);
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java
index bd9057b47..6156da926 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java
@@ -15,6 +15,7 @@ import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.activity.OnlineFeedViewActivity;
+import de.danoeh.antennapod.activity.PreferenceActivity;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
@@ -22,7 +23,6 @@ import de.danoeh.antennapod.fragment.DownloadsFragment;
import de.danoeh.antennapod.fragment.EpisodesFragment;
import de.danoeh.antennapod.fragment.PlaybackHistoryFragment;
import de.danoeh.antennapod.fragment.QueueFragment;
-import de.danoeh.antennapod.preferences.PreferenceController;
/**
* User interface tests for MainActivity
@@ -96,7 +96,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv
public void testClickNavDrawer() throws Exception {
uiTestUtils.addLocalFeedData(false);
- UserPreferences.setHiddenDrawerItems(new ArrayList<String>());
+ UserPreferences.setHiddenDrawerItems(new ArrayList<>());
// queue
openNavDrawer();
@@ -155,11 +155,11 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv
public void testGoToPreferences() {
openNavDrawer();
solo.clickOnText(solo.getString(R.string.settings_label));
- solo.waitForActivity(PreferenceController.getPreferenceActivity());
+ solo.waitForActivity(PreferenceActivity.class);
}
public void testDrawerPreferencesHideSomeElements() {
- UserPreferences.setHiddenDrawerItems(new ArrayList<String>());
+ UserPreferences.setHiddenDrawerItems(new ArrayList<>());
openNavDrawer();
solo.clickLongOnText(solo.getString(R.string.queue_label));
solo.waitForDialogToOpen();
@@ -190,7 +190,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv
}
public void testDrawerPreferencesHideAllElements() {
- UserPreferences.setHiddenDrawerItems(new ArrayList<String>());
+ UserPreferences.setHiddenDrawerItems(new ArrayList<>());
String[] titles = getInstrumentation().getTargetContext().getResources().getStringArray(R.array.nav_drawer_titles);
openNavDrawer();
@@ -209,7 +209,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv
}
public void testDrawerPreferencesHideCurrentElement() {
- UserPreferences.setHiddenDrawerItems(new ArrayList<String>());
+ UserPreferences.setHiddenDrawerItems(new ArrayList<>());
openNavDrawer();
String downloads = solo.getString(R.string.downloads_label);
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java
index bfbeedd83..293ed2848 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackSonicTest.java
@@ -33,8 +33,8 @@ import de.danoeh.antennapod.core.storage.PodDBAdapter;
public class PlaybackSonicTest extends ActivityInstrumentationTestCase2<MainActivity> {
private static final String TAG = PlaybackTest.class.getSimpleName();
- public static final int EPISODES_DRAWER_LIST_INDEX = 1;
- public static final int QUEUE_DRAWER_LIST_INDEX = 0;
+ private static final int EPISODES_DRAWER_LIST_INDEX = 1;
+ private static final int QUEUE_DRAWER_LIST_INDEX = 0;
private Solo solo;
private UITestUtils uiTestUtils;
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java
index 661c2200b..74d59abd7 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/PlaybackTest.java
@@ -30,8 +30,8 @@ import de.danoeh.antennapod.core.storage.PodDBAdapter;
public class PlaybackTest extends ActivityInstrumentationTestCase2<MainActivity> {
private static final String TAG = PlaybackTest.class.getSimpleName();
- public static final int EPISODES_DRAWER_LIST_INDEX = 1;
- public static final int QUEUE_DRAWER_LIST_INDEX = 0;
+ private static final int EPISODES_DRAWER_LIST_INDEX = 1;
+ private static final int QUEUE_DRAWER_LIST_INDEX = 0;
private Solo solo;
private UITestUtils uiTestUtils;
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java
index 91928f01e..9a5ea437c 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java
@@ -3,7 +3,6 @@ package de.test.antennapod.ui;
import android.content.Context;
import android.content.res.Resources;
import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
import com.robotium.solo.Solo;
import com.robotium.solo.Timeout;
@@ -56,6 +55,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
} else {
otherTheme = R.string.pref_theme_title_light;
}
+ solo.clickOnText(solo.getString(R.string.user_interface_label));
solo.clickOnText(solo.getString(R.string.pref_set_theme_title));
solo.waitForDialogToOpen();
solo.clickOnText(solo.getString(otherTheme));
@@ -70,6 +70,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
} else {
otherTheme = R.string.pref_theme_title_light;
}
+ solo.clickOnText(solo.getString(R.string.user_interface_label));
solo.clickOnText(solo.getString(R.string.pref_set_theme_title));
solo.waitForDialogToOpen(1000);
solo.clickOnText(solo.getString(otherTheme));
@@ -77,6 +78,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testExpandNotification() {
+ solo.clickOnText(solo.getString(R.string.user_interface_label));
final int priority = UserPreferences.getNotifyPriority();
solo.clickOnText(solo.getString(R.string.pref_expandNotify_title));
assertTrue(solo.waitForCondition(() -> priority != UserPreferences.getNotifyPriority(), Timeout.getLargeTimeout()));
@@ -85,7 +87,10 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testEnablePersistentPlaybackControls() {
+ solo.clickOnText(solo.getString(R.string.user_interface_label));
final boolean persistNotify = UserPreferences.isPersistNotify();
+ solo.scrollDown();
+ solo.scrollDown();
solo.clickOnText(solo.getString(R.string.pref_persistNotify_title));
assertTrue(solo.waitForCondition(() -> persistNotify != UserPreferences.isPersistNotify(), Timeout.getLargeTimeout()));
solo.clickOnText(solo.getString(R.string.pref_persistNotify_title));
@@ -93,14 +98,16 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testSetLockscreenButtons() {
+ solo.clickOnText(solo.getString(R.string.user_interface_label));
+ solo.scrollDown();
String[] buttons = res.getStringArray(R.array.compact_notification_buttons_options);
solo.clickOnText(solo.getString(R.string.pref_compact_notification_buttons_title));
solo.waitForDialogToOpen(1000);
// First uncheck every checkbox
- for (int i=0; i<buttons.length; i++) {
- assertTrue(solo.searchText(buttons[i]));
- if (solo.isTextChecked(buttons[i])) {
- solo.clickOnText(buttons[i]);
+ for (String button : buttons) {
+ assertTrue(solo.searchText(button));
+ if (solo.isTextChecked(button)) {
+ solo.clickOnText(button);
}
}
// Now try to check all checkboxes
@@ -111,13 +118,16 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
assertTrue(!solo.isTextChecked(buttons[2]));
solo.clickOnText(solo.getString(R.string.confirm_label));
solo.waitForDialogToClose(1000);
- assertTrue(solo.waitForCondition(() -> UserPreferences.showRewindOnCompactNotification(), Timeout.getLargeTimeout()));
- assertTrue(solo.waitForCondition(() -> UserPreferences.showFastForwardOnCompactNotification(), Timeout.getLargeTimeout()));
+ assertTrue(solo.waitForCondition(UserPreferences::showRewindOnCompactNotification, Timeout.getLargeTimeout()));
+ assertTrue(solo.waitForCondition(UserPreferences::showFastForwardOnCompactNotification, Timeout.getLargeTimeout()));
assertTrue(solo.waitForCondition(() -> !UserPreferences.showSkipOnCompactNotification(), Timeout.getLargeTimeout()));
}
public void testEnqueueAtFront() {
+ solo.clickOnText(solo.getString(R.string.playback_pref));
final boolean enqueueAtFront = UserPreferences.enqueueAtFront();
+ solo.scrollDown();
+ solo.scrollDown();
solo.clickOnText(solo.getString(R.string.pref_queueAddToFront_title));
assertTrue(solo.waitForCondition(() -> enqueueAtFront != UserPreferences.enqueueAtFront(), Timeout.getLargeTimeout()));
solo.clickOnText(solo.getString(R.string.pref_queueAddToFront_title));
@@ -125,6 +135,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testHeadPhonesDisconnect() {
+ solo.clickOnText(solo.getString(R.string.playback_pref));
final boolean pauseOnHeadsetDisconnect = UserPreferences.isPauseOnHeadsetDisconnect();
solo.clickOnText(solo.getString(R.string.pref_pauseOnHeadsetDisconnect_title));
assertTrue(solo.waitForCondition(() -> pauseOnHeadsetDisconnect != UserPreferences.isPauseOnHeadsetDisconnect(), Timeout.getLargeTimeout()));
@@ -133,9 +144,10 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testHeadPhonesReconnect() {
+ solo.clickOnText(solo.getString(R.string.playback_pref));
if(UserPreferences.isPauseOnHeadsetDisconnect() == false) {
solo.clickOnText(solo.getString(R.string.pref_pauseOnHeadsetDisconnect_title));
- assertTrue(solo.waitForCondition(() -> UserPreferences.isPauseOnHeadsetDisconnect(), Timeout.getLargeTimeout()));
+ assertTrue(solo.waitForCondition(UserPreferences::isPauseOnHeadsetDisconnect, Timeout.getLargeTimeout()));
}
final boolean unpauseOnHeadsetReconnect = UserPreferences.isUnpauseOnHeadsetReconnect();
solo.clickOnText(solo.getString(R.string.pref_unpauseOnHeadsetReconnect_title));
@@ -145,9 +157,10 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testBluetoothReconnect() {
+ solo.clickOnText(solo.getString(R.string.playback_pref));
if(UserPreferences.isPauseOnHeadsetDisconnect() == false) {
solo.clickOnText(solo.getString(R.string.pref_pauseOnHeadsetDisconnect_title));
- assertTrue(solo.waitForCondition(() -> UserPreferences.isPauseOnHeadsetDisconnect(), Timeout.getLargeTimeout()));
+ assertTrue(solo.waitForCondition(UserPreferences::isPauseOnHeadsetDisconnect, Timeout.getLargeTimeout()));
}
final boolean unpauseOnBluetoothReconnect = UserPreferences.isUnpauseOnBluetoothReconnect();
solo.clickOnText(solo.getString(R.string.pref_unpauseOnBluetoothReconnect_title));
@@ -157,7 +170,10 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testContinuousPlayback() {
+ solo.clickOnText(solo.getString(R.string.playback_pref));
final boolean continuousPlayback = UserPreferences.isFollowQueue();
+ solo.scrollDown();
+ solo.scrollDown();
solo.clickOnText(solo.getString(R.string.pref_followQueue_title));
assertTrue(solo.waitForCondition(() -> continuousPlayback != UserPreferences.isFollowQueue(), Timeout.getLargeTimeout()));
solo.clickOnText(solo.getString(R.string.pref_followQueue_title));
@@ -165,6 +181,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testAutoDelete() {
+ solo.clickOnText(solo.getString(R.string.storage_pref));
final boolean autoDelete = UserPreferences.isAutoDelete();
solo.clickOnText(solo.getString(R.string.pref_auto_delete_title));
assertTrue(solo.waitForCondition(() -> autoDelete != UserPreferences.isAutoDelete(), Timeout.getLargeTimeout()));
@@ -173,6 +190,9 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testPlaybackSpeeds() {
+ solo.clickOnText(solo.getString(R.string.playback_pref));
+ solo.scrollDown();
+ solo.scrollDown();
solo.clickOnText(solo.getString(R.string.pref_playback_speed_title));
solo.waitForDialogToOpen(1000);
assertTrue(solo.searchText(res.getStringArray(R.array.playback_speed_values)[0]));
@@ -181,6 +201,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testPauseForInterruptions() {
+ solo.clickOnText(solo.getString(R.string.playback_pref));
final boolean pauseForFocusLoss = UserPreferences.shouldPauseForFocusLoss();
solo.clickOnText(solo.getString(R.string.pref_pausePlaybackForFocusLoss_title));
assertTrue(solo.waitForCondition(() -> pauseForFocusLoss != UserPreferences.shouldPauseForFocusLoss(), Timeout.getLargeTimeout()));
@@ -189,6 +210,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testDisableUpdateInterval() {
+ solo.clickOnText(solo.getString(R.string.network_pref));
solo.clickOnText(solo.getString(R.string.pref_autoUpdateIntervallOrTime_sum));
solo.waitForDialogToOpen();
solo.clickOnText(solo.getString(R.string.pref_autoUpdateIntervallOrTime_Disable));
@@ -196,6 +218,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testSetUpdateInterval() {
+ solo.clickOnText(solo.getString(R.string.network_pref));
solo.clickOnText(solo.getString(R.string.pref_autoUpdateIntervallOrTime_title));
solo.waitForDialogToOpen();
solo.clickOnText(solo.getString(R.string.pref_autoUpdateIntervallOrTime_Interval));
@@ -208,6 +231,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testMobileUpdates() {
+ solo.clickOnText(solo.getString(R.string.network_pref));
final boolean mobileUpdates = UserPreferences.isAllowMobileUpdate();
solo.clickOnText(solo.getString(R.string.pref_mobileUpdate_title));
assertTrue(solo.waitForCondition(() -> mobileUpdates != UserPreferences.isAllowMobileUpdate(), Timeout.getLargeTimeout()));
@@ -216,6 +240,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testSetSequentialDownload() {
+ solo.clickOnText(solo.getString(R.string.network_pref));
solo.clickOnText(solo.getString(R.string.pref_parallel_downloads_title));
solo.waitForDialogToOpen();
solo.clearEditText(0);
@@ -225,6 +250,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testSetParallelDownloads() {
+ solo.clickOnText(solo.getString(R.string.network_pref));
solo.clickOnText(solo.getString(R.string.pref_parallel_downloads_title));
solo.waitForDialogToOpen();
solo.clearEditText(0);
@@ -234,6 +260,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testSetParallelDownloadsInvalidInput() {
+ solo.clickOnText(solo.getString(R.string.network_pref));
solo.clickOnText(solo.getString(R.string.pref_parallel_downloads_title));
solo.waitForDialogToOpen();
solo.clearEditText(0);
@@ -249,6 +276,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
String[] values = res.getStringArray(R.array.episode_cache_size_values);
String entry = entries[entries.length/2];
final int value = Integer.valueOf(values[values.length/2]);
+ solo.clickOnText(solo.getString(R.string.network_pref));
solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
solo.waitForText(solo.getString(R.string.pref_automatic_download_title));
solo.clickOnText(solo.getString(R.string.pref_episode_cache_title));
@@ -262,6 +290,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
String[] values = res.getStringArray(R.array.episode_cache_size_values);
String minEntry = entries[0];
final int minValue = Integer.valueOf(values[0]);
+ solo.clickOnText(solo.getString(R.string.network_pref));
solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
solo.waitForText(solo.getString(R.string.pref_automatic_download_title));
if(!UserPreferences.isEnableAutodownload()) {
@@ -279,6 +308,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
String[] values = res.getStringArray(R.array.episode_cache_size_values);
String maxEntry = entries[entries.length-1];
final int maxValue = Integer.valueOf(values[values.length-1]);
+ solo.clickOnText(solo.getString(R.string.network_pref));
solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
solo.waitForText(solo.getString(R.string.pref_automatic_download_title));
if(!UserPreferences.isEnableAutodownload()) {
@@ -292,6 +322,7 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
public void testAutomaticDownload() {
final boolean automaticDownload = UserPreferences.isEnableAutodownload();
+ solo.clickOnText(solo.getString(R.string.network_pref));
solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
solo.waitForText(solo.getString(R.string.pref_automatic_download_title));
solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
@@ -313,6 +344,8 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testEpisodeCleanupQueueOnly() {
+ solo.clickOnText(solo.getString(R.string.network_pref));
+ solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
solo.clickOnText(solo.getString(R.string.pref_episode_cleanup_title));
solo.waitForText(solo.getString(R.string.episode_cleanup_queue_removal));
solo.clickOnText(solo.getString(R.string.episode_cleanup_queue_removal));
@@ -324,6 +357,8 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testEpisodeCleanupNeverAlg() {
+ solo.clickOnText(solo.getString(R.string.network_pref));
+ solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
solo.clickOnText(solo.getString(R.string.pref_episode_cleanup_title));
solo.waitForText(solo.getString(R.string.episode_cleanup_never));
solo.clickOnText(solo.getString(R.string.episode_cleanup_never));
@@ -335,6 +370,8 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testEpisodeCleanupClassic() {
+ solo.clickOnText(solo.getString(R.string.network_pref));
+ solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
solo.clickOnText(solo.getString(R.string.pref_episode_cleanup_title));
solo.waitForText(solo.getString(R.string.episode_cleanup_after_listening));
solo.clickOnText(solo.getString(R.string.episode_cleanup_after_listening));
@@ -350,6 +387,8 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testEpisodeCleanupNumDays() {
+ solo.clickOnText(solo.getString(R.string.network_pref));
+ solo.clickOnText(solo.getString(R.string.pref_automatic_download_title));
solo.clickOnText(solo.getString(R.string.pref_episode_cleanup_title));
solo.waitForText(solo.getString(R.string.episode_cleanup_after_listening));
solo.clickOnText("5");
@@ -369,6 +408,9 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
int seconds = UserPreferences.getRewindSecs();
int deltas[] = res.getIntArray(R.array.seek_delta_values);
+ solo.clickOnText(solo.getString(R.string.playback_pref));
+ solo.scrollDown();
+ solo.scrollDown();
solo.clickOnText(solo.getString(R.string.pref_rewind));
solo.waitForDialogToOpen();
@@ -387,6 +429,9 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
}
public void testFastForwardChange() {
+ solo.clickOnText(solo.getString(R.string.playback_pref));
+ solo.scrollDown();
+ solo.scrollDown();
for (int i = 2; i > 0; i--) { // repeat twice to catch any error where fastforward is tracking rewind
int seconds = UserPreferences.getFastForwardSecs();
int deltas[] = res.getIntArray(R.array.seek_delta_values);
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java
index ccac4e761..ff5374268 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtils.java
@@ -1,9 +1,7 @@
package de.test.antennapod.ui;
-import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
-import android.os.Build;
import android.util.Log;
import junit.framework.Assert;
@@ -20,14 +18,12 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
-import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
+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.FeedImage;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
-import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.fragment.ExternalPlayerFragment;
@@ -39,27 +35,25 @@ import de.test.antennapod.util.syndication.feedgenerator.RSS2Generator;
* Utility methods for UI tests.
* Starts a web server that hosts feeds, episodes and images.
*/
-@TargetApi(Build.VERSION_CODES.HONEYCOMB)
-public class UITestUtils {
+class UITestUtils {
private static final String TAG = UITestUtils.class.getSimpleName();
private static final String DATA_FOLDER = "test/UITestUtils";
- public static final int NUM_FEEDS = 5;
- public static final int NUM_ITEMS_PER_FEED = 10;
+ private static final int NUM_FEEDS = 5;
+ private static final int NUM_ITEMS_PER_FEED = 10;
- public static final int HOME_VIEW = (Build.VERSION.SDK_INT >= 11) ? android.R.id.home : R.id.home;
- public static final String TEST_FILE_NAME = "3sec.mp3";
+ private static final String TEST_FILE_NAME = "3sec.mp3";
- private Context context;
- private HTTPBin server = new HTTPBin();
+ private final Context context;
+ private final HTTPBin server = new HTTPBin();
private File destDir;
private File hostedFeedDir;
private File hostedMediaDir;
- public List<Feed> hostedFeeds = new ArrayList<>();
+ public final List<Feed> hostedFeeds = new ArrayList<>();
public UITestUtils(Context context) {
this.context = context;
@@ -141,12 +135,9 @@ public class UITestUtils {
public void addHostedFeedData() throws IOException {
if (feedDataHosted) throw new IllegalStateException("addHostedFeedData was called twice on the same instance");
for (int i = 0; i < NUM_FEEDS; i++) {
- File bitmapFile = newBitmapFile("image" + i);
- FeedImage image = new FeedImage(0, "image " + i, null, hostFile(bitmapFile), false);
Feed feed = new Feed(0, null, "Title " + i, "http://example.com/" + i, "Description of feed " + i,
- "http://example.com/pay/feed" + i, "author " + i, "en", Feed.TYPE_RSS2, "feed" + i, image, null,
+ "http://example.com/pay/feed" + i, "author " + i, "en", Feed.TYPE_RSS2, "feed" + i, null, null,
"http://example.com/feed/src/" + i, false);
- image.setOwner(feed);
// create items
List<FeedItem> items = new ArrayList<>();
@@ -192,12 +183,6 @@ public class UITestUtils {
List<FeedItem> queue = new ArrayList<>();
for (Feed feed : hostedFeeds) {
feed.setDownloaded(true);
- if (feed.getImage() != null) {
- FeedImage image = feed.getImage();
- int fileId = Integer.parseInt(StringUtils.substringAfter(image.getDownload_url(), "files/"));
- image.setFile_url(server.accessFile(fileId).getAbsolutePath());
- image.setDownloaded(true);
- }
if (downloadEpisodes) {
for (FeedItem item : feed.getItems()) {
if (item.hasMedia()) {
diff --git a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java
index 53fd7d7fd..45ba472ff 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/UITestUtilsTest.java
@@ -38,9 +38,6 @@ public class UITestUtilsTest extends InstrumentationTestCase {
for (Feed feed : feeds) {
testUrlReachable(feed.getDownload_url());
- if (feed.getImage() != null) {
- testUrlReachable(feed.getImage().getDownload_url());
- }
for (FeedItem item : feed.getItems()) {
if (item.hasMedia()) {
testUrlReachable(item.getMedia().getDownload_url());
@@ -66,9 +63,6 @@ public class UITestUtilsTest extends InstrumentationTestCase {
for (Feed feed : uiTestUtils.hostedFeeds) {
assertTrue(feed.getId() != 0);
- if (feed.getImage() != null) {
- assertTrue(feed.getImage().getId() != 0);
- }
for (FeedItem item : feed.getItems()) {
assertTrue(item.getId() != 0);
if (item.hasMedia()) {
diff --git a/app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java b/app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java
index cb2d012e0..a36b3b65a 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/FilenameGeneratorTest.java
@@ -1,11 +1,12 @@
package de.test.antennapod.util;
+import android.test.AndroidTestCase;
+import android.text.TextUtils;
+
import java.io.File;
import java.io.IOException;
import de.danoeh.antennapod.core.util.FileNameGenerator;
-import android.test.AndroidTestCase;
-import android.text.TextUtils;
public class FilenameGeneratorTest extends AndroidTestCase {
diff --git a/app/src/androidTest/java/de/test/antennapod/util/RewindAfterPauseUtilTest.java b/app/src/androidTest/java/de/test/antennapod/util/RewindAfterPauseUtilTest.java
index fcfb16eb4..d564d0492 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/RewindAfterPauseUtilTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/RewindAfterPauseUtilTest.java
@@ -1,8 +1,8 @@
package de.test.antennapod.util;
-import junit.framework.*;
+import junit.framework.TestCase;
-import de.danoeh.antennapod.core.util.*;
+import de.danoeh.antennapod.core.util.RewindAfterPauseUtils;
/**
* Tests for {@link RewindAfterPauseUtils}.
diff --git a/app/src/androidTest/java/de/test/antennapod/util/URIUtilTest.java b/app/src/androidTest/java/de/test/antennapod/util/URIUtilTest.java
index 7bdcfb898..2cca6b4dc 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/URIUtilTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/URIUtilTest.java
@@ -1,6 +1,7 @@
package de.test.antennapod.util;
import android.test.AndroidTestCase;
+
import de.danoeh.antennapod.core.util.URIUtil;
/**
diff --git a/app/src/androidTest/java/de/test/antennapod/util/URLCheckerTest.java b/app/src/androidTest/java/de/test/antennapod/util/URLCheckerTest.java
index aa197b6e1..1b444bfa9 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/URLCheckerTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/URLCheckerTest.java
@@ -1,6 +1,7 @@
package de.test.antennapod.util;
import android.test.AndroidTestCase;
+
import de.danoeh.antennapod.core.util.URLChecker;
/**
diff --git a/app/src/androidTest/java/de/test/antennapod/util/service/download/HTTPBin.java b/app/src/androidTest/java/de/test/antennapod/util/service/download/HTTPBin.java
index 23be5ad4a..cde93fd7e 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/service/download/HTTPBin.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/service/download/HTTPBin.java
@@ -45,7 +45,7 @@ public class HTTPBin extends NanoHTTPD {
private static final String MIME_HTML = "text/html";
private static final String MIME_PLAIN = "text/plain";
- private List<File> servedFiles;
+ private final List<File> servedFiles;
public HTTPBin() {
super(PORT);
diff --git a/app/src/androidTest/java/de/test/antennapod/util/service/download/NanoHTTPD.java b/app/src/androidTest/java/de/test/antennapod/util/service/download/NanoHTTPD.java
index a728d9afd..61ff65809 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/service/download/NanoHTTPD.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/service/download/NanoHTTPD.java
@@ -88,15 +88,15 @@ public abstract class NanoHTTPD {
* This is required as the Keep-Alive HTTP connections would otherwise
* block the socket reading thread forever (or as long the browser is open).
*/
- public static final int SOCKET_READ_TIMEOUT = 5000;
+ private static final int SOCKET_READ_TIMEOUT = 5000;
/**
* Common mime type for dynamic content: plain text
*/
- public static final String MIME_PLAINTEXT = "text/plain";
+ private static final String MIME_PLAINTEXT = "text/plain";
/**
* Common mime type for dynamic content: html
*/
- public static final String MIME_HTML = "text/html";
+ private static final String MIME_HTML = "text/html";
/**
* Pseudo-Parameter to use to store the actual query string in the parameters map for later re-processing.
*/
@@ -104,7 +104,7 @@ public abstract class NanoHTTPD {
private final String hostname;
private final int myPort;
private ServerSocket myServerSocket;
- private Set<Socket> openConnections = new HashSet<>();
+ private final Set<Socket> openConnections = new HashSet<>();
private Thread myThread;
/**
* Pluggable strategy for asynchronously executing requests.
@@ -118,14 +118,14 @@ public abstract class NanoHTTPD {
/**
* Constructs an HTTP server on given port.
*/
- public NanoHTTPD(int port) {
+ NanoHTTPD(int port) {
this(null, port);
}
/**
* Constructs an HTTP server on given hostname and port.
*/
- public NanoHTTPD(String hostname, int port) {
+ private NanoHTTPD(String hostname, int port) {
this.hostname = hostname;
this.myPort = port;
setTempFileManagerFactory(new DefaultTempFileManagerFactory());
@@ -168,44 +168,38 @@ public abstract class NanoHTTPD {
myServerSocket = new ServerSocket();
myServerSocket.bind((hostname != null) ? new InetSocketAddress(hostname, myPort) : new InetSocketAddress(myPort));
- myThread = new Thread(new Runnable() {
- @Override
- public void run() {
- do {
- try {
- final Socket finalAccept = myServerSocket.accept();
- registerConnection(finalAccept);
- finalAccept.setSoTimeout(SOCKET_READ_TIMEOUT);
- final InputStream inputStream = finalAccept.getInputStream();
- asyncRunner.exec(new Runnable() {
- @Override
- public void run() {
- OutputStream outputStream = null;
- try {
- outputStream = finalAccept.getOutputStream();
- TempFileManager tempFileManager = tempFileManagerFactory.create();
- HTTPSession session = new HTTPSession(tempFileManager, inputStream, outputStream, finalAccept.getInetAddress());
- while (!finalAccept.isClosed()) {
- session.execute();
- }
- } catch (Exception e) {
- // When the socket is closed by the client, we throw our own SocketException
- // to break the "keep alive" loop above.
- if (!(e instanceof SocketException && "NanoHttpd Shutdown".equals(e.getMessage()))) {
- e.printStackTrace();
- }
- } finally {
- safeClose(outputStream);
- safeClose(inputStream);
- safeClose(finalAccept);
- unRegisterConnection(finalAccept);
- }
+ myThread = new Thread(() -> {
+ do {
+ try {
+ final Socket finalAccept = myServerSocket.accept();
+ registerConnection(finalAccept);
+ finalAccept.setSoTimeout(SOCKET_READ_TIMEOUT);
+ final InputStream inputStream = finalAccept.getInputStream();
+ asyncRunner.exec(() -> {
+ OutputStream outputStream = null;
+ try {
+ outputStream = finalAccept.getOutputStream();
+ TempFileManager tempFileManager = tempFileManagerFactory.create();
+ HTTPSession session = new HTTPSession(tempFileManager, inputStream, outputStream, finalAccept.getInetAddress());
+ while (!finalAccept.isClosed()) {
+ session.execute();
}
- });
- } catch (IOException e) {
- }
- } while (!myServerSocket.isClosed());
- }
+ } catch (Exception e) {
+ // When the socket is closed by the client, we throw our own SocketException
+ // to break the "keep alive" loop above.
+ if (!(e instanceof SocketException && "NanoHttpd Shutdown".equals(e.getMessage()))) {
+ e.printStackTrace();
+ }
+ } finally {
+ safeClose(outputStream);
+ safeClose(inputStream);
+ safeClose(finalAccept);
+ unRegisterConnection(finalAccept);
+ }
+ });
+ } catch (IOException e) {
+ }
+ } while (!myServerSocket.isClosed());
});
myThread.setDaemon(true);
myThread.setName("NanoHttpd Main Listener");
@@ -232,7 +226,7 @@ public abstract class NanoHTTPD {
*
* @param socket the {@link Socket} for the connection.
*/
- public synchronized void registerConnection(Socket socket) {
+ private synchronized void registerConnection(Socket socket) {
openConnections.add(socket);
}
@@ -242,14 +236,14 @@ public abstract class NanoHTTPD {
* @param socket
* the {@link Socket} for the connection.
*/
- public synchronized void unRegisterConnection(Socket socket) {
+ private synchronized void unRegisterConnection(Socket socket) {
openConnections.remove(socket);
}
/**
* Forcibly closes all connections that are open.
*/
- public synchronized void closeAllConnections() {
+ private synchronized void closeAllConnections() {
for (Socket socket : openConnections) {
safeClose(socket);
}
@@ -259,7 +253,7 @@ public abstract class NanoHTTPD {
return myServerSocket == null ? -1 : myServerSocket.getLocalPort();
}
- public final boolean wasStarted() {
+ private boolean wasStarted() {
return myServerSocket != null && myThread != null;
}
@@ -294,7 +288,7 @@ public abstract class NanoHTTPD {
* @param session The HTTP session
* @return HTTP response, see class Response for details
*/
- public Response serve(IHTTPSession session) {
+ Response serve(IHTTPSession session) {
Map<String, String> files = new ArrayMap<>();
Method method = session.getMethod();
if (Method.PUT.equals(method) || Method.POST.equals(method)) {
@@ -318,7 +312,7 @@ public abstract class NanoHTTPD {
* @param str the percent encoded <code>String</code>
* @return expanded form of the input, for example "foo%20bar" becomes "foo bar"
*/
- protected String decodePercent(String str) {
+ private String decodePercent(String str) {
String decoded = null;
try {
decoded = URLDecoder.decode(str, "UTF8");
@@ -347,7 +341,7 @@ public abstract class NanoHTTPD {
* @param queryString a query string pulled from the URL.
* @return a map of <code>String</code> (parameter name) to <code>List&lt;String&gt;</code> (a list of the values supplied).
*/
- protected Map<String, List<String>> decodeParameters(String queryString) {
+ private Map<String, List<String>> decodeParameters(String queryString) {
Map<String, List<String>> parms = new ArrayMap<>();
if (queryString != null) {
StringTokenizer st = new StringTokenizer(queryString, "&");
@@ -378,7 +372,7 @@ public abstract class NanoHTTPD {
*
* @param asyncRunner new strategy for handling threads.
*/
- public void setAsyncRunner(AsyncRunner asyncRunner) {
+ private void setAsyncRunner(AsyncRunner asyncRunner) {
this.asyncRunner = asyncRunner;
}
@@ -393,7 +387,7 @@ public abstract class NanoHTTPD {
*
* @param tempFileManagerFactory new strategy for handling temp files.
*/
- public void setTempFileManagerFactory(TempFileManagerFactory tempFileManagerFactory) {
+ private void setTempFileManagerFactory(TempFileManagerFactory tempFileManagerFactory) {
this.tempFileManagerFactory = tempFileManagerFactory;
}
@@ -448,9 +442,9 @@ public abstract class NanoHTTPD {
* themselves up when no longer needed.</p>
*/
public interface TempFile {
- OutputStream open() throws Exception;
+ OutputStream open();
- void delete() throws Exception;
+ void delete();
String getName();
}
@@ -528,12 +522,12 @@ public abstract class NanoHTTPD {
}
@Override
- public OutputStream open() throws Exception {
+ public OutputStream open() {
return fstream;
}
@Override
- public void delete() throws Exception {
+ public void delete() {
safeClose(fstream);
file.delete();
}
@@ -563,7 +557,7 @@ public abstract class NanoHTTPD {
/**
* Headers for the HTTP response. Use addHeader() to add lines.
*/
- private Map<String, String> header = new ArrayMap<>();
+ private final Map<String, String> header = new ArrayMap<>();
/**
* The request method that spawned this response.
*/
@@ -616,7 +610,7 @@ public abstract class NanoHTTPD {
/**
* Sends given response to the socket.
*/
- protected void send(OutputStream outputStream) {
+ void send(OutputStream outputStream) {
String mime = mimeType;
SimpleDateFormat gmtFrmt = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss 'GMT'", Locale.US);
gmtFrmt.setTimeZone(TimeZone.getTimeZone("GMT"));
@@ -661,13 +655,13 @@ public abstract class NanoHTTPD {
}
}
- protected void sendContentLengthHeaderIfNotAlreadyPresent(PrintWriter pw, Map<String, String> header, int size) {
+ void sendContentLengthHeaderIfNotAlreadyPresent(PrintWriter pw, Map<String, String> header, int size) {
if (!headerAlreadySent(header, "content-length")) {
pw.print("Content-Length: "+ size +"\r\n");
}
}
- protected void sendConnectionHeaderIfNotAlreadyPresent(PrintWriter pw, Map<String, String> header) {
+ void sendConnectionHeaderIfNotAlreadyPresent(PrintWriter pw, Map<String, String> header) {
if (!headerAlreadySent(header, "connection")) {
pw.print("Connection: keep-alive\r\n");
}
@@ -694,7 +688,7 @@ public abstract class NanoHTTPD {
outputStream.write(buff, 0, read);
outputStream.write(CRLF);
}
- outputStream.write(String.format("0\r\n\r\n").getBytes());
+ outputStream.write("0\r\n\r\n".getBytes());
}
private void sendAsFixedLength(OutputStream outputStream, int pending) throws IOException {
@@ -844,7 +838,7 @@ public abstract class NanoHTTPD {
public static final int BUFSIZE = 8192;
private final TempFileManager tempFileManager;
private final OutputStream outputStream;
- private PushbackInputStream inputStream;
+ private final PushbackInputStream inputStream;
private int splitbyte;
private int rlen;
private String uri;
@@ -1144,17 +1138,19 @@ public abstract class NanoHTTPD {
String value = "";
if (item.get("content-type") == null) {
+ StringBuilder tmp = new StringBuilder();
while (mpline != null && !mpline.contains(boundary)) {
mpline = in.readLine();
if (mpline != null) {
int d = mpline.indexOf(boundary);
if (d == -1) {
- value += mpline;
+ tmp.append(mpline);
} else {
- value += mpline.substring(0, d - 2);
+ tmp.append(mpline.substring(0, d - 2));
}
}
}
+ value = tmp.toString();
} else {
if (boundarycount > bpositions.length) {
throw new ResponseException(Response.Status.INTERNAL_ERROR, "Error processing request");
@@ -1326,7 +1322,9 @@ public abstract class NanoHTTPD {
}
public static class Cookie {
- private String n, v, e;
+ private final String n;
+ private final String v;
+ private final String e;
public Cookie(String name, String value, String expires) {
n = name;
@@ -1366,8 +1364,8 @@ public abstract class NanoHTTPD {
* @author LordFokas
*/
public class CookieHandler implements Iterable<String> {
- private ArrayMap<String, String> cookies = new ArrayMap<>();
- private ArrayList<Cookie> queue = new ArrayList<>();
+ private final ArrayMap<String, String> cookies = new ArrayMap<>();
+ private final ArrayList<Cookie> queue = new ArrayList<>();
public CookieHandler(Map<String, String> httpHeaders) {
String raw = httpHeaders.get("cookie");
diff --git a/app/src/androidTest/java/de/test/antennapod/util/syndication/FeedDiscovererTest.java b/app/src/androidTest/java/de/test/antennapod/util/syndication/FeedDiscovererTest.java
index 4e5d0297f..809b9769a 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/syndication/FeedDiscovererTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/syndication/FeedDiscovererTest.java
@@ -1,7 +1,7 @@
package de.test.antennapod.util.syndication;
import android.test.InstrumentationTestCase;
-import de.danoeh.antennapod.core.util.syndication.FeedDiscoverer;
+
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
@@ -9,6 +9,8 @@ import java.io.File;
import java.io.FileOutputStream;
import java.util.Map;
+import de.danoeh.antennapod.core.util.syndication.FeedDiscoverer;
+
/**
* Test class for FeedDiscoverer
*/
diff --git a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/AtomGenerator.java b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/AtomGenerator.java
index bd3df0f9d..afe15f1b2 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/AtomGenerator.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/AtomGenerator.java
@@ -19,7 +19,7 @@ public class AtomGenerator implements FeedGenerator{
private static final String NS_ATOM = "http://www.w3.org/2005/Atom";
- public static final long FEATURE_USE_RFC3339LOCAL = 1;
+ private static final long FEATURE_USE_RFC3339LOCAL = 1;
@Override
public void writeFeed(Feed feed, OutputStream outputStream, String encoding, long flags) throws IOException {
diff --git a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/FeedGenerator.java b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/FeedGenerator.java
index fe5afd847..b63159384 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/FeedGenerator.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/FeedGenerator.java
@@ -1,10 +1,10 @@
package de.test.antennapod.util.syndication.feedgenerator;
-import de.danoeh.antennapod.core.feed.Feed;
-
import java.io.IOException;
import java.io.OutputStream;
+import de.danoeh.antennapod.core.feed.Feed;
+
/**
* Generates a machine-readable, platform-independent representation of a Feed object.
*/
@@ -24,5 +24,5 @@ public interface FeedGenerator {
* @param encoding The encoding to use. Must not be null.
* @param flags Optional argument for enabling implementation-dependent features.
*/
- public void writeFeed(Feed feed, OutputStream outputStream, String encoding, long flags) throws IOException;
+ void writeFeed(Feed feed, OutputStream outputStream, String encoding, long flags) throws IOException;
}
diff --git a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/GeneratorUtil.java b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/GeneratorUtil.java
index ba924d637..89542d222 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/GeneratorUtil.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/GeneratorUtil.java
@@ -7,7 +7,7 @@ import java.io.IOException;
/**
* Utility methods for FeedGenerator
*/
-public class GeneratorUtil {
+class GeneratorUtil {
private GeneratorUtil(){}
public static void addPaymentLink(XmlSerializer xml, String paymentLink, boolean withNamespace) throws IOException {
diff --git a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/RSS2Generator.java b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/RSS2Generator.java
index 27e89620d..f2d53799d 100644
--- a/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/RSS2Generator.java
+++ b/app/src/androidTest/java/de/test/antennapod/util/syndication/feedgenerator/RSS2Generator.java
@@ -1,14 +1,16 @@
package de.test.antennapod.util.syndication.feedgenerator;
import android.util.Xml;
-import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.feed.FeedItem;
-import de.danoeh.antennapod.core.util.DateUtils;
+
import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.io.OutputStream;
+import de.danoeh.antennapod.core.feed.Feed;
+import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.util.DateUtils;
+
/**
* Creates RSS 2.0 feeds. See FeedGenerator for more information.
*/
diff --git a/app/src/free/java/de/danoeh/antennapod/config/CastCallbackImpl.java b/app/src/free/java/de/danoeh/antennapod/config/CastCallbackImpl.java
index 5e714f02c..fb23dfa1a 100644
--- a/app/src/free/java/de/danoeh/antennapod/config/CastCallbackImpl.java
+++ b/app/src/free/java/de/danoeh/antennapod/config/CastCallbackImpl.java
@@ -2,6 +2,6 @@ package de.danoeh.antennapod.config;
import de.danoeh.antennapod.core.CastCallbacks;
-public class CastCallbackImpl implements CastCallbacks {
+class CastCallbackImpl implements CastCallbacks {
}
diff --git a/app/src/free/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java b/app/src/free/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java
index de604c7c4..4e2c40885 100644
--- a/app/src/free/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java
+++ b/app/src/free/java/de/danoeh/antennapod/preferences/PreferenceControllerFlavorHelper.java
@@ -5,7 +5,7 @@ import de.danoeh.antennapod.core.preferences.UserPreferences;
/**
* Implements functions from PreferenceController that are flavor dependent.
*/
-public class PreferenceControllerFlavorHelper {
+class PreferenceControllerFlavorHelper {
static void setupFlavoredUI(PreferenceController.PreferenceUI ui) {
ui.findPreference(UserPreferences.PREF_CAST_ENABLED).setEnabled(false);
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 56d076441..6e62bc227 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -2,8 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.danoeh.antennapod"
android:installLocation="auto"
- android:versionCode="1060402"
- android:versionName="1.6.4.2">
+ android:versionCode="1070000"
+ android:versionName="1.7.0">
<!--
Version code schema:
"1.2.3-SNAPSHOT" -> 1020300
@@ -33,11 +33,12 @@
<application
android:name="de.danoeh.antennapod.PodcastApp"
- android:icon="@drawable/ic_launcher"
+ android:icon="@mipmap/ic_launcher"
+ android:roundIcon="@mipmap/ic_launcher_round"
android:label="@string/app_name"
android:backupAgent=".core.backup.OpmlBackupAgent"
android:restoreAnyVersion="true"
- android:logo="@drawable/ic_launcher">
+ android:logo="@mipmap/ic_launcher">
<meta-data android:name="com.google.android.gms.car.notification.SmallIcon"
android:resource="@drawable/ic_notification" />
<meta-data
@@ -97,7 +98,7 @@
android:launchMode="singleInstance"/>
<activity
- android:name=".activity.PreferenceActivityGingerbread"
+ android:name=".activity.PreferenceActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/settings_label">
<meta-data
@@ -106,24 +107,24 @@
</activity>
<activity
- android:name=".activity.PreferenceActivity"
- android:configChanges="keyboardHidden|orientation|screenSize"
- android:label="@string/settings_label">
- <meta-data
- android:name="android.support.PARENT_ACTIVITY"
- android:value="de.danoeh.antennapod.activity.MainActivity"/>
+ android:name=".activity.FeedInfoActivity"
+ android:label="@string/feed_info_label">
</activity>
- <activity android:name=".activity.FeedInfoActivity">
+ <activity
+ android:name=".activity.FeedSettingsActivity"
+ android:windowSoftInputMode="stateHidden"
+ android:label="@string/feed_settings_label">
</activity>
<service
- android:name=".service.PlayerWidgetService"
+ android:name=".core.service.PlayerWidgetJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE"
android:enabled="true"
android:exported="false">
</service>
- <receiver android:name=".receiver.PlayerWidget">
+ <receiver android:name=".core.receiver.PlayerWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
</intent-filter>
@@ -177,6 +178,13 @@
android:value="de.danoeh.antennapod.activity.PreferenceActivity"/>
</activity>
<activity
+ android:name=".activity.ImportExportActivity"
+ android:label="@string/import_export">
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value="de.danoeh.antennapod.activity.PreferenceActivity"/>
+ </activity>
+ <activity
android:name=".activity.OpmlImportFromPathActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/opml_import_label">
@@ -224,7 +232,8 @@
<activity
android:name=".activity.VideoplayerActivity"
- android:configChanges="keyboardHidden|orientation"
+ android:configChanges="keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize"
+ android:supportsPictureInPicture="true"
android:screenOrientation="sensorLandscape">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
diff --git a/app/src/main/assets/LICENSE_SIL.txt b/app/src/main/assets/LICENSE_SIL.txt
new file mode 100644
index 000000000..f5ed6fa72
--- /dev/null
+++ b/app/src/main/assets/LICENSE_SIL.txt
@@ -0,0 +1,91 @@
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE. \ No newline at end of file
diff --git a/app/src/main/assets/logo.png b/app/src/main/assets/logo.png
index d0e988a6d..3b5261b28 100755
--- a/app/src/main/assets/logo.png
+++ b/app/src/main/assets/logo.png
Binary files differ
diff --git a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java
index f6a8db5fb..3abf7557a 100644
--- a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java
+++ b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java
@@ -41,10 +41,8 @@ public class PodcastApp extends Application {
.detectLeakedSqlLiteObjects()
.penaltyLog()
.penaltyDropBox();
- if (Build.VERSION.SDK_INT >= 11) {
- builder.detectActivityLeaks();
- builder.detectLeakedClosableObjects();
- }
+ builder.detectActivityLeaks();
+ builder.detectLeakedClosableObjects();
if(Build.VERSION.SDK_INT >= 16) {
builder.detectLeakedRegistrationObjects();
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java
index 1b42b274c..141fddd1c 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java
@@ -21,8 +21,7 @@ import java.nio.charset.Charset;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.preferences.UserPreferences;
-import rx.Observable;
-import rx.Subscriber;
+import rx.Single;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
@@ -34,10 +33,8 @@ public class AboutActivity extends AppCompatActivity {
private static final String TAG = AboutActivity.class.getSimpleName();
- private WebView webview;
- private LinearLayout webviewContainer;
- private int depth = 0;
-
+ private WebView webView;
+ private LinearLayout webViewContainer;
private Subscription subscription;
@Override
@@ -46,28 +43,25 @@ public class AboutActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
getSupportActionBar().setDisplayShowHomeEnabled(true);
setContentView(R.layout.about);
- webviewContainer = (LinearLayout) findViewById(R.id.webvContainer);
- webview = (WebView) findViewById(R.id.webvAbout);
- webview.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
+ webViewContainer = (LinearLayout) findViewById(R.id.webViewContainer);
+ webView = (WebView) findViewById(R.id.webViewAbout);
+ webView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
if (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
- if (Build.VERSION.SDK_INT >= 11
- && Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
- webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
+ webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
- webview.setBackgroundColor(Color.TRANSPARENT);
+ webView.setBackgroundColor(Color.TRANSPARENT);
}
- webview.setWebViewClient(new WebViewClient() {
+ webView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
- if(url.startsWith("http")) {
- depth++;
- return false;
- } else {
+ if (!url.startsWith("http")) {
url = url.replace("file:///android_asset/", "");
loadAsset(url);
return true;
}
+ return false;
}
});
@@ -75,69 +69,65 @@ public class AboutActivity extends AppCompatActivity {
}
private void loadAsset(String filename) {
- subscription = Observable.create(new Observable.OnSubscribe<String>() {
- @Override
- public void call(Subscriber<? super String> subscriber) {
- InputStream input = null;
- try {
- TypedArray res = AboutActivity.this.getTheme().obtainStyledAttributes(
- new int[] { android.R.attr.textColorPrimary });
- int colorResource = res.getColor(0, 0);
- String colorString = String.format("#%06X", 0xFFFFFF & colorResource);
- res.recycle();
- input = getAssets().open(filename);
- String webViewData = IOUtils.toString(input, Charset.defaultCharset());
- if(!webViewData.startsWith("<!DOCTYPE html>")) {
- //webViewData = webViewData.replace("\n\n", "</p><p>");
- webViewData = webViewData.replace("%", "&#37;");
- webViewData =
- "<!DOCTYPE html>" +
- "<html>" +
- "<head>" +
- " <meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\">" +
- " <style type=\"text/css\">" +
- " @font-face {" +
- " font-family: 'Roboto-Light';" +
- " src: url('file:///android_asset/Roboto-Light.ttf');" +
- " }" +
- " * {" +
- " color: %s;" +
- " font-family: roboto-Light;" +
- " font-size: 8pt;" +
- " }" +
- " </style>" +
- "</head><body><p>" + webViewData + "</p></body></html>";
- webViewData = webViewData.replace("\n", "<br/>");
- depth++;
- } else {
- depth = 0;
- }
- webViewData = String.format(webViewData, colorString);
- subscriber.onNext(webViewData);
- } catch (IOException e) {
- subscriber.onError(e);
- } finally {
- IOUtils.closeQuietly(input);
- }
- subscriber.onCompleted();
- }
- })
+ subscription = Single.create(subscriber -> {
+ InputStream input = null;
+ try {
+ TypedArray res = AboutActivity.this.getTheme().obtainStyledAttributes(
+ new int[] { R.attr.about_screen_font_color, R.attr.about_screen_background,
+ R.attr.about_screen_card_background, R.attr.about_screen_card_border});
+ String fontColor = String.format("#%06X", 0xFFFFFF & res.getColor(0, 0));
+ String backgroundColor = String.format("#%06X", 0xFFFFFF & res.getColor(1, 0));
+ String cardBackground = String.format("#%06X", 0xFFFFFF & res.getColor(2, 0));
+ String cardBorder = String.format("#%06X", 0xFFFFFF & res.getColor(3, 0));
+ res.recycle();
+ input = getAssets().open(filename);
+ String webViewData = IOUtils.toString(input, Charset.defaultCharset());
+ if (!webViewData.startsWith("<!DOCTYPE html>")) {
+ webViewData = webViewData.replace("%", "&#37;");
+ webViewData =
+ "<!DOCTYPE html>" +
+ "<html>" +
+ "<head>" +
+ " <meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\">" +
+ " <style type=\"text/css\">" +
+ " @font-face {" +
+ " font-family: 'Roboto-Light';" +
+ " src: url('file:///android_asset/Roboto-Light.ttf');" +
+ " }" +
+ " * {" +
+ " color: @fontcolor@;" +
+ " font-family: roboto-Light;" +
+ " font-size: 8pt;" +
+ " }" +
+ " </style>" +
+ "</head><body><p>" + webViewData + "</p></body></html>";
+ webViewData = webViewData.replace("\n", "<br/>");
+ }
+ webViewData = webViewData.replace("@fontcolor@", fontColor);
+ webViewData = webViewData.replace("@background@", backgroundColor);
+ webViewData = webViewData.replace("@card_background@", cardBackground);
+ webViewData = webViewData.replace("@card_border@", cardBorder);
+ subscriber.onSuccess(webViewData);
+ } catch (IOException e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ subscriber.onError(e);
+ } finally {
+ IOUtils.closeQuietly(input);
+ }
+ })
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
- webviewData ->
- webview.loadDataWithBaseURL("file:///android_asset/", webviewData, "text/html", "utf-8", "about:blank"),
+ webViewData ->
+ webView.loadDataWithBaseURL("file:///android_asset/", webViewData.toString(), "text/html", "utf-8", "file:///android_asset/" + filename.toString()),
error -> Log.e(TAG, Log.getStackTraceString(error))
);
}
@Override
public void onBackPressed() {
- Log.d(TAG, "depth: " + depth);
- if(depth == 1) {
- loadAsset("about.html");
- } else if(depth > 1) {
- webview.goBack();
+ if (webView.canGoBack()) {
+ webView.goBack();
} else {
super.onBackPressed();
}
@@ -159,9 +149,9 @@ public class AboutActivity extends AppCompatActivity {
if(subscription != null) {
subscription.unsubscribe();
}
- if (webviewContainer != null && webview != null) {
- webviewContainer.removeAllViews();
- webview.destroy();
+ if (webViewContainer != null && webView != null) {
+ webViewContainer.removeAllViews();
+ webView.destroy();
}
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
index ca214de9e..67dda01cf 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
@@ -6,41 +6,31 @@ import android.text.TextUtils;
import android.util.Log;
import android.view.View;
+import java.text.DecimalFormat;
import java.util.concurrent.atomic.AtomicBoolean;
import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
-import de.danoeh.antennapod.core.util.playback.ExternalMedia;
import de.danoeh.antennapod.dialog.VariableSpeedDialog;
/**
* Activity for playing audio files.
*/
public class AudioplayerActivity extends MediaplayerInfoActivity {
- public static final String TAG = "AudioPlayerActivity";
+ private static final String TAG = "AudioPlayerActivity";
- private AtomicBoolean isSetup = new AtomicBoolean(false);
+ private final AtomicBoolean isSetup = new AtomicBoolean(false);
@Override
protected void onResume() {
super.onResume();
if (TextUtils.equals(getIntent().getAction(), Intent.ACTION_VIEW)) {
- Intent intent = getIntent();
- Log.d(TAG, "Received VIEW intent: " + intent.getData().getPath());
- ExternalMedia media = new ExternalMedia(intent.getData().getPath(),
- MediaType.AUDIO);
- Intent launchIntent = new Intent(this, PlaybackService.class);
- launchIntent.putExtra(PlaybackService.EXTRA_PLAYABLE, media);
- launchIntent.putExtra(PlaybackService.EXTRA_START_WHEN_PREPARED,
- true);
- launchIntent.putExtra(PlaybackService.EXTRA_SHOULD_STREAM, false);
- launchIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY,
- true);
- startService(launchIntent);
+ playExternalMedia(getIntent(), MediaType.AUDIO);
} else if (PlaybackService.isCasting()) {
Intent intent = PlaybackService.getPlayerActivityIntent(this);
- if (!intent.getComponent().getClassName().equals(AudioplayerActivity.class.getName())) {
+ if (intent.getComponent() != null &&
+ !intent.getComponent().getClassName().equals(AudioplayerActivity.class.getName())) {
saveCurrentFragment();
finish();
startActivity(intent);
@@ -95,7 +85,7 @@ public class AudioplayerActivity extends MediaplayerInfoActivity {
UserPreferences.setPlaybackSpeed(String.valueOf(speed));
}
}
- String speedStr = String.format("%.2fx", speed);
+ String speedStr = new DecimalFormat("0.00x").format(speed);
butPlaybackSpeed.setText(speedStr);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java
index a7e9b1e70..871e9c279 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java
@@ -13,9 +13,9 @@ import de.danoeh.antennapod.core.service.playback.PlaybackService;
* Activity for controlling the remote playback on a Cast device.
*/
public class CastplayerActivity extends MediaplayerInfoActivity {
- public static final String TAG = "CastPlayerActivity";
+ private static final String TAG = "CastPlayerActivity";
- private AtomicBoolean isSetup = new AtomicBoolean(false);
+ private final AtomicBoolean isSetup = new AtomicBoolean(false);
@Override
protected void onCreate(Bundle savedInstanceState) {
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java
index 41b2debdc..e726afaec 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java
@@ -3,15 +3,14 @@ package de.danoeh.antennapod.activity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
-import android.util.Log;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import org.apache.commons.lang3.Validate;
-import de.danoeh.antennapod.BuildConfig;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.download.DownloadRequest;
@@ -23,8 +22,7 @@ import de.danoeh.antennapod.core.storage.DownloadRequester;
* Other arguments are optional.
* The activity's result will be the same DownloadRequest with the entered username and password.
*/
-public class DownloadAuthenticationActivity extends ActionBarActivity {
- private static final String TAG = "DownloadAuthenticationActivity";
+public class DownloadAuthenticationActivity extends AppCompatActivity {
/**
* The download request object that contains information about the resource that requires a username and a password
@@ -36,47 +34,39 @@ public class DownloadAuthenticationActivity extends ActionBarActivity {
*/
public static final String ARG_SEND_TO_DOWNLOAD_REQUESTER_BOOL = "send_to_downloadrequester";
- public static final String RESULT_REQUEST = "request";
+ private static final String RESULT_REQUEST = "request";
private EditText etxtUsername;
private EditText etxtPassword;
- private Button butConfirm;
- private Button butCancel;
- private TextView txtvDescription;
-
- private DownloadRequest request;
- private boolean sendToDownloadRequester;
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(UserPreferences.getTheme());
super.onCreate(savedInstanceState);
- getSupportActionBar().hide();
- setContentView(R.layout.download_authentication_activity);
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.hide();
+ }
+ setContentView(R.layout.download_authentication_activity);
+ TextView txtvDescription = (TextView) findViewById(R.id.txtvDescription);
etxtUsername = (EditText) findViewById(R.id.etxtUsername);
etxtPassword = (EditText) findViewById(R.id.etxtPassword);
- butConfirm = (Button) findViewById(R.id.butConfirm);
- butCancel = (Button) findViewById(R.id.butCancel);
- txtvDescription = (TextView) findViewById(R.id.txtvDescription);
+ Button butConfirm = (Button) findViewById(R.id.butConfirm);
+ Button butCancel = (Button) findViewById(R.id.butCancel);
Validate.isTrue(getIntent().hasExtra(ARG_DOWNLOAD_REQUEST), "Download request missing");
+ DownloadRequest request = getIntent().getParcelableExtra(ARG_DOWNLOAD_REQUEST);
+ boolean sendToDownloadRequester = getIntent().getBooleanExtra(ARG_SEND_TO_DOWNLOAD_REQUESTER_BOOL, false);
- request = getIntent().getParcelableExtra(ARG_DOWNLOAD_REQUEST);
- sendToDownloadRequester = getIntent().getBooleanExtra(ARG_SEND_TO_DOWNLOAD_REQUESTER_BOOL, false);
+ String newDescription = txtvDescription.getText() + ":\n\n" + request.getTitle();
+ txtvDescription.setText(newDescription);
if (savedInstanceState != null) {
etxtUsername.setText(savedInstanceState.getString("username"));
etxtPassword.setText(savedInstanceState.getString("password"));
}
- txtvDescription.setText(txtvDescription.getText() + ":\n\n" + request.getTitle());
-
- butCancel.setOnClickListener(v -> {
- setResult(Activity.RESULT_CANCELED);
- finish();
- });
-
butConfirm.setOnClickListener(v -> {
String username = etxtUsername.getText().toString();
String password = etxtPassword.getText().toString();
@@ -87,11 +77,16 @@ public class DownloadAuthenticationActivity extends ActionBarActivity {
setResult(Activity.RESULT_OK, result);
if (sendToDownloadRequester) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Sending request to DownloadRequester");
DownloadRequester.getInstance().download(DownloadAuthenticationActivity.this, request);
}
finish();
});
+
+ butCancel.setOnClickListener(v -> {
+ setResult(Activity.RESULT_CANCELED);
+ finish();
+ });
+
}
@Override
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java
index 2a58d5104..6b1272b01 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java
@@ -2,51 +2,37 @@ package de.danoeh.antennapod.activity;
import android.content.ClipData;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
+import android.graphics.LightingColorFilter;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
-import android.text.Editable;
import android.text.TextUtils;
-import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemSelectedListener;
-import android.widget.CheckBox;
-import android.widget.EditText;
import android.widget.ImageView;
-import android.widget.RadioButton;
-import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
-
import com.bumptech.glide.Glide;
import com.joanzapata.iconify.Iconify;
-
-import org.apache.commons.lang3.StringUtils;
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Document;
-
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.feed.FeedFilter;
-import de.danoeh.antennapod.core.feed.FeedPreferences;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
+import de.danoeh.antennapod.core.glide.FastBlurTransformation;
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.DownloadRequestException;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.LangUtils;
import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText;
import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
+import org.apache.commons.lang3.StringUtils;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
@@ -59,7 +45,6 @@ public class FeedInfoActivity extends AppCompatActivity {
public static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId";
private static final String TAG = "FeedInfoActivity";
- private boolean autoDeleteChanged = false;
private Feed feed;
private ImageView imgvCover;
@@ -70,15 +55,6 @@ public class FeedInfoActivity extends AppCompatActivity {
private TextView lblAuthor;
private TextView txtvAuthor;
private TextView txtvUrl;
- private EditText etxtUsername;
- private EditText etxtPassword;
- private EditText etxtFilterText;
- private RadioButton rdoFilterInclude;
- private RadioButton rdoFilterExclude;
- private CheckBox cbxAutoDownload;
- private CheckBox cbxKeepUpdated;
- private Spinner spnAutoDelete;
- private boolean filterInclude = true;
private Subscription subscription;
@@ -88,56 +64,16 @@ public class FeedInfoActivity extends AppCompatActivity {
public void onClick(View v) {
if(feed != null && feed.getDownload_url() != null) {
String url = feed.getDownload_url();
- if (android.os.Build.VERSION.SDK_INT >= 11) {
- ClipData clipData = ClipData.newPlainText(url, url);
- android.content.ClipboardManager cm = (android.content.ClipboardManager) FeedInfoActivity.this
- .getSystemService(Context.CLIPBOARD_SERVICE);
- cm.setPrimaryClip(clipData);
- } else {
- android.text.ClipboardManager cm = (android.text.ClipboardManager) FeedInfoActivity.this
- .getSystemService(Context.CLIPBOARD_SERVICE);
- cm.setText(url);
- }
+ ClipData clipData = ClipData.newPlainText(url, url);
+ android.content.ClipboardManager cm = (android.content.ClipboardManager) FeedInfoActivity.this
+ .getSystemService(Context.CLIPBOARD_SERVICE);
+ cm.setPrimaryClip(clipData);
Toast t = Toast.makeText(FeedInfoActivity.this, R.string.copied_url_msg, Toast.LENGTH_SHORT);
t.show();
}
}
};
- private boolean authInfoChanged = false;
-
- private TextWatcher authTextWatcher = new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- authInfoChanged = true;
- }
- };
-
- private boolean filterTextChanged = false;
-
- private TextWatcher filterTextWatcher = new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- filterTextChanged = true;
- }
- };
-
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(UserPreferences.getTheme());
@@ -148,28 +84,20 @@ public class FeedInfoActivity extends AppCompatActivity {
imgvCover = (ImageView) findViewById(R.id.imgvCover);
txtvTitle = (TextView) findViewById(R.id.txtvTitle);
+ TextView txtvAuthorHeader = (TextView) findViewById(R.id.txtvAuthor);
+ ImageView imgvBackground = (ImageView) findViewById(R.id.imgvBackground);
+ findViewById(R.id.butShowInfo).setVisibility(View.INVISIBLE);
+ findViewById(R.id.butShowSettings).setVisibility(View.INVISIBLE);
+ // https://github.com/bumptech/glide/issues/529
+ imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000));
+
+
txtvDescription = (TextView) findViewById(R.id.txtvDescription);
lblLanguage = (TextView) findViewById(R.id.lblLanguage);
txtvLanguage = (TextView) findViewById(R.id.txtvLanguage);
lblAuthor = (TextView) findViewById(R.id.lblAuthor);
- txtvAuthor = (TextView) findViewById(R.id.txtvAuthor);
+ txtvAuthor = (TextView) findViewById(R.id.txtvDetailsAuthor);
txtvUrl = (TextView) findViewById(R.id.txtvUrl);
- cbxAutoDownload = (CheckBox) findViewById(R.id.cbxAutoDownload);
- cbxKeepUpdated = (CheckBox) findViewById(R.id.cbxKeepUpdated);
- spnAutoDelete = (Spinner) findViewById(R.id.spnAutoDelete);
- etxtUsername = (EditText) findViewById(R.id.etxtUsername);
- etxtPassword = (EditText) findViewById(R.id.etxtPassword);
- etxtFilterText = (EditText) findViewById(R.id.etxtEpisodeFilterText);
- rdoFilterInclude = (RadioButton) findViewById(R.id.radio_filter_include);
- rdoFilterInclude.setOnClickListener(v -> {
- filterInclude = true;
- filterTextChanged = true;
- });
- rdoFilterExclude = (RadioButton) findViewById(R.id.radio_filter_exclude);
- rdoFilterExclude.setOnClickListener(v -> {
- filterInclude = false;
- filterTextChanged = true;
- });
txtvUrl.setOnClickListener(copyUrlToClipboard);
@@ -185,7 +113,6 @@ public class FeedInfoActivity extends AppCompatActivity {
Log.d(TAG, "Language is " + feed.getLanguage());
Log.d(TAG, "Author is " + feed.getAuthor());
Log.d(TAG, "URL is " + feed.getDownload_url());
- FeedPreferences prefs = feed.getPreferences();
Glide.with(FeedInfoActivity.this)
.load(feed.getImageLocation())
.placeholder(R.color.light_gray)
@@ -194,6 +121,14 @@ public class FeedInfoActivity extends AppCompatActivity {
.fitCenter()
.dontAnimate()
.into(imgvCover);
+ Glide.with(FeedInfoActivity.this)
+ .load(feed.getImageLocation())
+ .placeholder(R.color.image_readability_tint)
+ .error(R.color.image_readability_tint)
+ .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
+ .transform(new FastBlurTransformation(FeedInfoActivity.this))
+ .dontAnimate()
+ .into(imgvBackground);
txtvTitle.setText(feed.getTitle());
@@ -211,6 +146,7 @@ public class FeedInfoActivity extends AppCompatActivity {
if (!TextUtils.isEmpty(feed.getAuthor())) {
txtvAuthor.setText(feed.getAuthor());
+ txtvAuthorHeader.setText(feed.getAuthor());
} else {
lblAuthor.setVisibility(View.GONE);
txtvAuthor.setVisibility(View.GONE);
@@ -224,76 +160,7 @@ public class FeedInfoActivity extends AppCompatActivity {
txtvUrl.setText(feed.getDownload_url() + " {fa-paperclip}");
Iconify.addIcons(txtvUrl);
- cbxAutoDownload.setEnabled(UserPreferences.isEnableAutodownload());
- cbxAutoDownload.setChecked(prefs.getAutoDownload());
- cbxAutoDownload.setOnCheckedChangeListener((compoundButton, checked) -> {
- feed.getPreferences().setAutoDownload(checked);
- feed.savePreferences();
- updateAutoDownloadSettings();
- ApplyToEpisodesDialog dialog = new ApplyToEpisodesDialog(FeedInfoActivity.this,
- feed, checked);
- dialog.createNewDialog().show();
- });
- cbxKeepUpdated.setChecked(prefs.getKeepUpdated());
- cbxKeepUpdated.setOnCheckedChangeListener((compoundButton, checked) -> {
- feed.getPreferences().setKeepUpdated(checked);
- feed.savePreferences();
- });
- spnAutoDelete.setOnItemSelectedListener(new OnItemSelectedListener() {
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
- FeedPreferences.AutoDeleteAction auto_delete_action;
- switch (parent.getSelectedItemPosition()) {
- case 0:
- auto_delete_action = FeedPreferences.AutoDeleteAction.GLOBAL;
- break;
- case 1:
- auto_delete_action = FeedPreferences.AutoDeleteAction.YES;
- break;
- case 2:
- auto_delete_action = FeedPreferences.AutoDeleteAction.NO;
- break;
- default: // TODO - add exceptions here
- return;
- }
- feed.getPreferences().setAutoDeleteAction(auto_delete_action);// p
- autoDeleteChanged = true;
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
- // Another interface callback
- }
- });
- spnAutoDelete.setSelection(prefs.getAutoDeleteAction().ordinal());
-
- etxtUsername.setText(prefs.getUsername());
- etxtPassword.setText(prefs.getPassword());
-
- etxtUsername.addTextChangedListener(authTextWatcher);
- etxtPassword.addTextChangedListener(authTextWatcher);
-
- FeedFilter filter = prefs.getFilter();
- if (filter.includeOnly()) {
- etxtFilterText.setText(filter.getIncludeFilter());
- rdoFilterInclude.setChecked(true);
- rdoFilterExclude.setChecked(false);
- filterInclude = true;
- } else if (filter.excludeOnly()) {
- etxtFilterText.setText(filter.getExcludeFilter());
- rdoFilterInclude.setChecked(false);
- rdoFilterExclude.setChecked(true);
- filterInclude = false;
- } else {
- Log.d(TAG, "No filter set");
- rdoFilterInclude.setChecked(false);
- rdoFilterExclude.setChecked(false);
- etxtFilterText.setText("");
- }
- etxtFilterText.addTextChangedListener(filterTextWatcher);
-
supportInvalidateOptionsMenu();
- updateAutoDownloadSettings();
}, error -> {
Log.d(TAG, Log.getStackTraceString(error));
finish();
@@ -301,37 +168,6 @@ public class FeedInfoActivity extends AppCompatActivity {
}
@Override
- protected void onPause() {
- super.onPause();
- if (feed != null) {
- FeedPreferences prefs = feed.getPreferences();
- if (authInfoChanged) {
- Log.d(TAG, "Auth info changed, saving credentials");
- prefs.setUsername(etxtUsername.getText().toString());
- prefs.setPassword(etxtPassword.getText().toString());
- }
- if (filterTextChanged) {
- Log.d(TAG, "Filter info changed, saving...");
- String filterText = etxtFilterText.getText().toString();
- String includeString = "";
- String excludeString = "";
- if (filterInclude) {
- includeString = filterText;
- } else {
- excludeString = filterText;
- }
- prefs.setFilter(new FeedFilter(includeString, excludeString));
- }
- if (authInfoChanged || autoDeleteChanged || filterTextChanged) {
- DBWriter.setFeedPreferences(prefs);
- }
- authInfoChanged = false;
- autoDeleteChanged = false;
- filterTextChanged = false;
- }
- }
-
- @Override
public void onDestroy() {
super.onDestroy();
if(subscription != null) {
@@ -375,34 +211,4 @@ public class FeedInfoActivity extends AppCompatActivity {
return super.onOptionsItemSelected(item);
}
}
-
- private void updateAutoDownloadSettings() {
- if (feed != null && feed.getPreferences() != null) {
- boolean enabled = feed.getPreferences().getAutoDownload() && UserPreferences.isEnableAutodownload();
- rdoFilterInclude.setEnabled(enabled);
- rdoFilterExclude.setEnabled(enabled);
- etxtFilterText.setEnabled(enabled);
- }
- }
-
- private class ApplyToEpisodesDialog extends ConfirmationDialog {
-
- private final Feed feed;
- private final boolean autoDownload;
-
- ApplyToEpisodesDialog(Context context, Feed feed, boolean autoDownload) {
- super(context, R.string.auto_download_apply_to_items_title,
- R.string.auto_download_apply_to_items_message);
- this.feed = feed;
- this.autoDownload = autoDownload;
- setPositiveText(R.string.yes);
- setNegativeText(R.string.no);
- }
-
- @Override
- public void onConfirmButtonPressed(DialogInterface dialog) {
- DBWriter.setFeedsItemsAutoDownload(feed, autoDownload);
- }
- }
-
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/FeedSettingsActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/FeedSettingsActivity.java
new file mode 100644
index 000000000..5e15585a5
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/activity/FeedSettingsActivity.java
@@ -0,0 +1,370 @@
+package de.danoeh.antennapod.activity;
+
+import android.content.ClipData;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.graphics.LightingColorFilter;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.RadioButton;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.Toast;
+import com.bumptech.glide.Glide;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
+import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
+import de.danoeh.antennapod.core.feed.Feed;
+import de.danoeh.antennapod.core.feed.FeedFilter;
+import de.danoeh.antennapod.core.feed.FeedPreferences;
+import de.danoeh.antennapod.core.glide.ApGlideSettings;
+import de.danoeh.antennapod.core.glide.FastBlurTransformation;
+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.DownloadRequestException;
+import de.danoeh.antennapod.core.util.IntentUtils;
+import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
+import rx.Observable;
+import rx.Subscription;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.schedulers.Schedulers;
+
+/**
+ * Displays information about a feed.
+ */
+public class FeedSettingsActivity extends AppCompatActivity {
+
+ public static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId";
+ private static final String TAG = "FeedSettingsActivity";
+ private boolean autoDeleteChanged = false;
+ private Feed feed;
+
+ private ImageView imgvCover;
+ private TextView txtvTitle;
+ private EditText etxtUsername;
+ private EditText etxtPassword;
+ private EditText etxtFilterText;
+ private RadioButton rdoFilterInclude;
+ private RadioButton rdoFilterExclude;
+ private CheckBox cbxAutoDownload;
+ private CheckBox cbxKeepUpdated;
+ private Spinner spnAutoDelete;
+ private boolean filterInclude = true;
+
+ private Subscription subscription;
+
+
+ private final View.OnClickListener copyUrlToClipboard = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if(feed != null && feed.getDownload_url() != null) {
+ String url = feed.getDownload_url();
+ ClipData clipData = ClipData.newPlainText(url, url);
+ android.content.ClipboardManager cm = (android.content.ClipboardManager) FeedSettingsActivity.this
+ .getSystemService(Context.CLIPBOARD_SERVICE);
+ cm.setPrimaryClip(clipData);
+ Toast t = Toast.makeText(FeedSettingsActivity.this, R.string.copied_url_msg, Toast.LENGTH_SHORT);
+ t.show();
+ }
+ }
+ };
+
+ private boolean authInfoChanged = false;
+
+ private final TextWatcher authTextWatcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ authInfoChanged = true;
+ }
+ };
+
+ private boolean filterTextChanged = false;
+
+ private final TextWatcher filterTextWatcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ filterTextChanged = true;
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ setTheme(UserPreferences.getTheme());
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.feedsettings);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ long feedId = getIntent().getLongExtra(EXTRA_FEED_ID, -1);
+
+ imgvCover = (ImageView) findViewById(R.id.imgvCover);
+ txtvTitle = (TextView) findViewById(R.id.txtvTitle);
+ TextView txtvAuthorHeader = (TextView) findViewById(R.id.txtvAuthor);
+ ImageView imgvBackground = (ImageView) findViewById(R.id.imgvBackground);
+ findViewById(R.id.butShowInfo).setVisibility(View.INVISIBLE);
+ findViewById(R.id.butShowSettings).setVisibility(View.INVISIBLE);
+ // https://github.com/bumptech/glide/issues/529
+ imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000));
+
+ cbxAutoDownload = (CheckBox) findViewById(R.id.cbxAutoDownload);
+ cbxKeepUpdated = (CheckBox) findViewById(R.id.cbxKeepUpdated);
+ spnAutoDelete = (Spinner) findViewById(R.id.spnAutoDelete);
+ etxtUsername = (EditText) findViewById(R.id.etxtUsername);
+ etxtPassword = (EditText) findViewById(R.id.etxtPassword);
+ etxtFilterText = (EditText) findViewById(R.id.etxtEpisodeFilterText);
+ rdoFilterInclude = (RadioButton) findViewById(R.id.radio_filter_include);
+ rdoFilterInclude.setOnClickListener(v -> {
+ filterInclude = true;
+ filterTextChanged = true;
+ });
+ rdoFilterExclude = (RadioButton) findViewById(R.id.radio_filter_exclude);
+ rdoFilterExclude.setOnClickListener(v -> {
+ filterInclude = false;
+ filterTextChanged = true;
+ });
+
+ subscription = Observable.fromCallable(()-> DBReader.getFeed(feedId))
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(result -> {
+ if (result == null) {
+ Log.e(TAG, "Activity was started with invalid arguments");
+ finish();
+ }
+ feed = result;
+ FeedPreferences prefs = feed.getPreferences();
+ Glide.with(FeedSettingsActivity.this)
+ .load(feed.getImageLocation())
+ .placeholder(R.color.light_gray)
+ .error(R.color.light_gray)
+ .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
+ .fitCenter()
+ .dontAnimate()
+ .into(imgvCover);
+ Glide.with(FeedSettingsActivity.this)
+ .load(feed.getImageLocation())
+ .placeholder(R.color.image_readability_tint)
+ .error(R.color.image_readability_tint)
+ .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
+ .transform(new FastBlurTransformation(FeedSettingsActivity.this))
+ .dontAnimate()
+ .into(imgvBackground);
+
+ txtvTitle.setText(feed.getTitle());
+
+ if (!TextUtils.isEmpty(feed.getAuthor())) {
+ txtvAuthorHeader.setText(feed.getAuthor());
+ }
+
+ cbxAutoDownload.setEnabled(UserPreferences.isEnableAutodownload());
+ cbxAutoDownload.setChecked(prefs.getAutoDownload());
+ cbxAutoDownload.setOnCheckedChangeListener((compoundButton, checked) -> {
+ feed.getPreferences().setAutoDownload(checked);
+ feed.savePreferences();
+ updateAutoDownloadSettings();
+ ApplyToEpisodesDialog dialog = new ApplyToEpisodesDialog(FeedSettingsActivity.this,
+ feed, checked);
+ dialog.createNewDialog().show();
+ });
+ cbxKeepUpdated.setChecked(prefs.getKeepUpdated());
+ cbxKeepUpdated.setOnCheckedChangeListener((compoundButton, checked) -> {
+ feed.getPreferences().setKeepUpdated(checked);
+ feed.savePreferences();
+ });
+ spnAutoDelete.setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+ FeedPreferences.AutoDeleteAction auto_delete_action;
+ switch (parent.getSelectedItemPosition()) {
+ case 0:
+ auto_delete_action = FeedPreferences.AutoDeleteAction.GLOBAL;
+ break;
+ case 1:
+ auto_delete_action = FeedPreferences.AutoDeleteAction.YES;
+ break;
+ case 2:
+ auto_delete_action = FeedPreferences.AutoDeleteAction.NO;
+ break;
+ default: // TODO - add exceptions here
+ return;
+ }
+ feed.getPreferences().setAutoDeleteAction(auto_delete_action);// p
+ autoDeleteChanged = true;
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ // Another interface callback
+ }
+ });
+ spnAutoDelete.setSelection(prefs.getAutoDeleteAction().ordinal());
+
+ etxtUsername.setText(prefs.getUsername());
+ etxtPassword.setText(prefs.getPassword());
+
+ etxtUsername.addTextChangedListener(authTextWatcher);
+ etxtPassword.addTextChangedListener(authTextWatcher);
+
+ FeedFilter filter = prefs.getFilter();
+ if (filter.includeOnly()) {
+ etxtFilterText.setText(filter.getIncludeFilter());
+ rdoFilterInclude.setChecked(true);
+ rdoFilterExclude.setChecked(false);
+ filterInclude = true;
+ } else if (filter.excludeOnly()) {
+ etxtFilterText.setText(filter.getExcludeFilter());
+ rdoFilterInclude.setChecked(false);
+ rdoFilterExclude.setChecked(true);
+ filterInclude = false;
+ } else {
+ Log.d(TAG, "No filter set");
+ rdoFilterInclude.setChecked(false);
+ rdoFilterExclude.setChecked(false);
+ etxtFilterText.setText("");
+ }
+ etxtFilterText.addTextChangedListener(filterTextWatcher);
+
+ supportInvalidateOptionsMenu();
+ updateAutoDownloadSettings();
+ }, error -> {
+ Log.d(TAG, Log.getStackTraceString(error));
+ finish();
+ });
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (feed != null) {
+ FeedPreferences prefs = feed.getPreferences();
+ if (authInfoChanged) {
+ Log.d(TAG, "Auth info changed, saving credentials");
+ prefs.setUsername(etxtUsername.getText().toString());
+ prefs.setPassword(etxtPassword.getText().toString());
+ }
+ if (filterTextChanged) {
+ Log.d(TAG, "Filter info changed, saving...");
+ String filterText = etxtFilterText.getText().toString();
+ String includeString = "";
+ String excludeString = "";
+ if (filterInclude) {
+ includeString = filterText;
+ } else {
+ excludeString = filterText;
+ }
+ prefs.setFilter(new FeedFilter(includeString, excludeString));
+ }
+ if (authInfoChanged || autoDeleteChanged || filterTextChanged) {
+ DBWriter.setFeedPreferences(prefs);
+ }
+ authInfoChanged = false;
+ autoDeleteChanged = false;
+ filterTextChanged = false;
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if(subscription != null) {
+ subscription.unsubscribe();
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.feedinfo, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ menu.findItem(R.id.support_item).setVisible(
+ feed != null && feed.getPaymentLink() != null);
+ menu.findItem(R.id.share_link_item).setVisible(feed != null && feed.getLink() != null);
+ menu.findItem(R.id.visit_website_item).setVisible(feed != null && feed.getLink() != null &&
+ IntentUtils.isCallable(this, new Intent(Intent.ACTION_VIEW, Uri.parse(feed.getLink()))));
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ finish();
+ return true;
+ default:
+ try {
+ return FeedMenuHandler.onOptionsItemClicked(this, item, feed);
+ } catch (DownloadRequestException e) {
+ e.printStackTrace();
+ DownloadRequestErrorDialogCreator.newRequestErrorDialog(this,
+ e.getMessage());
+ }
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ private void updateAutoDownloadSettings() {
+ if (feed != null && feed.getPreferences() != null) {
+ boolean enabled = feed.getPreferences().getAutoDownload() && UserPreferences.isEnableAutodownload();
+ rdoFilterInclude.setEnabled(enabled);
+ rdoFilterExclude.setEnabled(enabled);
+ etxtFilterText.setEnabled(enabled);
+ }
+ }
+
+ private static class ApplyToEpisodesDialog extends ConfirmationDialog {
+
+ private final Feed feed;
+ private final boolean autoDownload;
+
+ ApplyToEpisodesDialog(Context context, Feed feed, boolean autoDownload) {
+ super(context, R.string.auto_download_apply_to_items_title,
+ R.string.auto_download_apply_to_items_message);
+ this.feed = feed;
+ this.autoDownload = autoDownload;
+ setPositiveText(R.string.yes);
+ setNegativeText(R.string.no);
+ }
+
+ @Override
+ public void onConfirmButtonPressed(DialogInterface dialog) {
+ DBWriter.setFeedsItemsAutoDownload(feed, autoDownload);
+ }
+ }
+
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/FlattrAuthActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/FlattrAuthActivity.java
index be1c9f9e6..26352f58f 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/FlattrAuthActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/FlattrAuthActivity.java
@@ -4,7 +4,7 @@ package de.danoeh.antennapod.activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@@ -18,11 +18,10 @@ import de.danoeh.antennapod.BuildConfig;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.util.flattr.FlattrUtils;
-import de.danoeh.antennapod.preferences.PreferenceController;
/** Guides the user through the authentication process */
-public class FlattrAuthActivity extends ActionBarActivity {
+public class FlattrAuthActivity extends AppCompatActivity {
private static final String TAG = "FlattrAuthActivity";
private TextView txtvExplanation;
@@ -104,7 +103,7 @@ public class FlattrAuthActivity extends ActionBarActivity {
switch (item.getItemId()) {
case android.R.id.home:
if (authSuccessful) {
- Intent intent = new Intent(this, PreferenceController.getPreferenceActivity());
+ Intent intent = new Intent(this, PreferenceActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
} else {
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/ImportExportActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/ImportExportActivity.java
new file mode 100644
index 000000000..91462bce9
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/activity/ImportExportActivity.java
@@ -0,0 +1,188 @@
+package de.danoeh.antennapod.activity;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.ParcelFileDescriptor;
+import android.support.design.widget.Snackbar;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
+import android.util.Log;
+import android.view.MenuItem;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.storage.PodDBAdapter;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.channels.FileChannel;
+
+/**
+ * Displays the 'import/export' screen
+ */
+public class ImportExportActivity extends AppCompatActivity {
+ private static final int REQUEST_CODE_RESTORE = 43;
+ private static final int REQUEST_CODE_BACKUP_DOCUMENT = 44;
+ private static final String EXPORT_FILENAME = "AntennaPodBackup.db";
+ private static final String TAG = ImportExportActivity.class.getSimpleName();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ setTheme(UserPreferences.getTheme());
+ super.onCreate(savedInstanceState);
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayShowHomeEnabled(true);
+ }
+ setContentView(R.layout.import_export_activity);
+
+ findViewById(R.id.button_export).setOnClickListener(view -> backup());
+ findViewById(R.id.button_import).setOnClickListener(view -> restore());
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ return true;
+ } else {
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ private void backup() {
+ if (Build.VERSION.SDK_INT >= 19) {
+ Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT)
+ .addCategory(Intent.CATEGORY_OPENABLE)
+ .setType("application/x-sqlite3")
+ .putExtra(Intent.EXTRA_TITLE, EXPORT_FILENAME);
+
+ startActivityForResult(intent, REQUEST_CODE_BACKUP_DOCUMENT);
+ } else {
+ try {
+ File sd = Environment.getExternalStorageDirectory();
+ File backupDB = new File(sd, EXPORT_FILENAME);
+ writeBackupTo(new FileOutputStream(backupDB));
+ } catch (IOException e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ Snackbar.make(findViewById(R.id.import_export_layout), e.getLocalizedMessage(), Snackbar.LENGTH_SHORT).show();
+ }
+ }
+ }
+
+ private void restore() {
+ if (Build.VERSION.SDK_INT >= 19) {
+ Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.setType("*/*");
+ startActivityForResult(intent, REQUEST_CODE_RESTORE);
+ } else {
+ Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.setType("*/*");
+ startActivityForResult(Intent.createChooser(intent,
+ getString(R.string.import_select_file)), REQUEST_CODE_RESTORE);
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent resultData) {
+ if (resultCode != RESULT_OK || resultData == null) {
+ return;
+ }
+ Uri uri = resultData.getData();
+
+ if (requestCode == REQUEST_CODE_RESTORE) {
+ restoreFrom(uri);
+ } else if (requestCode == REQUEST_CODE_BACKUP_DOCUMENT) {
+ backupToDocument(uri);
+ }
+ }
+
+ private void restoreFrom(Uri inputUri) {
+ File currentDB = getDatabasePath(PodDBAdapter.DATABASE_NAME);
+ InputStream inputStream = null;
+ try {
+ inputStream = getContentResolver().openInputStream(inputUri);
+ FileUtils.copyInputStreamToFile(inputStream, currentDB);
+ displayImportSuccessDialog();
+ } catch (IOException e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ Snackbar.make(findViewById(R.id.import_export_layout), e.getLocalizedMessage(), Snackbar.LENGTH_SHORT).show();
+ } finally {
+ IOUtils.closeQuietly(inputStream);
+ }
+ }
+
+ private void displayImportSuccessDialog() {
+ AlertDialog.Builder d = new AlertDialog.Builder(ImportExportActivity.this);
+ d.setMessage(R.string.import_ok);
+ d.setCancelable(false);
+ d.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
+ Intent intent = new Intent(getApplicationContext(), SplashActivity.class);
+ ComponentName cn = intent.getComponent();
+ Intent mainIntent = Intent.makeRestartActivityTask(cn);
+ startActivity(mainIntent);
+ });
+ d.show();
+ }
+
+ private void backupToDocument(Uri uri) {
+ ParcelFileDescriptor pfd = null;
+ FileOutputStream fileOutputStream = null;
+ try {
+ pfd = getContentResolver().openFileDescriptor(uri, "w");
+ fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
+ writeBackupTo(fileOutputStream);
+
+ Snackbar.make(findViewById(R.id.import_export_layout),
+ R.string.export_ok, Snackbar.LENGTH_SHORT).show();
+ } catch (IOException e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ Snackbar.make(findViewById(R.id.import_export_layout), e.getLocalizedMessage(), Snackbar.LENGTH_SHORT).show();
+ } finally {
+ IOUtils.closeQuietly(fileOutputStream);
+
+ if (pfd != null) {
+ try {
+ pfd.close();
+ } catch (IOException e) {
+ Log.d(TAG, "Unable to close ParcelFileDescriptor");
+ }
+ }
+ }
+ }
+
+ private void writeBackupTo(FileOutputStream outFileStream) {
+ FileChannel src = null;
+ FileChannel dst = null;
+ try {
+ File currentDB = getDatabasePath(PodDBAdapter.DATABASE_NAME);
+
+ if (currentDB.exists()) {
+ src = new FileInputStream(currentDB).getChannel();
+ dst = outFileStream.getChannel();
+ dst.transferFrom(src, 0, src.size());
+
+ Snackbar.make(findViewById(R.id.import_export_layout),
+ R.string.export_ok, Snackbar.LENGTH_SHORT).show();
+ } else {
+ Snackbar.make(findViewById(R.id.import_export_layout),
+ "Can not access current database", Snackbar.LENGTH_SHORT).show();
+ }
+ } catch (IOException e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ Snackbar.make(findViewById(R.id.import_export_layout), e.getLocalizedMessage(), Snackbar.LENGTH_SHORT).show();
+ } finally {
+ IOUtils.closeQuietly(src);
+ IOUtils.closeQuietly(dst);
+ }
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
index f0fcdca90..0879b2cec 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
@@ -30,6 +30,9 @@ import android.widget.ListView;
import com.bumptech.glide.Glide;
+import de.danoeh.antennapod.core.event.ServiceEvent;
+import de.danoeh.antennapod.core.util.IntentUtils;
+import de.danoeh.antennapod.core.util.gui.NotificationUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.Validate;
@@ -64,7 +67,6 @@ import de.danoeh.antennapod.fragment.PlaybackHistoryFragment;
import de.danoeh.antennapod.fragment.QueueFragment;
import de.danoeh.antennapod.fragment.SubscriptionFragment;
import de.danoeh.antennapod.menuhandler.NavDrawerActivity;
-import de.danoeh.antennapod.preferences.PreferenceController;
import de.greenrobot.event.EventBus;
import rx.Observable;
import rx.Subscription;
@@ -83,7 +85,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
public static final String PREF_NAME = "MainActivityPrefs";
public static final String PREF_IS_FIRST_LAUNCH = "prefMainActivityIsFirstLaunch";
- public static final String PREF_LAST_FRAGMENT_TAG = "prefMainActivityLastFragmentTag";
+ private static final String PREF_LAST_FRAGMENT_TAG = "prefMainActivityLastFragmentTag";
public static final String EXTRA_NAV_TYPE = "nav_type";
public static final String EXTRA_NAV_INDEX = "nav_index";
@@ -91,8 +93,8 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
public static final String EXTRA_FRAGMENT_ARGS = "fragment_args";
public static final String EXTRA_FEED_ID = "fragment_feed_id";
- public static final String SAVE_BACKSTACK_COUNT = "backstackCount";
- public static final String SAVE_TITLE = "title";
+ private static final String SAVE_BACKSTACK_COUNT = "backstackCount";
+ private static final String SAVE_TITLE = "title";
public static final String[] NAV_DRAWER_TAGS = {
QueueFragment.TAG,
@@ -173,7 +175,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
findViewById(R.id.nav_settings).setOnClickListener(v -> {
drawerLayout.closeDrawer(navDrawer);
- startActivity(new Intent(MainActivity.this, PreferenceController.getPreferenceActivity()));
+ startActivity(new Intent(MainActivity.this, PreferenceActivity.class));
});
FragmentTransaction transaction = fm.beginTransaction();
@@ -201,6 +203,8 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
transaction.commit();
checkFirstLaunch();
+ NotificationUtils.createChannels(this);
+ UserPreferences.restartUpdateAlarm(false);
}
private void saveLastNavFragment(String tag) {
@@ -236,7 +240,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
}
}
- public void showDrawerPreferencesDialog() {
+ private void showDrawerPreferencesDialog() {
final List<String> hiddenDrawerItems = UserPreferences.getHiddenDrawerItems();
String[] navLabels = new String[NAV_DRAWER_TAGS.length];
final boolean[] checked = new boolean[NAV_DRAWER_TAGS.length];
@@ -270,7 +274,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
return (navDrawerData != null) ? navDrawerData.feeds : null;
}
- public void loadFragment(int index, Bundle args) {
+ private void loadFragment(int index, Bundle args) {
Log.d(TAG, "loadFragment(index: " + index + ", args: " + args + ")");
if (index < navAdapter.getSubscriptionOffset()) {
String tag = navAdapter.getTags().get(index);
@@ -399,7 +403,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
}
}
- private AdapterView.OnItemClickListener navListClickListener = new AdapterView.OnItemClickListener() {
+ private final AdapterView.OnItemClickListener navListClickListener = new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
int viewType = parent.getAdapter().getItemViewType(position);
@@ -410,7 +414,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
}
};
- private AdapterView.OnItemLongClickListener newListLongClickListener = new AdapterView.OnItemLongClickListener() {
+ private final AdapterView.OnItemLongClickListener newListLongClickListener = new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if(position < navAdapter.getTags().size()) {
@@ -573,10 +577,29 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
switch(item.getItemId()) {
case R.id.mark_all_seen_item:
- DBWriter.markFeedSeen(feed.getId());
+ ConfirmationDialog markAllSeenConfirmationDialog = new ConfirmationDialog(this,
+ R.string.mark_all_seen_label,
+ R.string.mark_all_seen_confirmation_msg) {
+ @Override
+ public void onConfirmButtonPressed(DialogInterface dialog) {
+ dialog.dismiss();
+ DBWriter.markFeedSeen(feed.getId());
+ }
+ };
+ markAllSeenConfirmationDialog.createNewDialog().show();
return true;
case R.id.mark_all_read_item:
- DBWriter.markFeedRead(feed.getId());
+ ConfirmationDialog markAllReadConfirmationDialog = new ConfirmationDialog(this,
+ R.string.mark_all_read_label,
+ R.string.mark_all_read_confirmation_msg) {
+
+ @Override
+ public void onConfirmButtonPressed(DialogInterface dialog) {
+ dialog.dismiss();
+ DBWriter.markFeedRead(feed.getId());
+ }
+ };
+ markAllReadConfirmationDialog.createNewDialog().show();
return true;
case R.id.rename_item:
new RenameFeedDialog(this, feed).show();
@@ -605,8 +628,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
remover.skipOnCompletion = true;
int playerStatus = PlaybackPreferences.getCurrentPlayerStatus();
if(playerStatus == PlaybackPreferences.PLAYER_STATUS_PLAYING) {
- sendBroadcast(new Intent(
- PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE));
+ IntentUtils.sendLocalBroadcast(MainActivity.this, PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE);
}
}
remover.executeAsync();
@@ -631,7 +653,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
private DBReader.NavDrawerData navDrawerData;
private int selectedNavListIndex = 0;
- private NavListAdapter.ItemAccess itemAccess = new NavListAdapter.ItemAccess() {
+ private final NavListAdapter.ItemAccess itemAccess = new NavListAdapter.ItemAccess() {
@Override
public int getCount() {
if (navDrawerData != null) {
@@ -721,6 +743,15 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
loadData();
}
+ public void onEventMainThread(ServiceEvent event) {
+ Log.d(TAG, "onEvent(" + event + ")");
+ switch(event.action) {
+ case SERVICE_STARTED:
+ externalPlayerFragment.connectToPlaybackService();
+ break;
+ }
+ }
+
public void onEventMainThread(ProgressEvent event) {
Log.d(TAG, "onEvent(" + event + ")");
switch(event.action) {
@@ -744,14 +775,12 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi
View parentLayout = findViewById(R.id.drawer_layout);
Snackbar snackbar = Snackbar.make(parentLayout, event.message, Snackbar.LENGTH_SHORT);
if(event.action != null) {
- snackbar.setAction(getString(R.string.undo), v -> {
- event.action.run();
- });
+ snackbar.setAction(getString(R.string.undo), v -> event.action.run());
}
snackbar.show();
}
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
+ private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override
public void update(EventDistributor eventDistributor, Integer arg) {
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
index 21a0fa66f..be9d60c93 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
@@ -1,9 +1,11 @@
package de.danoeh.antennapod.activity;
+import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PixelFormat;
@@ -11,6 +13,9 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.app.ActivityOptionsCompat;
+import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.Menu;
@@ -33,21 +38,28 @@ import com.joanzapata.iconify.fonts.FontAwesomeIcons;
import java.util.Locale;
import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.event.ServiceEvent;
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.service.playback.PlaybackService;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.Converter;
+import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.Flavors;
+import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.ShareUtils;
import de.danoeh.antennapod.core.util.StorageUtils;
import de.danoeh.antennapod.core.util.Supplier;
+import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil;
+import de.danoeh.antennapod.core.util.playback.ExternalMedia;
import de.danoeh.antennapod.core.util.playback.MediaPlayerError;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
+import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
import de.danoeh.antennapod.dialog.SleepTimerDialog;
import de.danoeh.antennapod.dialog.VariableSpeedDialog;
import rx.Observable;
@@ -65,20 +77,21 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
private static final String TAG = "MediaplayerActivity";
private static final String PREFS = "MediaPlayerActivityPreferences";
private static final String PREF_SHOW_TIME_LEFT = "showTimeLeft";
+ private static final int REQUEST_CODE_STORAGE = 42;
- protected PlaybackController controller;
+ PlaybackController controller;
- protected TextView txtvPosition;
- protected TextView txtvLength;
- protected SeekBar sbPosition;
- protected ImageButton butRev;
- protected TextView txtvRev;
- protected ImageButton butPlay;
- protected ImageButton butFF;
- protected TextView txtvFF;
- protected ImageButton butSkip;
+ private TextView txtvPosition;
+ private TextView txtvLength;
+ SeekBar sbPosition;
+ private ImageButton butRev;
+ private TextView txtvRev;
+ private ImageButton butPlay;
+ private ImageButton butFF;
+ private TextView txtvFF;
+ private ImageButton butSkip;
- protected boolean showTimeLeft = false;
+ private boolean showTimeLeft = false;
private boolean isFavorite = false;
@@ -183,31 +196,31 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
};
}
- protected static TextView getTxtvFFFromActivity(MediaplayerActivity activity) {
+ private static TextView getTxtvFFFromActivity(MediaplayerActivity activity) {
return activity.txtvFF;
}
- protected static TextView getTxtvRevFromActivity(MediaplayerActivity activity) {
+ private static TextView getTxtvRevFromActivity(MediaplayerActivity activity) {
return activity.txtvRev;
}
- protected void onSetSpeedAbilityChanged() {
+ private void onSetSpeedAbilityChanged() {
Log.d(TAG, "onSetSpeedAbilityChanged()");
updatePlaybackSpeedButton();
}
- protected void onPlaybackSpeedChange() {
+ private void onPlaybackSpeedChange() {
updatePlaybackSpeedButtonText();
}
- protected void onServiceQueried() {
+ private void onServiceQueried() {
supportInvalidateOptionsMenu();
}
- protected void chooseTheme() {
+ void chooseTheme() {
setTheme(UserPreferences.getTheme());
}
- protected void setScreenOn(boolean enable) {
+ void setScreenOn(boolean enable) {
}
@Override
@@ -224,9 +237,11 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
@Override
protected void onPause() {
- if(controller != null) {
- controller.reinitServiceIfPaused();
- controller.pause();
+ if (!PictureInPictureUtil.isInPictureInPictureMode(this)) {
+ if (controller != null) {
+ controller.reinitServiceIfPaused();
+ controller.pause();
+ }
}
super.onPause();
}
@@ -248,7 +263,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
*/
protected abstract void onBufferEnd();
- protected void onBufferUpdate(float progress) {
+ private void onBufferUpdate(float progress) {
if (sbPosition != null) {
sbPosition.setSecondaryProgress((int) progress * sbPosition.getMax());
}
@@ -257,7 +272,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
/**
* Current screen orientation.
*/
- protected int orientation;
+ private int orientation;
@Override
protected void onStart() {
@@ -266,6 +281,9 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
controller.release();
}
controller = newPlaybackController();
+ setupGUI();
+ loadMediaInfo();
+ onPositionObserverUpdate();
}
@Override
@@ -316,11 +334,11 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
((FeedMedia) media).getItem().getFlattrStatus().flattrable()
);
- boolean hasWebsiteLink = media != null && media.getWebsiteLink() != null;
+ boolean hasWebsiteLink = ( getWebsiteLinkWithFallback(media) != null );
menu.findItem(R.id.visit_website_item).setVisible(hasWebsiteLink);
boolean isItemAndHasLink = isFeedMedia &&
- ((FeedMedia) media).getItem() != null && ((FeedMedia) media).getItem().getLink() != null;
+ ShareUtils.hasLinkToShare(((FeedMedia) media).getItem());
menu.findItem(R.id.share_link_item).setVisible(isItemAndHasLink);
menu.findItem(R.id.share_link_with_position_item).setVisible(isItemAndHasLink);
@@ -368,7 +386,17 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
| Intent.FLAG_ACTIVITY_NEW_TASK);
- startActivity(intent);
+
+ View cover = findViewById(R.id.imgvCover);
+ if (cover != null && Build.VERSION.SDK_INT >= 16) {
+ ActivityOptionsCompat options = ActivityOptionsCompat.
+ makeSceneTransitionAnimation(MediaplayerActivity.this,
+ cover, "coverTransition");
+ startActivity(intent, options.toBundle());
+ } else {
+ startActivity(intent);
+ }
+ finish();
return true;
} else {
if (media != null) {
@@ -546,7 +574,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
});
break;
case R.id.visit_website_item:
- Uri uri = Uri.parse(media.getWebsiteLink());
+ Uri uri = Uri.parse(getWebsiteLinkWithFallback(media));
startActivity(new Intent(Intent.ACTION_VIEW, uri));
break;
case R.id.support_item:
@@ -589,16 +617,37 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
}
}
+ private static String getWebsiteLinkWithFallback(Playable media) {
+ if (media == null) {
+ return null;
+ } else if (media.getWebsiteLink() != null) {
+ return media.getWebsiteLink();
+ } else if (media instanceof FeedMedia) {
+ return FeedItemUtil.getLinkWithFallback(((FeedMedia)media).getItem());
+ }
+ return null;
+ }
+
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume()");
StorageUtils.checkStorageAvailability(this);
- if(controller != null) {
+ if (controller != null) {
controller.init();
}
}
+ public void onEventMainThread(ServiceEvent event) {
+ Log.d(TAG, "onEvent(" + event + ")");
+ if (event.action == ServiceEvent.Action.SERVICE_STARTED) {
+ if (controller != null) {
+ controller.init();
+ }
+
+ }
+ }
+
/**
* Called by 'handleStatus()' when the PlaybackService is waiting for
* a video surface.
@@ -609,7 +658,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
protected abstract void clearStatusMsg();
- protected void onPositionObserverUpdate() {
+ void onPositionObserverUpdate() {
if (controller == null || txtvPosition == null || txtvLength == null) {
return;
}
@@ -645,12 +694,11 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
* to the PlaybackService to ensure that the activity has the right
* FeedMedia object.
*/
- protected boolean loadMediaInfo() {
+ boolean loadMediaInfo() {
Log.d(TAG, "loadMediaInfo()");
if(controller == null || controller.getMedia() == null) {
return false;
}
- Playable media = controller.getMedia();
SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
showTimeLeft = prefs.getBoolean(PREF_SHOW_TIME_LEFT, false);
onPositionObserverUpdate();
@@ -659,18 +707,18 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
return true;
}
- protected void updatePlaybackSpeedButton() {
+ void updatePlaybackSpeedButton() {
// Only meaningful on AudioplayerActivity, where it is overridden.
}
- protected void updatePlaybackSpeedButtonText() {
+ void updatePlaybackSpeedButtonText() {
// Only meaningful on AudioplayerActivity, where it is overridden.
}
/**
* Abstract directions to skip forward or back (rewind) and encapsulates behavior to get or set preference (including update of UI on the skip buttons).
*/
- static public enum SkipDirection {
+ public enum SkipDirection {
SKIP_FORWARD(
UserPreferences::getFastForwardSecs,
MediaplayerActivity::getTxtvFFFromActivity,
@@ -753,7 +801,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
builder.create().show();
}
- protected void setupGUI() {
+ void setupGUI() {
setContentView(getContentViewResourceId());
sbPosition = (SeekBar) findViewById(R.id.sbPosition);
txtvPosition = (TextView) findViewById(R.id.txtvPosition);
@@ -823,11 +871,12 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
}
if (butSkip != null) {
- butSkip.setOnClickListener(v -> sendBroadcast(new Intent(PlaybackService.ACTION_SKIP_CURRENT_EPISODE)));
+ butSkip.setOnClickListener(v ->
+ IntentUtils.sendLocalBroadcast(MediaplayerActivity.this, PlaybackService.ACTION_SKIP_CURRENT_EPISODE));
}
}
- protected void onRewind() {
+ void onRewind() {
if (controller == null) {
return;
}
@@ -835,14 +884,15 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
controller.seekTo(curr - UserPreferences.getRewindSecs() * 1000);
}
- protected void onPlayPause() {
+ void onPlayPause() {
if(controller == null) {
return;
}
+ controller.init();
controller.playPause();
}
- protected void onFastForward() {
+ void onFastForward() {
if (controller == null) {
return;
}
@@ -852,7 +902,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
protected abstract int getContentViewResourceId();
- void handleError(int errorCode) {
+ private void handleError(int errorCode) {
final AlertDialog.Builder errorDialog = new AlertDialog.Builder(this);
errorDialog.setTitle(R.string.error_label);
errorDialog.setMessage(MediaPlayerError.getErrorString(this, errorCode));
@@ -865,7 +915,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
errorDialog.create().show();
}
- float prog;
+ private float prog;
@Override
public void onProgressChanged (SeekBar seekBar,int progress, boolean fromUser) {
@@ -914,4 +964,39 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements
}
}
+ void playExternalMedia(Intent intent, MediaType type) {
+ if (intent == null || intent.getData() == null) {
+ return;
+ }
+ if (Build.VERSION.SDK_INT >= 23
+ && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
+ != PackageManager.PERMISSION_GRANTED) {
+
+ if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
+ Toast.makeText(this, R.string.needs_storage_permission, Toast.LENGTH_LONG).show();
+ } else {
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
+ REQUEST_CODE_STORAGE);
+ }
+ return;
+ }
+
+ Log.d(TAG, "Received VIEW intent: " + intent.getData().getPath());
+ ExternalMedia media = new ExternalMedia(intent.getData().getPath(), type);
+
+ new PlaybackServiceStarter(this, media)
+ .startWhenPrepared(true)
+ .shouldStream(false)
+ .prepareImmediately(true)
+ .start();
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
+ if (requestCode == REQUEST_CODE_STORAGE) {
+ if (grantResults.length <= 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
+ Toast.makeText(this, R.string.needs_storage_permission, Toast.LENGTH_LONG).show();
+ }
+ }
+ }
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java
index b3cda69d3..49a0e898b 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java
@@ -6,6 +6,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Build;
+import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.Snackbar;
@@ -47,6 +48,7 @@ import de.danoeh.antennapod.core.service.playback.PlayerStatus;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
+import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.dialog.RenameFeedDialog;
@@ -60,7 +62,6 @@ import de.danoeh.antennapod.fragment.PlaybackHistoryFragment;
import de.danoeh.antennapod.fragment.QueueFragment;
import de.danoeh.antennapod.fragment.SubscriptionFragment;
import de.danoeh.antennapod.menuhandler.NavDrawerActivity;
-import de.danoeh.antennapod.preferences.PreferenceController;
import de.greenrobot.event.EventBus;
import rx.Observable;
import rx.Subscription;
@@ -72,16 +73,17 @@ import rx.schedulers.Schedulers;
*/
public abstract class MediaplayerInfoActivity extends MediaplayerActivity implements NavDrawerActivity {
+ private static final String TAG = "MediaplayerInfoActivity";
+
private static final int POS_COVER = 0;
private static final int POS_DESCR = 1;
private static final int POS_CHAPTERS = 2;
private static final int NUM_CONTENT_FRAGMENTS = 3;
- final String TAG = "MediaplayerInfoActivity";
private static final String PREFS = "AudioPlayerActivityPreferences";
private static final String PREF_KEY_SELECTED_FRAGMENT_POSITION = "selectedFragmentPosition";
- public static final String[] NAV_DRAWER_TAGS = {
+ private static final String[] NAV_DRAWER_TAGS = {
QueueFragment.TAG,
EpisodesFragment.TAG,
SubscriptionFragment.TAG,
@@ -91,8 +93,8 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
NavListAdapter.SUBSCRIPTION_LIST_TAG
};
- protected Button butPlaybackSpeed;
- protected ImageButton butCastDisconnect;
+ Button butPlaybackSpeed;
+ ImageButton butCastDisconnect;
private DrawerLayout drawerLayout;
private NavListAdapter navAdapter;
private ListView navList;
@@ -113,6 +115,12 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
}
@Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ supportPostponeEnterTransition();
+ }
+
+ @Override
protected void onStop() {
super.onStop();
Log.d(TAG, "onStop()");
@@ -145,7 +153,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
setTheme(UserPreferences.getNoTitleTheme());
}
- protected void saveCurrentFragment() {
+ void saveCurrentFragment() {
if(pager == null) {
return;
}
@@ -153,7 +161,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
prefs.edit()
.putInt(PREF_KEY_SELECTED_FRAGMENT_POSITION, pager.getCurrentItem())
- .commit();
+ .apply();
}
@Override
@@ -235,7 +243,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.drawer_open, R.string.drawer_close);
drawerToggle.setDrawerIndicatorEnabled(false);
- drawerLayout.setDrawerListener(drawerToggle);
+ drawerLayout.addDrawerListener(drawerToggle);
navAdapter = new NavListAdapter(itemAccess, this);
navList.setAdapter(navAdapter);
@@ -263,7 +271,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
findViewById(R.id.nav_settings).setOnClickListener(v -> {
drawerLayout.closeDrawer(navDrawer);
- startActivity(new Intent(MediaplayerInfoActivity.this, PreferenceController.getPreferenceActivity()));
+ startActivity(new Intent(MediaplayerInfoActivity.this, PreferenceActivity.class));
});
butPlaybackSpeed = (Button) findViewById(R.id.butPlaybackSpeed);
@@ -277,6 +285,8 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
pageIndicator.setViewPager(pager);
loadLastFragment();
pager.onSaveInstanceState();
+
+ navList.post(this::supportStartPostponedEnterTransition);
}
@Override
@@ -297,7 +307,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
return true;
}
- public void notifyMediaPositionChanged() {
+ private void notifyMediaPositionChanged() {
if(pagerAdapter == null) {
return;
}
@@ -387,12 +397,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
new RenameFeedDialog(this, feed).show();
return true;
case R.id.remove_item:
- final FeedRemover remover = new FeedRemover(this, feed) {
- @Override
- protected void onPostExecute(Void result) {
- super.onPostExecute(result);
- }
- };
+ final FeedRemover remover = new FeedRemover(this, feed);
ConfirmationDialog conDialog = new ConfirmationDialog(this,
R.string.remove_feed_label,
getString(R.string.feed_delete_confirmation_msg, feed.getTitle())) {
@@ -404,12 +409,12 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
Playable playable = controller.getMedia();
if (playable != null && playable instanceof FeedMedia) {
FeedMedia media = (FeedMedia) playable;
- if (media.getItem().getFeed().getId() == feed.getId()) {
+ if (media.getItem() != null && media.getItem().getFeed() != null &&
+ media.getItem().getFeed().getId() == feed.getId()) {
Log.d(TAG, "Currently playing episode is about to be deleted, skipping");
remover.skipOnCompletion = true;
if(controller.getStatus() == PlayerStatus.PLAYING) {
- sendBroadcast(new Intent(
- PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE));
+ IntentUtils.sendLocalBroadcast(MediaplayerInfoActivity.this, PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE);
}
}
}
@@ -438,7 +443,7 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
}
}
- public void showDrawerPreferencesDialog() {
+ private void showDrawerPreferencesDialog() {
final List<String> hiddenDrawerItems = UserPreferences.getHiddenDrawerItems();
String[] navLabels = new String[NAV_DRAWER_TAGS.length];
final boolean[] checked = new boolean[NAV_DRAWER_TAGS.length];
@@ -483,14 +488,12 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem
View parentLayout = findViewById(R.id.drawer_layout);
Snackbar snackbar = Snackbar.make(parentLayout, event.message, Snackbar.LENGTH_SHORT);
if (event.action != null) {
- snackbar.setAction(getString(R.string.undo), v -> {
- event.action.run();
- });
+ snackbar.setAction(getString(R.string.undo), v -> event.action.run());
}
snackbar.show();
}
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
+ private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override
public void update(EventDistributor eventDistributor, Integer arg) {
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
index f6bf11e66..28cabfbc7 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
@@ -5,8 +5,9 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
-import android.os.Looper;
+import android.support.annotation.UiThread;
import android.support.v4.app.NavUtils;
+import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
@@ -55,7 +56,6 @@ import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.syndication.handler.FeedHandler;
-import de.danoeh.antennapod.core.syndication.handler.FeedHandlerResult;
import de.danoeh.antennapod.core.syndication.handler.UnsupportedFeedtypeException;
import de.danoeh.antennapod.core.util.DownloadError;
import de.danoeh.antennapod.core.util.FileNameGenerator;
@@ -66,7 +66,6 @@ import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText;
import de.danoeh.antennapod.dialog.AuthenticationDialog;
import de.greenrobot.event.EventBus;
import rx.Observable;
-import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
@@ -84,7 +83,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
public static final String ARG_FEEDURL = "arg.feedurl";
// Optional argument: specify a title for the actionbar.
public static final String ARG_TITLE = "title";
- public static final int RESULT_ERROR = 2;
+ private static final int RESULT_ERROR = 2;
private static final String TAG = "OnlineFeedViewActivity";
private static final int EVENTS = EventDistributor.FEED_LIST_UPDATE;
private volatile List<Feed> feeds;
@@ -101,7 +100,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
private Subscription download;
private Subscription parser;
private Subscription updater;
- private EventDistributor.EventListener listener = new EventDistributor.EventListener() {
+ private final EventDistributor.EventListener listener = new EventDistributor.EventListener() {
@Override
public void update(EventDistributor eventDistributor, Integer arg) {
if ((arg & EventDistributor.FEED_LIST_UPDATE) != 0) {
@@ -112,9 +111,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
feeds -> {
OnlineFeedViewActivity.this.feeds = feeds;
setSubscribeButtonState(feed);
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- }
+ }, error -> Log.e(TAG, Log.getStackTraceString(error))
);
} else if ((arg & EVENTS) != 0) {
setSubscribeButtonState(feed);
@@ -131,10 +128,13 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
setTheme(UserPreferences.getTheme());
super.onCreate(savedInstanceState);
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ }
- if (getIntent() != null && getIntent().hasExtra(ARG_TITLE)) {
- getSupportActionBar().setTitle(getIntent().getStringExtra(ARG_TITLE));
+ if (actionBar != null && getIntent() != null && getIntent().hasExtra(ARG_TITLE)) {
+ actionBar.setTitle(getIntent().getStringExtra(ARG_TITLE));
}
StorageUtils.checkStorageAvailability(this);
@@ -146,7 +146,9 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
|| TextUtils.equals(getIntent().getAction(), Intent.ACTION_VIEW)) {
feedUrl = (TextUtils.equals(getIntent().getAction(), Intent.ACTION_SEND))
? getIntent().getStringExtra(Intent.EXTRA_TEXT) : getIntent().getDataString();
- getSupportActionBar().setTitle(R.string.add_feed_label);
+ if (actionBar != null) {
+ actionBar.setTitle(R.string.add_feed_label);
+ }
} else {
throw new IllegalArgumentException("Activity must be started with feedurl argument!");
}
@@ -265,16 +267,11 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
feed.getDownload_url(), "OnlineFeed", 0, Feed.FEEDFILETYPE_FEED, username, password,
true, null);
- download = Observable.create(new Observable.OnSubscribe<DownloadStatus>() {
- @Override
- public void call(Subscriber<? super DownloadStatus> subscriber) {
- feeds = DBReader.getFeedList();
- downloader = new HttpDownloader(request);
- downloader.call();
- Log.d(TAG, "Download was completed");
- subscriber.onNext(downloader.getResult());
- subscriber.onCompleted();
- }
+ download = Observable.fromCallable(() -> {
+ feeds = DBReader.getFeedList();
+ downloader = new HttpDownloader(request);
+ downloader.call();
+ return downloader.getResult();
})
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
@@ -286,6 +283,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
if (status == null) {
Log.wtf(TAG, "DownloadStatus returned by Downloader was null");
finish();
+ return;
}
if (status.isCancelled()) {
return;
@@ -300,7 +298,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
}
} else {
String errorMsg = status.getReason().getErrorString(OnlineFeedViewActivity.this);
- if (errorMsg != null && status.getReasonDetailed() != null) {
+ if (status.getReasonDetailed() != null) {
errorMsg += " (" + status.getReasonDetailed() + ")";
}
showErrorDialog(errorMsg);
@@ -313,39 +311,38 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
}
Log.d(TAG, "Parsing feed");
- parser = Observable.create(new Observable.OnSubscribe<FeedHandlerResult>() {
- @Override
- public void call(Subscriber<? super FeedHandlerResult> subscriber) {
- FeedHandler handler = new FeedHandler();
- try {
- FeedHandlerResult result = handler.parseFeed(feed);
- subscriber.onNext(result);
- } catch (UnsupportedFeedtypeException e) {
- Log.d(TAG, "Unsupported feed type detected");
- if (TextUtils.equals("html", e.getRootElement().toLowerCase())) {
- showFeedDiscoveryDialog(new File(feed.getFile_url()), feed.getDownload_url());
- } else {
- subscriber.onError(e);
- }
- } catch (Exception e) {
- Log.e(TAG, Log.getStackTraceString(e));
- subscriber.onError(e);
- } finally {
- boolean rc = new File(feed.getFile_url()).delete();
- Log.d(TAG, "Deleted feed source file. Result: " + rc);
- subscriber.onCompleted();
+ parser = Observable.fromCallable(() -> {
+ FeedHandler handler = new FeedHandler();
+ try {
+ return handler.parseFeed(feed);
+ } catch (UnsupportedFeedtypeException e) {
+ Log.d(TAG, "Unsupported feed type detected");
+ if ("html".equalsIgnoreCase(e.getRootElement())) {
+ showFeedDiscoveryDialog(new File(feed.getFile_url()), feed.getDownload_url());
+ return null;
+ } else {
+ throw e;
}
+ } catch (Exception e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ throw e;
+ } finally {
+ boolean rc = new File(feed.getFile_url()).delete();
+ Log.d(TAG, "Deleted feed source file. Result: " + rc);
}
})
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
- beforeShowFeedInformation(result.feed);
- showFeedInformation(result.feed, result.alternateFeedUrls);
+ if(result != null) {
+ beforeShowFeedInformation(result.feed);
+ showFeedInformation(result.feed, result.alternateFeedUrls);
+ }
}, error -> {
String errorMsg = DownloadError.ERROR_PARSER_EXCEPTION.getErrorString(
OnlineFeedViewActivity.this) + " (" + error.getMessage() + ")";
showErrorDialog(errorMsg);
+ Log.d(TAG, "Feed parser exception: " + Log.getStackTraceString(error));
});
}
@@ -383,8 +380,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
this.selectedDownloadUrl = feed.getDownload_url();
EventDistributor.getInstance().register(listener);
ListView listView = (ListView) findViewById(R.id.listview);
- LayoutInflater inflater = (LayoutInflater)
- getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ LayoutInflater inflater = LayoutInflater.from(this);
View header = inflater.inflate(R.layout.onlinefeedview_header, listView, false);
listView.addHeaderView(header);
@@ -398,9 +394,9 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
subscribeButton = (Button) header.findViewById(R.id.butSubscribe);
- if (feed.getImage() != null && StringUtils.isNotBlank(feed.getImage().getDownload_url())) {
+ if (StringUtils.isNotBlank(feed.getImageUrl())) {
Glide.with(this)
- .load(feed.getImage().getDownload_url())
+ .load(feed.getImageUrl())
.placeholder(R.color.light_gray)
.error(R.color.light_gray)
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
@@ -414,7 +410,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
description.setText(feed.getDescription());
subscribeButton.setOnClickListener(v -> {
- if(feed != null && feedInFeedlist(feed)) {
+ if(feedInFeedlist(feed)) {
Intent intent = new Intent(OnlineFeedViewActivity.this, MainActivity.class);
// feed.getId() is always 0, we have to retrieve the id from the feed list from
// the database
@@ -508,8 +504,8 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
return 0;
}
+ @UiThread
private void showErrorDialog(String errorMsg) {
- assert(Looper.myLooper() == Looper.getMainLooper()); // run on UI thread
if (!isFinishing() && !isPaused) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.error_label);
@@ -586,7 +582,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity {
private class FeedViewAuthenticationDialog extends AuthenticationDialog {
- private String feedUrl;
+ private final String feedUrl;
FeedViewAuthenticationDialog(Context context, int titleRes, String feedUrl) {
super(context, titleRes, true, false, null, null);
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java
index 07b0b3cdb..c04ae051e 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java
@@ -68,7 +68,7 @@ public class OpmlImportBaseActivity extends AppCompatActivity {
}
}
- protected void importUri(@Nullable Uri uri) {
+ void importUri(@Nullable Uri uri) {
if(uri == null) {
new MaterialDialog.Builder(this)
.content(R.string.opml_import_error_no_file)
@@ -114,7 +114,7 @@ public class OpmlImportBaseActivity extends AppCompatActivity {
}
/** Starts the import process. */
- protected void startImport() {
+ private void startImport() {
try {
Reader mReader = new InputStreamReader(getContentResolver().openInputStream(uri), LangUtils.UTF_8);
importWorker = new OpmlImportWorker(this, mReader) {
@@ -144,7 +144,7 @@ public class OpmlImportBaseActivity extends AppCompatActivity {
}
}
- protected boolean finishWhenCanceled() {
+ boolean finishWhenCanceled() {
return false;
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java
index dd932814f..3f005fe36 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java
@@ -1,14 +1,12 @@
package de.danoeh.antennapod.activity;
-import android.annotation.TargetApi;
-import android.app.Activity;
import android.content.Intent;
-import android.os.Build;
import android.os.Bundle;
-import android.preference.Preference;
-import android.preference.PreferenceFragment;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceFragmentCompat;
+import android.support.v7.preference.PreferenceScreen;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewGroup;
@@ -16,6 +14,9 @@ import android.widget.FrameLayout;
import java.lang.ref.WeakReference;
+import com.bytehamster.lib.preferencesearch.SearchPreference;
+import com.bytehamster.lib.preferencesearch.SearchPreferenceResult;
+import com.bytehamster.lib.preferencesearch.SearchPreferenceResultListener;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.preferences.PreferenceController;
@@ -24,25 +25,40 @@ import de.danoeh.antennapod.preferences.PreferenceController;
* PreferenceActivity for API 11+. In order to change the behavior of the preference UI, see
* PreferenceController.
*/
-public class PreferenceActivity extends AppCompatActivity {
+public class PreferenceActivity extends AppCompatActivity implements SearchPreferenceResultListener {
+ public static final String PARAM_RESOURCE = "resource";
private static WeakReference<PreferenceActivity> instance;
private PreferenceController preferenceController;
- private MainFragment prefFragment;
private final PreferenceController.PreferenceUI preferenceUI = new PreferenceController.PreferenceUI() {
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ private PreferenceFragmentCompat fragment;
+
+ @Override
+ public void setFragment(PreferenceFragmentCompat fragment) {
+ this.fragment = fragment;
+ }
+
+ @Override
+ public PreferenceFragmentCompat getFragment() {
+ return fragment;
+ }
+
@Override
public Preference findPreference(CharSequence key) {
- return prefFragment.findPreference(key);
+ return fragment.findPreference(key);
}
@Override
- public Activity getActivity() {
+ public PreferenceScreen getPreferenceScreen() {
+ return fragment.getPreferenceScreen();
+ }
+
+ @Override
+ public AppCompatActivity getActivity() {
return PreferenceActivity.this;
}
};
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
protected void onCreate(Bundle savedInstanceState) {
// This must be the FIRST thing we do, otherwise other code may not have the
@@ -68,8 +84,21 @@ public class PreferenceActivity extends AppCompatActivity {
// since the MainFragment depends on the preferenceController already being created
preferenceController = new PreferenceController(preferenceUI);
- prefFragment = new MainFragment();
- getFragmentManager().beginTransaction().replace(R.id.content, prefFragment).commit();
+ showPreferenceScreen(R.xml.preferences, false);
+ }
+
+ private void showPreferenceScreen(int screen, boolean addHistory) {
+ PreferenceFragmentCompat prefFragment = new MainFragment();
+ preferenceUI.setFragment(prefFragment);
+ Bundle args = new Bundle();
+ args.putInt(PARAM_RESOURCE, screen);
+ prefFragment.setArguments(args);
+ if (addHistory) {
+ getSupportFragmentManager().beginTransaction().replace(R.id.content, prefFragment)
+ .addToBackStack(getString(PreferenceController.getTitleOfPage(screen))).commit();
+ } else {
+ getSupportFragmentManager().beginTransaction().replace(R.id.content, prefFragment).commit();
+ }
}
@Override
@@ -88,24 +117,40 @@ public class PreferenceActivity extends AppCompatActivity {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
- finish();
+ if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
+ finish();
+ } else {
+ getSupportFragmentManager().popBackStack();
+ }
return true;
default:
return false;
}
}
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
- public static class MainFragment extends PreferenceFragment {
+ @Override
+ public void onSearchResultClicked(SearchPreferenceResult result) {
+ showPreferenceScreen(result.getResourceFile(), true);
+ result.highlight(preferenceUI.getFragment());
+ }
+
+ public static class MainFragment extends PreferenceFragmentCompat {
+ private int screen;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
- addPreferencesFromResource(R.xml.preferences);
+ }
+
+ @Override
+ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+ screen = getArguments().getInt(PARAM_RESOURCE);
+ addPreferencesFromResource(screen);
PreferenceActivity activity = instance.get();
- if(activity != null && activity.preferenceController != null) {
- activity.preferenceController.onCreate();
+ if (activity != null && activity.preferenceController != null) {
+ activity.preferenceUI.setFragment(this);
+ activity.preferenceController.onCreate(screen);
}
}
@@ -114,15 +159,17 @@ public class PreferenceActivity extends AppCompatActivity {
super.onResume();
PreferenceActivity activity = instance.get();
if(activity != null && activity.preferenceController != null) {
- activity.preferenceController.onResume();
+ activity.setTitle(PreferenceController.getTitleOfPage(screen));
+ activity.preferenceUI.setFragment(this);
+ activity.preferenceController.onResume(screen);
}
}
@Override
public void onPause() {
PreferenceActivity activity = instance.get();
- if(activity != null && activity.preferenceController != null) {
- activity.preferenceController.onPause();
+ if (screen == R.xml.preferences_gpodder) {
+ activity.preferenceController.unregisterGpodnet();
}
super.onPause();
}
@@ -130,8 +177,8 @@ public class PreferenceActivity extends AppCompatActivity {
@Override
public void onStop() {
PreferenceActivity activity = instance.get();
- if(activity != null && activity.preferenceController != null) {
- activity.preferenceController.onStop();
+ if (screen == R.xml.preferences_storage) {
+ activity.preferenceController.unsubscribeExportSubscription();
}
super.onStop();
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java
deleted file mode 100644
index 390bec15c..000000000
--- a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package de.danoeh.antennapod.activity;
-
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.content.Intent;
-import android.content.res.Resources.Theme;
-import android.os.Bundle;
-import android.preference.Preference;
-import android.preference.PreferenceScreen;
-
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.preferences.PreferenceController;
-
-/**
- * PreferenceActivity for API 10. In order to change the behavior of the preference UI, see
- * PreferenceController.
- */
-public class PreferenceActivityGingerbread extends android.preference.PreferenceActivity {
- private static final String TAG = "PreferenceActivity";
- private final PreferenceController.PreferenceUI preferenceUI = new PreferenceController.PreferenceUI() {
-
- @SuppressWarnings("deprecation")
- @Override
- public Preference findPreference(CharSequence key) {
- return PreferenceActivityGingerbread.this.findPreference(key);
- }
-
- @Override
- public Activity getActivity() {
- return PreferenceActivityGingerbread.this;
- }
- };
- private PreferenceController preferenceController;
-
- @SuppressLint("NewApi")
- @SuppressWarnings("deprecation")
- @Override
- public void onCreate(Bundle savedInstanceState) {
- setTheme(UserPreferences.getTheme());
- super.onCreate(savedInstanceState);
-
- addPreferencesFromResource(R.xml.preferences);
- preferenceController = new PreferenceController(preferenceUI);
- preferenceController.onCreate();
- }
-
-
- @Override
- protected void onResume() {
- super.onResume();
- preferenceController.onResume();
- }
-
- @Override
- protected void onPause() {
- preferenceController.onPause();
- super.onPause();
- }
-
- @Override
- protected void onStop() {
- preferenceController.onStop();
- super.onStop();
- }
-
- @Override
- protected void onApplyThemeResource(Theme theme, int resid, boolean first) {
- theme.applyStyle(UserPreferences.getTheme(), true);
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- preferenceController.onActivityResult(requestCode, resultCode, data);
- }
-
- @SuppressWarnings("deprecation")
- @Override
- public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
- Preference preference) {
- super.onPreferenceTreeClick(preferenceScreen, preference);
- if (preference != null)
- if (preference instanceof PreferenceScreen)
- if (((PreferenceScreen) preference).getDialog() != null)
- ((PreferenceScreen) preference)
- .getDialog()
- .getWindow()
- .getDecorView()
- .setBackgroundDrawable(
- this.getWindow().getDecorView()
- .getBackground().getConstantState()
- .newDrawable()
- );
- return false;
- }
-}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java
index b92ac8577..73b495a42 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java
@@ -1,23 +1,50 @@
package de.danoeh.antennapod.activity;
import android.content.Intent;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
+import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.app.AppCompatActivity;
+import android.widget.ProgressBar;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.storage.PodDBAdapter;
+import rx.Completable;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.schedulers.Schedulers;
/**
- * Creator: vbarad
- * Date: 2016-12-03
- * Project: AntennaPod
+ * Shows the AntennaPod logo while waiting for the main activity to start
*/
-
public class SplashActivity extends AppCompatActivity {
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.splash);
+
+ ProgressBar progressBar = findViewById(R.id.progressBar);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ Drawable wrapDrawable = DrawableCompat.wrap(progressBar.getIndeterminateDrawable());
+ DrawableCompat.setTint(wrapDrawable, 0xffffffff);
+ progressBar.setIndeterminateDrawable(DrawableCompat.unwrap(wrapDrawable));
+ } else {
+ progressBar.getIndeterminateDrawable().setColorFilter(0xffffffff, PorterDuff.Mode.SRC_IN);
+ }
- Intent intent = new Intent(this, MainActivity.class);
- startActivity(intent);
- finish();
- }
+ Completable.create(subscriber -> {
+ // Trigger schema updates
+ PodDBAdapter.getInstance().open();
+ PodDBAdapter.getInstance().close();
+ subscriber.onCompleted();
+ })
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(() -> {
+ Intent intent = new Intent(SplashActivity.this, MainActivity.class);
+ startActivity(intent);
+ finish();
+ });
+ }
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java
index d104a9e93..a2a49f54e 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java
@@ -164,7 +164,7 @@ public class StorageErrorActivity extends AppCompatActivity {
startActivity(new Intent(this, MainActivity.class));
}
- private BroadcastReceiver mediaUpdate = new BroadcastReceiver() {
+ private final BroadcastReceiver mediaUpdate = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java
index 8531a7356..ea408c650 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java
@@ -7,29 +7,34 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.view.WindowCompat;
+import android.support.v7.app.ActionBar;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
+import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.SeekBar;
-
-import java.lang.ref.WeakReference;
-import java.util.concurrent.atomic.AtomicBoolean;
-
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.MediaType;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.service.playback.PlayerStatus;
-import de.danoeh.antennapod.core.util.playback.ExternalMedia;
+import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.view.AspectRatioVideoView;
+import java.lang.ref.WeakReference;
+import java.util.concurrent.atomic.AtomicBoolean;
+
/**
* Activity for playing video files.
*/
@@ -45,12 +50,13 @@ public class VideoplayerActivity extends MediaplayerActivity {
private VideoControlsHider videoControlsHider = new VideoControlsHider(this);
- private AtomicBoolean isSetup = new AtomicBoolean(false);
+ private final AtomicBoolean isSetup = new AtomicBoolean(false);
private LinearLayout controls;
private LinearLayout videoOverlay;
private AspectRatioVideoView videoview;
private ProgressBar progressIndicator;
+ private FrameLayout videoframe;
@Override
protected void chooseTheme() {
@@ -70,20 +76,8 @@ public class VideoplayerActivity extends MediaplayerActivity {
@Override
protected void onResume() {
super.onResume();
- if (getIntent().getAction() != null
- && getIntent().getAction().equals(Intent.ACTION_VIEW)) {
- Intent intent = getIntent();
- Log.d(TAG, "Received VIEW intent: " + intent.getData().getPath());
- ExternalMedia media = new ExternalMedia(intent.getData().getPath(),
- MediaType.VIDEO);
- Intent launchIntent = new Intent(this, PlaybackService.class);
- launchIntent.putExtra(PlaybackService.EXTRA_PLAYABLE, media);
- launchIntent.putExtra(PlaybackService.EXTRA_START_WHEN_PREPARED,
- true);
- launchIntent.putExtra(PlaybackService.EXTRA_SHOULD_STREAM, false);
- launchIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY,
- true);
- startService(launchIntent);
+ if (TextUtils.equals(getIntent().getAction(), Intent.ACTION_VIEW)) {
+ playExternalMedia(getIntent(), MediaType.VIDEO);
} else if (PlaybackService.isCasting()) {
Intent intent = PlaybackService.getPlayerActivityIntent(this);
if (!intent.getComponent().getClassName().equals(VideoplayerActivity.class.getName())) {
@@ -95,10 +89,27 @@ public class VideoplayerActivity extends MediaplayerActivity {
}
@Override
+ protected void onStop() {
+ super.onStop();
+ if (!PictureInPictureUtil.isInPictureInPictureMode(this)) {
+ videoControlsHider.stop();
+ }
+ }
+
+ @Override
+ public void onUserLeaveHint () {
+ if (!PictureInPictureUtil.isInPictureInPictureMode(this) && UserPreferences.getVideoBackgroundBehavior()
+ == UserPreferences.VideoBackgroundBehavior.PICTURE_IN_PICTURE) {
+ compatEnterPictureInPicture();
+ }
+ }
+
+ @Override
protected void onPause() {
- videoControlsHider.stop();
- if (controller != null && controller.getStatus() == PlayerStatus.PLAYING) {
- controller.pause();
+ if (!PictureInPictureUtil.isInPictureInPictureMode(this)) {
+ if (controller != null && controller.getStatus() == PlayerStatus.PLAYING) {
+ controller.pause();
+ }
}
super.onPause();
}
@@ -126,7 +137,7 @@ public class VideoplayerActivity extends MediaplayerActivity {
@Override
protected void setupGUI() {
- if(isSetup.getAndSet(true)) {
+ if (isSetup.getAndSet(true)) {
return;
}
super.setupGUI();
@@ -134,34 +145,30 @@ public class VideoplayerActivity extends MediaplayerActivity {
controls = (LinearLayout) findViewById(R.id.controls);
videoOverlay = (LinearLayout) findViewById(R.id.overlay);
videoview = (AspectRatioVideoView) findViewById(R.id.videoview);
+ videoframe = (FrameLayout) findViewById(R.id.videoframe);
progressIndicator = (ProgressBar) findViewById(R.id.progressIndicator);
videoview.getHolder().addCallback(surfaceHolderCallback);
- videoview.setOnTouchListener(onVideoviewTouched);
+ videoframe.setOnTouchListener(onVideoviewTouched);
+ videoOverlay.setOnTouchListener((view, motionEvent) -> true); // To suppress touches directly below the slider
if (Build.VERSION.SDK_INT >= 16) {
videoview.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
}
- if (Build.VERSION.SDK_INT >= 14) {
- videoOverlay.setFitsSystemWindows(true);
- }
+ videoOverlay.setFitsSystemWindows(true);
setupVideoControlsToggler();
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
+
+ videoframe.getViewTreeObserver().addOnGlobalLayoutListener(() ->
+ videoview.setAvailableSize(videoframe.getWidth(), videoframe.getHeight()));
}
@Override
protected void onAwaitingVideoSurface() {
+ setupVideoAspectRatio();
if (videoSurfaceCreated && controller != null) {
Log.d(TAG, "Videosurface already created, setting videosurface now");
-
- Pair<Integer, Integer> videoSize = controller.getVideoSize();
- if (videoSize != null && videoSize.first > 0 && videoSize.second > 0) {
- Log.d(TAG, "Width,height of video: " + videoSize.first + ", " + videoSize.second);
- videoview.setVideoSize(videoSize.first, videoSize.second);
- } else {
- Log.e(TAG, "Could not determine video size");
- }
controller.setVideoSurface(videoview.getHolder());
}
}
@@ -180,8 +187,11 @@ public class VideoplayerActivity extends MediaplayerActivity {
progressIndicator.setVisibility(View.INVISIBLE);
}
- View.OnTouchListener onVideoviewTouched = (v, event) -> {
+ private final View.OnTouchListener onVideoviewTouched = (v, event) -> {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ if (PictureInPictureUtil.isInPictureInPictureMode(this)) {
+ return true;
+ }
videoControlsHider.stop();
toggleVideoControlsVisibility();
if (videoControlsShowing) {
@@ -194,11 +204,23 @@ public class VideoplayerActivity extends MediaplayerActivity {
};
@SuppressLint("NewApi")
- void setupVideoControlsToggler() {
+ private void setupVideoControlsToggler() {
videoControlsHider.stop();
videoControlsHider.start();
}
+ private void setupVideoAspectRatio() {
+ if (videoSurfaceCreated && controller != null) {
+ Pair<Integer, Integer> videoSize = controller.getVideoSize();
+ if (videoSize != null && videoSize.first > 0 && videoSize.second > 0) {
+ Log.d(TAG, "Width,height of video: " + videoSize.first + ", " + videoSize.second);
+ videoview.setVideoSize(videoSize.first, videoSize.second);
+ } else {
+ Log.e(TAG, "Could not determine video size");
+ }
+ }
+ }
+
private void toggleVideoControlsVisibility() {
if (videoControlsShowing) {
getSupportActionBar().hide();
@@ -247,14 +269,16 @@ public class VideoplayerActivity extends MediaplayerActivity {
Log.e(TAG, "Couldn't attach surface to mediaplayer - reference to service was null");
}
}
-
+ setupVideoAspectRatio();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "Videosurface was destroyed");
videoSurfaceCreated = false;
- if (controller != null && !destroyingDueToReload) {
+ if (controller != null && !destroyingDueToReload
+ && UserPreferences.getVideoBackgroundBehavior()
+ != UserPreferences.VideoBackgroundBehavior.CONTINUE_PLAYING) {
controller.notifyVideoSurfaceAbandoned();
}
}
@@ -263,6 +287,13 @@ public class VideoplayerActivity extends MediaplayerActivity {
@Override
protected void onReloadNotification(int notificationCode) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && PictureInPictureUtil.isInPictureInPictureMode(this)) {
+ if (notificationCode == PlaybackService.EXTRA_CODE_AUDIO
+ || notificationCode == PlaybackService.EXTRA_CODE_CAST) {
+ finish();
+ }
+ return;
+ }
if (notificationCode == PlaybackService.EXTRA_CODE_AUDIO) {
Log.d(TAG, "ReloadNotification received, switching to Audioplayer now");
destroyingDueToReload = true;
@@ -307,28 +338,31 @@ public class VideoplayerActivity extends MediaplayerActivity {
videoOverlay.startAnimation(animation);
controls.startAnimation(animation);
}
- if (Build.VERSION.SDK_INT >= 14) {
- videoview.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
- }
+ videoview.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
}
@SuppressLint("NewApi")
- private void hideVideoControls() {
- final Animation animation = AnimationUtils.loadAnimation(this, R.anim.fade_out);
- if (animation != null) {
- videoOverlay.startAnimation(animation);
- controls.startAnimation(animation);
- }
- if (Build.VERSION.SDK_INT >= 14) {
- int videoviewFlag = (Build.VERSION.SDK_INT >= 16) ? View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION : 0;
- getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN
- | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | videoviewFlag);
- videoOverlay.setFitsSystemWindows(true);
+ private void hideVideoControls(boolean showAnimation) {
+ if (showAnimation) {
+ final Animation animation = AnimationUtils.loadAnimation(this, R.anim.fade_out);
+ if (animation != null) {
+ videoOverlay.startAnimation(animation);
+ controls.startAnimation(animation);
+ }
}
+ int videoviewFlag = (Build.VERSION.SDK_INT >= 16) ? View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION : 0;
+ getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | videoviewFlag);
+ videoOverlay.setFitsSystemWindows(true);
+
videoOverlay.setVisibility(View.GONE);
controls.setVisibility(View.GONE);
}
+ private void hideVideoControls() {
+ hideVideoControls(true);
+ }
+
@Override
protected int getContentViewResourceId() {
return R.layout.videoplayer_activity;
@@ -344,24 +378,53 @@ public class VideoplayerActivity extends MediaplayerActivity {
}
}
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ if (PictureInPictureUtil.supportsPictureInPicture(this)) {
+ menu.findItem(R.id.player_go_to_picture_in_picture).setVisible(true);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == R.id.player_go_to_picture_in_picture) {
+ compatEnterPictureInPicture();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void compatEnterPictureInPicture() {
+ if (PictureInPictureUtil.supportsPictureInPicture(this) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ getSupportActionBar().hide();
+ hideVideoControls(false);
+ enterPictureInPictureMode();
+ }
+ }
+
private static class VideoControlsHider extends Handler {
private static final int DELAY = 2500;
private WeakReference<VideoplayerActivity> activity;
- public VideoControlsHider(VideoplayerActivity activity) {
+ VideoControlsHider(VideoplayerActivity activity) {
this.activity = new WeakReference<>(activity);
}
private final Runnable hideVideoControls = () -> {
- VideoplayerActivity vpa = activity.get();
- if(vpa == null) {
+ VideoplayerActivity vpa = activity != null ? activity.get() : null;
+ if (vpa == null) {
return;
}
if (vpa.videoControlsShowing) {
Log.d(TAG, "Hiding video controls");
- vpa.getSupportActionBar().hide();
+ ActionBar actionBar = vpa.getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.hide();
+ }
vpa.hideVideoControls();
vpa.videoControlsShowing = false;
}
@@ -371,7 +434,7 @@ public class VideoplayerActivity extends MediaplayerActivity {
this.postDelayed(hideVideoControls, DELAY);
}
- public void stop() {
+ void stop() {
this.removeCallbacks(hideVideoControls);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java
index 8ede947c5..8f447ac90 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java
@@ -61,7 +61,7 @@ public class GpodnetAuthenticationActivity extends AppCompatActivity {
private volatile String password;
private volatile GpodnetDevice selectedDevice;
- View[] views;
+ private View[] views;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -171,11 +171,7 @@ public class GpodnetAuthenticationActivity extends AppCompatActivity {
return null;
}
};
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- authTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, service);
- } else {
- authTask.execute();
- }
+ authTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, service);
}
});
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonCallback.java b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonCallback.java
index c18564351..e6b42efcb 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonCallback.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonCallback.java
@@ -3,7 +3,7 @@ package de.danoeh.antennapod.adapter;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.util.LongList;
-public interface ActionButtonCallback {
+interface ActionButtonCallback {
/** Is called when the action button of a list item has been pressed. */
void onActionButtonPressed(FeedItem item, LongList queueIds);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java
index f0210f983..a915692d1 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java
@@ -16,7 +16,7 @@ import de.danoeh.antennapod.core.storage.DownloadRequester;
* Utility methods for the action button that is displayed on the right hand side
* of a listitem.
*/
-public class ActionButtonUtils {
+class ActionButtonUtils {
private final int[] labels;
private final TypedArray drawables;
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
index 3e8bbc488..9739b999b 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
@@ -21,7 +21,6 @@ import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.joanzapata.iconify.Iconify;
-import com.nineoldandroids.view.ViewHelper;
import java.lang.ref.WeakReference;
@@ -30,12 +29,12 @@ import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.DateUtils;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.NetworkUtils;
+import de.danoeh.antennapod.core.util.ThemeUtils;
import de.danoeh.antennapod.fragment.ItemFragment;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
@@ -68,11 +67,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
this.actionButtonCallback = actionButtonCallback;
this.showOnlyNewEpisodes = showOnlyNewEpisodes;
- if(UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
- playingBackGroundColor = ContextCompat.getColor(mainActivity, R.color.highlight_dark);
- } else {
- playingBackGroundColor = ContextCompat.getColor(mainActivity, R.color.highlight_light);
- }
+ playingBackGroundColor = ThemeUtils.getColorFromAttr(mainActivity, R.attr.currently_playing_background);
normalBackGroundColor = ContextCompat.getColor(mainActivity, android.R.color.transparent);
}
@@ -101,7 +96,6 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
holder.txtvDuration = (TextView) view.findViewById(R.id.txtvDuration);
holder.item = null;
holder.mainActivityRef = mainActivityRef;
- holder.position = -1;
// so we can grab this later
view.setTag(holder);
@@ -113,11 +107,10 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
final FeedItem item = itemAccess.getItem(position);
if (item == null) return;
holder.itemView.setOnLongClickListener(v -> {
- this.position = position;
+ this.position = holder.getAdapterPosition();
return false;
});
holder.item = item;
- holder.position = position;
holder.placeholder.setVisibility(View.VISIBLE);
holder.placeholder.setText(item.getFeed().getTitle());
holder.title.setText(item.getTitle());
@@ -129,9 +122,9 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
holder.statusUnread.setVisibility(View.VISIBLE);
}
if(item.isPlayed()) {
- ViewHelper.setAlpha(holder.content, 0.5f);
+ holder.content.setAlpha(0.5f);
} else {
- ViewHelper.setAlpha(holder.content, 1.0f);
+ holder.content.setAlpha(1.0f);
}
FeedMedia media = item.getMedia();
@@ -174,7 +167,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
holder.progress.setVisibility(View.VISIBLE);
}
} else {
- holder.progress.setVisibility(View.GONE);
+ holder.progress.setVisibility(View.INVISIBLE);
}
if(media.isCurrentlyPlaying()) {
@@ -183,7 +176,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
holder.container.setBackgroundColor(normalBackGroundColor);
}
} else {
- holder.progress.setVisibility(View.GONE);
+ holder.progress.setVisibility(View.INVISIBLE);
holder.txtvDuration.setVisibility(View.GONE);
}
@@ -228,7 +221,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
return pos;
}
- private View.OnClickListener secondaryActionListener = new View.OnClickListener() {
+ private final View.OnClickListener secondaryActionListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
FeedItem item = (FeedItem) v.getTag();
@@ -253,7 +246,6 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
ImageButton butSecondary;
FeedItem item;
WeakReference<MainActivity> mainActivityRef;
- int position;
public Holder(View itemView) {
super(itemView);
@@ -266,18 +258,18 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
MainActivity mainActivity = mainActivityRef.get();
if (mainActivity != null) {
long[] ids = itemAccess.getItemsIds().toArray();
- mainActivity.loadChildFragment(ItemFragment.newInstance(ids, position));
+ mainActivity.loadChildFragment(ItemFragment.newInstance(ids, getAdapterPosition()));
}
}
@Override
public void onItemSelected() {
- ViewHelper.setAlpha(itemView, 0.5f);
+ itemView.setAlpha(0.5f);
}
@Override
public void onItemClear() {
- ViewHelper.setAlpha(itemView, 1.0f);
+ itemView.setAlpha(1.0f);
}
public FeedItem getFeedItem() { return item; }
@@ -303,6 +295,8 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
}
};
FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, true, null);
+
+ contextMenuInterface.setItemVisibility(R.id.mark_as_seen_item, item.isNew());
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java
index 75514abb1..cbd089d4c 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java
@@ -9,7 +9,6 @@ import android.text.Spannable;
import android.text.Spanned;
import android.text.style.ClickableSpan;
import android.text.util.Linkify;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@@ -20,9 +19,9 @@ import android.widget.TextView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.Chapter;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.util.ChapterUtils;
import de.danoeh.antennapod.core.util.Converter;
+import de.danoeh.antennapod.core.util.ThemeUtils;
import de.danoeh.antennapod.core.util.playback.Playable;
public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
@@ -144,9 +143,7 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
Chapter current = ChapterUtils.getCurrentChapter(media);
if (current == sc) {
- boolean darkTheme = UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark;
- int highlight = darkTheme ? R.color.highlight_dark : R.color.highlight_light;
- int playingBackGroundColor = ContextCompat.getColor(getContext(), highlight);
+ int playingBackGroundColor = ThemeUtils.getColorFromAttr(getContext(), R.attr.currently_playing_background);
holder.view.setBackgroundColor(playingBackGroundColor);
} else {
holder.view.setBackgroundColor(ContextCompat.getColor(getContext(), android.R.color.transparent));
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java b/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java
index 538af8c79..ba6e7b25d 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java
@@ -1,7 +1,6 @@
package de.danoeh.antennapod.adapter;
import android.graphics.drawable.Drawable;
-import android.net.Uri;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java b/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java
index 4a53be9dc..08b2908ac 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java
@@ -6,6 +6,8 @@ import android.widget.Toast;
import com.afollestad.materialdialogs.MaterialDialog;
+import de.danoeh.antennapod.core.util.IntentUtils;
+import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
import org.apache.commons.lang3.Validate;
import de.danoeh.antennapod.R;
@@ -80,13 +82,19 @@ public class DefaultActionButtonCallback implements ActionButtonCallback {
Toast.makeText(context, R.string.download_canceled_msg, Toast.LENGTH_LONG).show();
}
} else { // media is downloaded
- if (item.hasMedia() && item.getMedia().isCurrentlyPlaying()) {
- context.sendBroadcast(new Intent(PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE));
- }
- else if (item.hasMedia() && item.getMedia().isCurrentlyPaused()) {
- context.sendBroadcast(new Intent(PlaybackService.ACTION_RESUME_PLAY_CURRENT_EPISODE));
- }
- else {
+ if (media.isCurrentlyPlaying()) {
+ new PlaybackServiceStarter(context, media)
+ .startWhenPrepared(true)
+ .shouldStream(false)
+ .start();
+ IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE);
+ } else if (media.isCurrentlyPaused()) {
+ new PlaybackServiceStarter(context, media)
+ .startWhenPrepared(true)
+ .shouldStream(false)
+ .start();
+ IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_RESUME_PLAY_CURRENT_EPISODE);
+ } else {
DBTasks.playMedia(context, media, false, true, false);
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java
index e271b5eed..163366c3c 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java
@@ -19,7 +19,6 @@ import com.joanzapata.iconify.widget.IconTextView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
import de.danoeh.antennapod.core.feed.Feed;
-import de.danoeh.antennapod.core.feed.FeedImage;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.storage.DBReader;
@@ -29,11 +28,11 @@ import de.danoeh.antennapod.core.storage.DownloadRequestException;
/** Displays a list of DownloadStatus entries. */
public class DownloadLogAdapter extends BaseAdapter {
- private final String TAG = "DownloadLogAdapter";
+ private static final String TAG = "DownloadLogAdapter";
- private Context context;
+ private final Context context;
- private ItemAccess itemAccess;
+ private final ItemAccess itemAccess;
public DownloadLogAdapter(Context context, ItemAccess itemAccess) {
super();
@@ -67,8 +66,6 @@ public class DownloadLogAdapter extends BaseAdapter {
holder.type.setText(R.string.download_type_feed);
} else if (status.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
holder.type.setText(R.string.download_type_media);
- } else if (status.getFeedfileType() == FeedImage.FEEDFILETYPE_FEEDIMAGE) {
- holder.type.setText(R.string.download_type_image);
}
if (status.getTitle() != null) {
holder.title.setText(status.getTitle());
@@ -94,8 +91,7 @@ public class DownloadLogAdapter extends BaseAdapter {
}
holder.reason.setText(reasonText);
holder.reason.setVisibility(View.VISIBLE);
- if(status.getFeedfileType() != FeedImage.FEEDFILETYPE_FEEDIMAGE &&
- !newerWasSuccessful(position, status.getFeedfileType(), status.getFeedfileId())) {
+ if(!newerWasSuccessful(position, status.getFeedfileType(), status.getFeedfileId())) {
holder.retry.setVisibility(View.VISIBLE);
holder.retry.setOnClickListener(clickListener);
ButtonHolder btnHolder;
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
index 6907e467b..51e1271d9 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
@@ -12,11 +12,11 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
-import com.nineoldandroids.view.ViewHelper;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
+import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.DateUtils;
@@ -87,9 +87,9 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter {
.into(holder.imageView);
if(item.isPlayed()) {
- ViewHelper.setAlpha(convertView, 0.5f);
+ convertView.setAlpha(0.5f);
} else {
- ViewHelper.setAlpha(convertView, 1.0f);
+ convertView.setAlpha(1.0f);
}
holder.title.setText(item.getTitle());
@@ -99,10 +99,12 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter {
holder.pubDate.setText(pubDateStr);
FeedItem.State state = item.getState();
- if (state == FeedItem.State.PLAYING) {
+ if (state == FeedItem.State.PLAYING && PlaybackService.isRunning) {
holder.butSecondary.setEnabled(false);
+ holder.butSecondary.setAlpha(0.5f);
} else {
holder.butSecondary.setEnabled(true);
+ holder.butSecondary.setAlpha(1.0f);
}
holder.butSecondary.setFocusable(false);
holder.butSecondary.setTag(item);
@@ -111,7 +113,7 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter {
return convertView;
}
- private View.OnClickListener secondaryActionListener = new View.OnClickListener() {
+ private final View.OnClickListener secondaryActionListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
FeedItem item = (FeedItem) v.getTag();
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java
index e1efdaa7b..a8c60c19e 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java
@@ -19,11 +19,11 @@ import de.danoeh.antennapod.core.util.ThemeUtils;
public class DownloadlistAdapter extends BaseAdapter {
- public static final int SELECTION_NONE = -1;
+ private static final int SELECTION_NONE = -1;
private int selectedItemIndex;
- private ItemAccess itemAccess;
- private Context context;
+ private final ItemAccess itemAccess;
+ private final Context context;
public DownloadlistAdapter(Context context,
ItemAccess itemAccess) {
@@ -105,7 +105,7 @@ public class DownloadlistAdapter extends BaseAdapter {
return convertView;
}
- private View.OnClickListener butSecondaryListener = new View.OnClickListener() {
+ private final View.OnClickListener butSecondaryListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
Downloader downloader = (Downloader) v.getTag();
@@ -121,15 +121,6 @@ public class DownloadlistAdapter extends BaseAdapter {
ImageButton butSecondary;
}
- public int getSelectedItemIndex() {
- return selectedItemIndex;
- }
-
- public void setSelectedItemIndex(int selectedItemIndex) {
- this.selectedItemIndex = selectedItemIndex;
- notifyDataSetChanged();
- }
-
public interface ItemAccess {
int getCount();
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
index 35c42725c..cf3dd8b09 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
@@ -17,13 +17,10 @@ import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
-import com.nineoldandroids.view.ViewHelper;
-
import de.danoeh.antennapod.R;
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.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.DateUtils;
import de.danoeh.antennapod.core.util.LongList;
@@ -34,16 +31,16 @@ import de.danoeh.antennapod.core.util.ThemeUtils;
*/
public class FeedItemlistAdapter extends BaseAdapter {
- private ActionButtonCallback callback;
+ private final ActionButtonCallback callback;
private final ItemAccess itemAccess;
private final Context context;
- private boolean showFeedtitle;
- private int selectedItemIndex;
+ private final boolean showFeedtitle;
+ private final int selectedItemIndex;
/** true if played items should be made partially transparent */
- private boolean makePlayedItemsTransparent;
+ private final boolean makePlayedItemsTransparent;
private final ActionButtonUtils actionButtonUtils;
- public static final int SELECTION_NONE = -1;
+ private static final int SELECTION_NONE = -1;
private final int playingBackGroundColor;
private final int normalBackGroundColor;
@@ -62,11 +59,7 @@ public class FeedItemlistAdapter extends BaseAdapter {
this.actionButtonUtils = new ActionButtonUtils(context);
this.makePlayedItemsTransparent = makePlayedItemsTransparent;
- if(UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
- playingBackGroundColor = ContextCompat.getColor(context, R.color.highlight_dark);
- } else {
- playingBackGroundColor = ContextCompat.getColor(context, R.color.highlight_light);
- }
+ playingBackGroundColor = ThemeUtils.getColorFromAttr(context, R.attr.currently_playing_background);
normalBackGroundColor = ContextCompat.getColor(context, android.R.color.transparent);
}
@@ -145,9 +138,9 @@ public class FeedItemlistAdapter extends BaseAdapter {
holder.statusUnread.setVisibility(View.INVISIBLE);
}
if(item.isPlayed() && makePlayedItemsTransparent) {
- ViewHelper.setAlpha(convertView, 0.5f);
+ convertView.setAlpha(0.5f);
} else {
- ViewHelper.setAlpha(convertView, 1.0f);
+ convertView.setAlpha(1.0f);
}
String pubDateStr = DateUtils.formatAbbrev(context, item.getPubDate());
@@ -157,7 +150,7 @@ public class FeedItemlistAdapter extends BaseAdapter {
FeedMedia media = item.getMedia();
if (media == null) {
- holder.episodeProgress.setVisibility(View.GONE);
+ holder.episodeProgress.setVisibility(View.INVISIBLE);
holder.inPlaylist.setVisibility(View.INVISIBLE);
holder.type.setVisibility(View.INVISIBLE);
holder.lenSize.setVisibility(View.INVISIBLE);
@@ -176,7 +169,7 @@ public class FeedItemlistAdapter extends BaseAdapter {
holder.episodeProgress.setProgress(itemAccess.getItemDownloadProgressPercent(item));
} else {
if(media.getPosition() == 0) {
- holder.episodeProgress.setVisibility(View.GONE);
+ holder.episodeProgress.setVisibility(View.INVISIBLE);
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
index 465497b55..2daa5e70f 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
@@ -48,10 +48,10 @@ import de.danoeh.antennapod.fragment.SubscriptionFragment;
public class NavListAdapter extends BaseAdapter
implements SharedPreferences.OnSharedPreferenceChangeListener {
- public static final int VIEW_TYPE_COUNT = 3;
+ private static final int VIEW_TYPE_COUNT = 3;
public static final int VIEW_TYPE_NAV = 0;
public static final int VIEW_TYPE_SECTION_DIVIDER = 1;
- public static final int VIEW_TYPE_SUBSCRIPTION = 2;
+ private static final int VIEW_TYPE_SUBSCRIPTION = 2;
/**
* a tag used as a placeholder to indicate if the subscription list should be displayed or not
@@ -62,8 +62,8 @@ public class NavListAdapter extends BaseAdapter
private static List<String> tags;
private static String[] titles;
- private ItemAccess itemAccess;
- private WeakReference<Activity> activity;
+ private final ItemAccess itemAccess;
+ private final WeakReference<Activity> activity;
private boolean showSubscriptionList = true;
public NavListAdapter(ItemAccess itemAccess, Activity context) {
@@ -86,9 +86,7 @@ public class NavListAdapter extends BaseAdapter
private void loadItems() {
List<String> newTags = new ArrayList<>(Arrays.asList(MainActivity.NAV_DRAWER_TAGS));
List<String> hiddenFragments = UserPreferences.getHiddenDrawerItems();
- for(String hidden : hiddenFragments) {
- newTags.remove(hidden);
- }
+ newTags.removeAll(hiddenFragments);
if (newTags.contains(SUBSCRIPTION_LIST_TAG)) {
// we never want SUBSCRIPTION_LIST_TAG to be in 'tags'
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
index c6ddc6c86..ee14cb70a 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
@@ -24,8 +24,8 @@ import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.joanzapata.iconify.Iconify;
-import com.nineoldandroids.view.ViewHelper;
+import de.danoeh.antennapod.core.util.ThemeUtils;
import org.apache.commons.lang3.ArrayUtils;
import java.lang.ref.WeakReference;
@@ -51,7 +51,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
private static final String TAG = QueueRecyclerAdapter.class.getSimpleName();
- private WeakReference<MainActivity> mainActivity;
+ private final WeakReference<MainActivity> mainActivity;
private final ItemAccess itemAccess;
private final ActionButtonCallback actionButtonCallback;
private final ActionButtonUtils actionButtonUtils;
@@ -76,11 +76,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
this.itemTouchHelper = itemTouchHelper;
locked = UserPreferences.isQueueLocked();
- if(UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
- playingBackGroundColor = ContextCompat.getColor(mainActivity, R.color.highlight_dark);
- } else {
- playingBackGroundColor = ContextCompat.getColor(mainActivity, R.color.highlight_light);
- }
+ playingBackGroundColor = ThemeUtils.getColorFromAttr(mainActivity, R.attr.currently_playing_background);
normalBackGroundColor = ContextCompat.getColor(mainActivity, android.R.color.transparent);
}
@@ -198,12 +194,12 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
@Override
public void onItemSelected() {
- ViewHelper.setAlpha(itemView, 0.5f);
+ itemView.setAlpha(0.5f);
}
@Override
public void onItemClear() {
- ViewHelper.setAlpha(itemView, 1.0f);
+ itemView.setAlpha(1.0f);
}
public void bind(FeedItem item) {
@@ -280,7 +276,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
progressLeft.setText("");
}
progressRight.setText(Converter.getDurationStringLong(media.getDuration()));
- progressBar.setVisibility(View.GONE);
+ progressBar.setVisibility(View.INVISIBLE);
}
if(media.isCurrentlyPlaying()) {
@@ -305,7 +301,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
}
- private View.OnClickListener secondaryActionListener = new View.OnClickListener() {
+ private final View.OnClickListener secondaryActionListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
FeedItem item = (FeedItem) v.getTag();
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java
index 8e1aa24e0..beb62b3bb 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java
@@ -11,7 +11,6 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
-import com.nineoldandroids.view.ViewHelper;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.Feed;
@@ -97,7 +96,7 @@ public class SearchlistAdapter extends BaseAdapter {
holder.subtitle.setText(result.getSubtitle());
}
- ViewHelper.setAlpha(convertView, item.isPlayed() ? 0.5f : 1.0f);
+ convertView.setAlpha(item.isPlayed() ? 0.5f : 1.0f);
Glide.with(context)
.load(item.getFeed().getImageLocation())
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java
index c060083a6..50255c11f 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java
@@ -23,8 +23,8 @@ import de.danoeh.antennapod.core.util.Converter;
* Adapter for the statistics list
*/
public class StatisticsListAdapter extends BaseAdapter {
- private Context context;
- List<DBReader.StatisticsItem> feedTime = new ArrayList<>();
+ private final Context context;
+ private List<DBReader.StatisticsItem> feedTime = new ArrayList<>();
private boolean countAll = true;
public StatisticsListAdapter(Context context) {
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java
index 6d19bfa6c..bb76ab501 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java
@@ -50,7 +50,6 @@ public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnI
}
private int getAdjustedPosition(int origPosition) {
- assert(origPosition != getAddTilePosition());
return origPosition < getAddTilePosition() ? origPosition : origPosition - 1;
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java
index f1f8be559..e493a2ecc 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java
@@ -124,7 +124,7 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
* @param json object holding the podcast information
* @throws JSONException
*/
- public static Podcast fromSearch(JSONObject json) throws JSONException {
+ public static Podcast fromSearch(JSONObject json) {
String title = json.optString("collectionName", "");
String imageUrl = json.optString("artworkUrl100", null);
String feedUrl = json.optString("feedUrl", null);
@@ -162,7 +162,7 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
/**
* View holder object for the GridView
*/
- class PodcastViewHolder {
+ static class PodcastViewHolder {
/**
* ImageView holding the Podcast image
diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java
index 192df8ca5..b6cf5cb84 100644
--- a/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java
+++ b/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java
@@ -23,15 +23,15 @@ public class ExportWorker {
private static final String TAG = "ExportWorker";
private static final String DEFAULT_OUTPUT_NAME = "antennapod-feeds";
- private ExportWriter exportWriter;
- private File output;
+ private final ExportWriter exportWriter;
+ private final File output;
public ExportWorker(ExportWriter exportWriter) {
this(exportWriter, new File(UserPreferences.getDataFolder(EXPORT_DIR),
DEFAULT_OUTPUT_NAME + "." + exportWriter.fileExtension()));
}
- public ExportWorker(ExportWriter exportWriter, @NonNull File output) {
+ private ExportWorker(ExportWriter exportWriter, @NonNull File output) {
this.exportWriter = exportWriter;
this.output = output;
}
diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java
index 4449d82c2..ea5128102 100644
--- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java
+++ b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java
@@ -1,6 +1,5 @@
package de.danoeh.antennapod.asynctask;
-import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
@@ -16,9 +15,9 @@ import de.danoeh.antennapod.core.storage.DownloadRequester;
/** Queues items for download in the background. */
public class OpmlFeedQueuer extends AsyncTask<Void, Void, Void> {
- private Context context;
+ private final Context context;
private ProgressDialog progDialog;
- private int[] selection;
+ private final int[] selection;
public OpmlFeedQueuer(Context context, int[] selection) {
super();
@@ -56,13 +55,8 @@ public class OpmlFeedQueuer extends AsyncTask<Void, Void, Void> {
return null;
}
- @SuppressLint("NewApi")
public void executeAsync() {
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- executeOnExecutor(THREAD_POOL_EXECUTOR);
- } else {
- execute();
- }
+ executeOnExecutor(THREAD_POOL_EXECUTOR);
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java
index 62ea85811..13b95907f 100644
--- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java
+++ b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java
@@ -1,6 +1,5 @@
package de.danoeh.antennapod.asynctask;
-import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
@@ -21,12 +20,12 @@ public class OpmlImportWorker extends
AsyncTask<Void, Void, ArrayList<OpmlElement>> {
private static final String TAG = "OpmlImportWorker";
- private Context context;
+ private final Context context;
private Exception exception;
private ProgressDialog progDialog;
- private Reader mReader;
+ private final Reader mReader;
public OpmlImportWorker(Context context, Reader reader) {
super();
@@ -93,13 +92,8 @@ public class OpmlImportWorker extends
return exception != null;
}
- @SuppressLint("NewApi")
public void executeAsync() {
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- executeOnExecutor(THREAD_POOL_EXECUTOR);
- } else {
- execute();
- }
+ executeOnExecutor(THREAD_POOL_EXECUTOR);
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java b/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java
index 538abd4c7..4138738f6 100644
--- a/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java
+++ b/app/src/main/java/de/danoeh/antennapod/config/ClientConfigurator.java
@@ -6,7 +6,7 @@ import de.danoeh.antennapod.core.ClientConfig;
/**
* Configures the ClientConfig class of the core package.
*/
-public class ClientConfigurator {
+class ClientConfigurator {
private ClientConfigurator(){}
diff --git a/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java b/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java
index 1ab60ef61..83dd3fe9c 100644
--- a/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java
+++ b/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java
@@ -3,6 +3,7 @@ package de.danoeh.antennapod.config;
import android.content.Context;
import android.content.Intent;
+import android.os.Build;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.AudioplayerActivity;
import de.danoeh.antennapod.activity.CastplayerActivity;
@@ -18,7 +19,11 @@ public class PlaybackServiceCallbacksImpl implements PlaybackServiceCallbacks {
return new Intent(context, CastplayerActivity.class);
}
if (mediaType == MediaType.VIDEO) {
- return new Intent(context, VideoplayerActivity.class);
+ Intent i = new Intent(context, VideoplayerActivity.class);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
+ }
+ return i;
} else {
return new Intent(context, AudioplayerActivity.class);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
index ac073141d..d1ee926ac 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
@@ -32,14 +32,14 @@ import de.danoeh.antennapod.core.util.LongList;
public class EpisodesApplyActionFragment extends Fragment {
- public String TAG = "EpisodeActionFragment";
+ public static final String TAG = "EpisodeActionFragment";
public static final int ACTION_QUEUE = 1;
- public static final int ACTION_MARK_PLAYED = 2;
- public static final int ACTION_MARK_UNPLAYED = 4;
- public static final int ACTION_DOWNLOAD = 8;
+ private static final int ACTION_MARK_PLAYED = 2;
+ private static final int ACTION_MARK_UNPLAYED = 4;
+ private static final int ACTION_DOWNLOAD = 8;
public static final int ACTION_REMOVE = 16;
- public static final int ACTION_ALL = ACTION_QUEUE | ACTION_MARK_PLAYED | ACTION_MARK_UNPLAYED
+ private static final int ACTION_ALL = ACTION_QUEUE | ACTION_MARK_PLAYED | ACTION_MARK_UNPLAYED
| ACTION_DOWNLOAD | ACTION_REMOVE;
private ListView mListView;
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java
index a4e71c249..933ced0f9 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java
@@ -8,6 +8,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.LinearLayout;
+
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.gpoddernet.GpodnetService;
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java
index 0bd75b5b0..b9276982a 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java
@@ -43,7 +43,7 @@ public class ProxyDialog {
private static final String TAG = "ProxyDialog";
- private Context context;
+ private final Context context;
private MaterialDialog dialog;
@@ -243,47 +243,44 @@ public class ProxyDialog {
txtvMessage.setTextColor(textColorPrimary);
txtvMessage.setText("{fa-circle-o-notch spin} " + checking);
txtvMessage.setVisibility(View.VISIBLE);
- subscription = Observable.create(new Observable.OnSubscribe<Response>() {
- @Override
- public void call(Subscriber<? super Response> subscriber) {
- String type = (String) spType.getSelectedItem();
- String host = etHost.getText().toString();
- String port = etPort.getText().toString();
- String username = etUsername.getText().toString();
- String password = etPassword.getText().toString();
- int portValue = 8080;
- if(!TextUtils.isEmpty(port)) {
- portValue = Integer.valueOf(port);
- }
- SocketAddress address = InetSocketAddress.createUnresolved(host, portValue);
- Proxy.Type proxyType = Proxy.Type.valueOf(type.toUpperCase());
- Proxy proxy = new Proxy(proxyType, address);
- OkHttpClient.Builder builder = AntennapodHttpClient.newBuilder()
- .connectTimeout(10, TimeUnit.SECONDS)
- .proxy(proxy);
- builder.interceptors().clear();
- OkHttpClient client = builder.build();
- if(!TextUtils.isEmpty(username)) {
- String credentials = Credentials.basic(username, password);
- client.interceptors().add(chain -> {
- Request request = chain.request().newBuilder()
- .header("Proxy-Authorization", credentials).build();
- return chain.proceed(request);
- });
- }
- Request request = new Request.Builder()
- .url("http://www.google.com")
- .head()
- .build();
- try {
- Response response = client.newCall(request).execute();
- subscriber.onNext(response);
- } catch(IOException e) {
- subscriber.onError(e);
- }
- subscriber.onCompleted();
- }
- })
+ subscription = Observable.create((Observable.OnSubscribe<Response>) subscriber -> {
+ String type = (String) spType.getSelectedItem();
+ String host = etHost.getText().toString();
+ String port = etPort.getText().toString();
+ String username = etUsername.getText().toString();
+ String password = etPassword.getText().toString();
+ int portValue = 8080;
+ if(!TextUtils.isEmpty(port)) {
+ portValue = Integer.valueOf(port);
+ }
+ SocketAddress address = InetSocketAddress.createUnresolved(host, portValue);
+ Proxy.Type proxyType = Proxy.Type.valueOf(type.toUpperCase());
+ Proxy proxy = new Proxy(proxyType, address);
+ OkHttpClient.Builder builder = AntennapodHttpClient.newBuilder()
+ .connectTimeout(10, TimeUnit.SECONDS)
+ .proxy(proxy);
+ builder.interceptors().clear();
+ OkHttpClient client = builder.build();
+ if(!TextUtils.isEmpty(username)) {
+ String credentials = Credentials.basic(username, password);
+ client.interceptors().add(chain -> {
+ Request request = chain.request().newBuilder()
+ .header("Proxy-Authorization", credentials).build();
+ return chain.proceed(request);
+ });
+ }
+ Request request = new Request.Builder()
+ .url("http://www.google.com")
+ .head()
+ .build();
+ try {
+ Response response = client.newCall(request).execute();
+ subscriber.onNext(response);
+ } catch(IOException e) {
+ subscriber.onError(e);
+ }
+ subscriber.onCompleted();
+ })
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java
index 6b38ecb2e..ece184035 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java
@@ -56,7 +56,7 @@ public class RatingDialog {
}
}
- public static void rateNow() {
+ private static void rateNow() {
Context context = mContext.get();
if(context == null) {
return;
@@ -69,11 +69,11 @@ public class RatingDialog {
saveRated();
}
- public static boolean rated() {
+ private static boolean rated() {
return mPreferences.getBoolean(KEY_RATED, false);
}
- public static void saveRated() {
+ private static void saveRated() {
mPreferences
.edit()
.putBoolean(KEY_RATED, true)
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java
index 7d6a66a54..be7850495 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java
@@ -1,7 +1,6 @@
package de.danoeh.antennapod.dialog;
import android.content.Context;
-import android.support.design.widget.Snackbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
@@ -9,7 +8,6 @@ import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
-import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
@@ -26,7 +24,7 @@ public abstract class SleepTimerDialog {
private static final String TAG = SleepTimerDialog.class.getSimpleName();
- private Context context;
+ private final Context context;
private MaterialDialog dialog;
private EditText etxtTime;
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
index 6a975fe49..cf9a2907b 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
@@ -52,7 +52,7 @@ public class VariableSpeedDialog {
builder.neutralText(R.string.close_label);
builder.onPositive((dialog, which) -> {
if (Build.VERSION.SDK_INT >= 16) { // just to be safe
- UserPreferences.enableSonic(true);
+ UserPreferences.enableSonic();
if(showSpeedSelector) {
showSpeedSelectorDialog(context);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java
index f14ebbdaf..a243ddcdc 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java
@@ -25,7 +25,7 @@ public class AddFeedFragment extends Fragment {
/**
* Preset value for url text field.
*/
- public static final String ARG_FEED_URL = "feedurl";
+ private static final String ARG_FEED_URL = "feedurl";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -66,4 +66,15 @@ public class AddFeedFragment extends Fragment {
return root;
}
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setRetainInstance(true);
+
+ // So, we certainly *don't* have an options menu,
+ // but unless we say we do, old options menus sometimes
+ // persist. mfietz thinks this causes the ActionBar to be invalidated
+ setHasOptionsMenu(true);
+ }
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
index bbfd1688d..497891dbd 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
@@ -4,6 +4,8 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
+import android.os.Handler;
+import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.LinearLayoutManager;
@@ -36,12 +38,12 @@ import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
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.download.DownloadService;
import de.danoeh.antennapod.core.service.download.Downloader;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
-import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.LongList;
@@ -69,24 +71,24 @@ public class AllEpisodesFragment extends Fragment {
private static final String PREF_SCROLL_POSITION = "scroll_position";
private static final String PREF_SCROLL_OFFSET = "scroll_offset";
- protected RecyclerView recyclerView;
- protected AllEpisodesRecycleAdapter listAdapter;
+ RecyclerView recyclerView;
+ AllEpisodesRecycleAdapter listAdapter;
private ProgressBar progLoading;
- protected List<FeedItem> episodes;
+ List<FeedItem> episodes;
private List<Downloader> downloaderList;
private boolean itemsLoaded = false;
private boolean viewsCreated = false;
private boolean isUpdatingFeeds;
- protected boolean isMenuInvalidationAllowed = false;
+ boolean isMenuInvalidationAllowed = false;
- protected Subscription subscription;
+ Subscription subscription;
private LinearLayoutManager layoutManager;
- protected boolean showOnlyNewEpisodes() { return false; }
- protected String getPrefName() { return DEFAULT_PREF_NAME; }
+ boolean showOnlyNewEpisodes() { return false; }
+ String getPrefName() { return DEFAULT_PREF_NAME; }
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -165,7 +167,7 @@ public class AllEpisodesFragment extends Fragment {
}
}
- protected void resetViewState() {
+ void resetViewState() {
viewsCreated = false;
listAdapter = null;
}
@@ -284,13 +286,17 @@ public class AllEpisodesFragment extends Fragment {
return super.onContextItemSelected(item);
}
- try {
- return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
+ // Mark as seen contains UI logic specific to All/New/FavoriteSegments,
+ // e.g., Undo with Snackbar,
+ // and is handled by this class rather than the generic FeedItemMenuHandler
+ // Undo is useful for Mark as seen, given there is no UI to undo it otherwise,
+ // i.e., there is context menu item for Mark as new
+ if (R.id.mark_as_seen_item == item.getItemId()) {
+ markItemAsSeenWithUndo(selectedItem);
return true;
}
+
+ return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
}
@Override
@@ -299,10 +305,10 @@ public class AllEpisodesFragment extends Fragment {
R.layout.all_episodes_fragment);
}
- protected View onCreateViewHelper(LayoutInflater inflater,
- ViewGroup container,
- Bundle savedInstanceState,
- int fragmentResource) {
+ View onCreateViewHelper(LayoutInflater inflater,
+ ViewGroup container,
+ Bundle savedInstanceState,
+ int fragmentResource) {
super.onCreateView(inflater, container, savedInstanceState);
View root = inflater.inflate(fragmentResource, container, false);
@@ -346,7 +352,7 @@ public class AllEpisodesFragment extends Fragment {
updateShowOnlyEpisodesListViewState();
}
- protected AllEpisodesRecycleAdapter.ItemAccess itemAccess = new AllEpisodesRecycleAdapter.ItemAccess() {
+ private final AllEpisodesRecycleAdapter.ItemAccess itemAccess = new AllEpisodesRecycleAdapter.ItemAccess() {
@Override
public int getCount() {
@@ -444,7 +450,7 @@ public class AllEpisodesFragment extends Fragment {
}
}
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
+ private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override
public void update(EventDistributor eventDistributor, Integer arg) {
if ((arg & EVENTS) != 0) {
@@ -459,7 +465,7 @@ public class AllEpisodesFragment extends Fragment {
private void updateShowOnlyEpisodesListViewState() {
}
- protected void loadItems() {
+ void loadItems() {
if(subscription != null) {
subscription.unsubscribe();
}
@@ -483,8 +489,40 @@ public class AllEpisodesFragment extends Fragment {
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
}
- protected List<FeedItem> loadData() {
+ List<FeedItem> loadData() {
return DBReader.getRecentlyPublishedEpisodes(RECENT_EPISODES_LIMIT);
}
+ void markItemAsSeenWithUndo(FeedItem item) {
+ if (item == null) {
+ return;
+ }
+
+ Log.d(TAG, "markItemAsSeenWithUndo(" + item.getId() + ")");
+ if (subscription != null) {
+ subscription.unsubscribe();
+ }
+ // we're marking it as unplayed since the user didn't actually play it
+ // but they don't want it considered 'NEW' anymore
+ DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId());
+
+ final Handler h = new Handler(getActivity().getMainLooper());
+ final Runnable r = () -> {
+ FeedMedia media = item.getMedia();
+ if (media != null && media.hasAlmostEnded() && UserPreferences.isAutoDelete()) {
+ DBWriter.deleteFeedMediaOfItem(getActivity(), media.getId());
+ }
+ };
+
+ Snackbar snackbar = Snackbar.make(getView(), getString(R.string.marked_as_seen_label),
+ Snackbar.LENGTH_LONG);
+ snackbar.setAction(getString(R.string.undo), v -> {
+ DBWriter.markItemPlayed(FeedItem.NEW, item.getId());
+ // don't forget to cancel the thing that's going to remove the media
+ h.removeCallbacks(r);
+ });
+ snackbar.show();
+ h.postDelayed(r, (int)Math.ceil(snackbar.getDuration() * 1.05f));
+ }
+
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
index 1ba7ed557..f6d503b29 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
@@ -140,18 +140,7 @@ public class CompletedDownloadsFragment extends ListFragment {
super.onCreateOptionsMenu(menu, inflater);
if(items != null) {
inflater.inflate(R.menu.downloads_completed, menu);
- MenuItem episodeActions = menu.findItem(R.id.episode_actions);
- if(items.size() > 0) {
- int[] attrs = {R.attr.action_bar_icon_color};
- TypedArray ta = getActivity().obtainStyledAttributes(UserPreferences.getTheme(), attrs);
- int textColor = ta.getColor(0, Color.GRAY);
- ta.recycle();
- episodeActions.setIcon(new IconDrawable(getActivity(),
- FontAwesomeIcons.fa_gears).color(textColor).actionBarSize());
- episodeActions.setVisible(true);
- } else {
- episodeActions.setVisible(false);
- }
+ menu.findItem(R.id.episode_actions).setVisible(items.size() > 0);
}
}
@@ -160,7 +149,7 @@ public class CompletedDownloadsFragment extends ListFragment {
switch (item.getItemId()) {
case R.id.episode_actions:
EpisodesApplyActionFragment fragment = EpisodesApplyActionFragment
- .newInstance(items, EpisodesApplyActionFragment.ACTION_REMOVE);
+ .newInstance(items, EpisodesApplyActionFragment.ACTION_REMOVE | EpisodesApplyActionFragment.ACTION_QUEUE);
((MainActivity) getActivity()).loadChildFragment(fragment);
return true;
default:
@@ -168,7 +157,7 @@ public class CompletedDownloadsFragment extends ListFragment {
}
}
- private DownloadedEpisodesListAdapter.ItemAccess itemAccess = new DownloadedEpisodesListAdapter.ItemAccess() {
+ private final DownloadedEpisodesListAdapter.ItemAccess itemAccess = new DownloadedEpisodesListAdapter.ItemAccess() {
@Override
public int getCount() {
return (items != null) ? items.size() : 0;
@@ -189,7 +178,7 @@ public class CompletedDownloadsFragment extends ListFragment {
}
};
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
+ private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override
public void update(EventDistributor eventDistributor, Integer arg) {
if ((arg & EVENTS) != 0) {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
index 0a710196a..ae9c60f65 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
@@ -1,5 +1,7 @@
package de.danoeh.antennapod.fragment;
+import android.app.AlertDialog;
+import android.app.Dialog;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
@@ -13,9 +15,11 @@ import android.widget.ListView;
import java.util.List;
+import android.widget.TextView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.DownloadLogAdapter;
import de.danoeh.antennapod.core.feed.EventDistributor;
+import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.service.download.DownloadStatus;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
@@ -82,7 +86,30 @@ public class DownloadLogFragment extends ListFragment {
getActivity().supportInvalidateOptionsMenu();
}
- private DownloadLogAdapter.ItemAccess itemAccess = new DownloadLogAdapter.ItemAccess() {
+ @Override
+ public void onListItemClick(ListView l, View v, int position, long id) {
+ super.onListItemClick(l, v, position, id);
+
+ DownloadStatus status = adapter.getItem(position);
+ String url = "unknown";
+ String message = getString(R.string.download_successful);
+ FeedMedia media = DBReader.getFeedMedia(status.getFeedfileId());
+ if (media != null) {
+ url = media.getDownload_url();
+ }
+ if (!status.isSuccessful()) {
+ message = status.getReasonDetailed();
+ }
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+ builder.setTitle(R.string.download_error_details);
+ builder.setMessage(getString(R.string.download_error_details_message, message, url));
+ builder.setPositiveButton(android.R.string.ok, null);
+ Dialog dialog = builder.show();
+ ((TextView) dialog.findViewById(android.R.id.message)).setTextIsSelectable(true);
+ }
+
+ private final DownloadLogAdapter.ItemAccess itemAccess = new DownloadLogAdapter.ItemAccess() {
@Override
public int getCount() {
@@ -99,7 +126,7 @@ public class DownloadLogFragment extends ListFragment {
}
};
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
+ private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override
public void update(EventDistributor eventDistributor, Integer arg) {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java
index 52a38ccb9..9c4d00e31 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java
@@ -25,7 +25,7 @@ public class DownloadsFragment extends Fragment {
public static final String ARG_SELECTED_TAB = "selected_tab";
public static final int POS_RUNNING = 0;
- public static final int POS_COMPLETED = 1;
+ private static final int POS_COMPLETED = 1;
public static final int POS_LOG = 2;
private static final String PREF_LAST_TAB_POSITION = "tab_position";
@@ -78,9 +78,9 @@ public class DownloadsFragment extends Fragment {
viewPager.setCurrentItem(lastPosition);
}
- public class DownloadsPagerAdapter extends FragmentPagerAdapter {
+ public static class DownloadsPagerAdapter extends FragmentPagerAdapter {
- Resources resources;
+ final Resources resources;
public DownloadsPagerAdapter(FragmentManager fm, Resources resources) {
super(fm);
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java
index e2fbd91f3..417ecff89 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java
@@ -21,10 +21,10 @@ public class EpisodesFragment extends Fragment {
public static final String TAG = "EpisodesFragment";
private static final String PREF_LAST_TAB_POSITION = "tab_position";
- public static final int POS_NEW_EPISODES = 0;
- public static final int POS_ALL_EPISODES = 1;
- public static final int POS_FAV_EPISODES = 2;
- public static final int TOTAL_COUNT = 3;
+ private static final int POS_NEW_EPISODES = 0;
+ private static final int POS_ALL_EPISODES = 1;
+ private static final int POS_FAV_EPISODES = 2;
+ private static final int TOTAL_COUNT = 3;
private TabLayout tabLayout;
@@ -79,7 +79,7 @@ public class EpisodesFragment extends Fragment {
public static class EpisodesPagerAdapter extends FragmentPagerAdapter {
private final Resources resources;
- private AllEpisodesFragment[] fragments = {
+ private final AllEpisodesFragment[] fragments = {
new NewEpisodesFragment(),
new AllEpisodesFragment(),
new FavoriteEpisodesFragment()
@@ -106,7 +106,7 @@ public class EpisodesFragment extends Fragment {
case POS_ALL_EPISODES:
return resources.getString(R.string.all_episodes_short_label);
case POS_NEW_EPISODES:
- return resources.getString(R.string.new_label);
+ return resources.getString(R.string.new_episodes_label);
case POS_FAV_EPISODES:
return resources.getString(R.string.favorite_episodes_label);
default:
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
index 1e385728a..9e8c9731e 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
@@ -1,6 +1,9 @@
package de.danoeh.antennapod.fragment;
+import android.content.Intent;
+import android.os.Build;
import android.os.Bundle;
+import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
@@ -14,11 +17,15 @@ import android.widget.TextView;
import com.bumptech.glide.Glide;
import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.feed.MediaType;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
-import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
+import rx.Single;
+import rx.Subscription;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.schedulers.Schedulers;
/**
* Fragment which is supposed to be displayed outside of the MediaplayerActivity
@@ -33,8 +40,8 @@ public class ExternalPlayerFragment extends Fragment {
private ImageButton butPlay;
private TextView mFeedName;
private ProgressBar mProgressBar;
-
private PlaybackController controller;
+ private Subscription subscription;
public ExternalPlayerFragment() {
super();
@@ -56,8 +63,15 @@ public class ExternalPlayerFragment extends Fragment {
Log.d(TAG, "layoutInfo was clicked");
if (controller != null && controller.getMedia() != null) {
- startActivity(PlaybackService.getPlayerActivityIntent(
- getActivity(), controller.getMedia()));
+ Intent intent = PlaybackService.getPlayerActivityIntent(getActivity(), controller.getMedia());
+
+ if (Build.VERSION.SDK_INT >= 16 && controller.getMedia().getMediaType() == MediaType.AUDIO) {
+ ActivityOptionsCompat options = ActivityOptionsCompat.
+ makeSceneTransitionAnimation(getActivity(), imgvCover, "coverTransition");
+ startActivity(intent, options.toBundle());
+ } else {
+ startActivity(intent);
+ }
}
});
return root;
@@ -68,10 +82,15 @@ public class ExternalPlayerFragment extends Fragment {
super.onActivityCreated(savedInstanceState);
controller = setupPlaybackController();
butPlay.setOnClickListener(v -> {
- if(controller != null) {
+ if (controller != null) {
controller.playPause();
}
});
+ loadMediaInfo();
+ }
+
+ public void connectToPlaybackService() {
+ controller.init();
}
private PlaybackController setupPlaybackController() {
@@ -112,9 +131,9 @@ public class ExternalPlayerFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
+ onPositionObserverUpdate();
+
controller.init();
- mProgressBar.setProgress((int)
- ((double) controller.getPosition() / controller.getDuration() * 100));
}
@Override
@@ -124,6 +143,9 @@ public class ExternalPlayerFragment extends Fragment {
if (controller != null) {
controller.release();
}
+ if (subscription != null) {
+ subscription.unsubscribe();
+ }
}
@Override
@@ -144,7 +166,7 @@ public class ExternalPlayerFragment extends Fragment {
controller = setupPlaybackController();
if (butPlay != null) {
butPlay.setOnClickListener(v -> {
- if(controller != null) {
+ if (controller != null) {
controller.playPause();
}
});
@@ -154,50 +176,56 @@ public class ExternalPlayerFragment extends Fragment {
private boolean loadMediaInfo() {
Log.d(TAG, "Loading media info");
- if (controller != null && controller.serviceAvailable()) {
- Playable media = controller.getMedia();
- if (media != null) {
- txtvTitle.setText(media.getEpisodeTitle());
- mFeedName.setText(media.getFeedTitle());
- mProgressBar.setProgress((int)
- ((double) controller.getPosition() / controller.getDuration() * 100));
-
- Glide.with(getActivity())
- .load(media.getImageLocation())
- .placeholder(R.color.light_gray)
- .error(R.color.light_gray)
- .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
- .fitCenter()
- .dontAnimate()
- .into(imgvCover);
-
- fragmentLayout.setVisibility(View.VISIBLE);
- if (controller.isPlayingVideoLocally()) {
- butPlay.setVisibility(View.GONE);
- } else {
- butPlay.setVisibility(View.VISIBLE);
- }
- return true;
- } else {
- Log.w(TAG, "loadMediaInfo was called while the media object of playbackService was null!");
- return false;
- }
- } else {
- Log.w(TAG, "loadMediaInfo was called while playbackService was null!");
+ if (controller == null) {
+ Log.w(TAG, "loadMediaInfo was called while PlaybackController was null!");
return false;
}
+
+ if (subscription != null) {
+ subscription.unsubscribe();
+ }
+ subscription = Single.create(subscriber -> subscriber.onSuccess(controller.getMedia()))
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(media -> updateUi((Playable) media));
+ return true;
}
- private String getPositionString(int position, int duration) {
- return Converter.getDurationStringLong(position) + " / "
- + Converter.getDurationStringLong(duration);
+ private void updateUi(Playable media) {
+ if (media != null) {
+ txtvTitle.setText(media.getEpisodeTitle());
+ mFeedName.setText(media.getFeedTitle());
+ onPositionObserverUpdate();
+
+ Glide.with(getActivity())
+ .load(media.getImageLocation())
+ .placeholder(R.color.light_gray)
+ .error(R.color.light_gray)
+ .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
+ .fitCenter()
+ .dontAnimate()
+ .into(imgvCover);
+
+ fragmentLayout.setVisibility(View.VISIBLE);
+ if (controller.isPlayingVideoLocally()) {
+ butPlay.setVisibility(View.GONE);
+ } else {
+ butPlay.setVisibility(View.VISIBLE);
+ }
+ } else {
+ Log.w(TAG, "loadMediaInfo was called while the media object of playbackService was null!");
+ }
}
public PlaybackController getPlaybackControllerTestingOnly() {
return controller;
}
- public void onPositionObserverUpdate() {
+ private void onPositionObserverUpdate() {
+ if (controller.getPosition() == PlaybackService.INVALID_TIME
+ || controller.getDuration() == PlaybackService.INVALID_TIME) {
+ return;
+ }
mProgressBar.setProgress((int)
((double) controller.getPosition() / controller.getDuration() * 100));
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
index 234c8377d..76d19d61c 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FavoriteEpisodesFragment.java
@@ -26,7 +26,7 @@ import de.danoeh.antennapod.core.storage.DBWriter;
public class FavoriteEpisodesFragment extends AllEpisodesFragment {
- public static final String TAG = "FavoriteEpisodesFrag";
+ private static final String TAG = "FavoriteEpisodesFrag";
private static final String PREF_NAME = "PrefFavoriteEpisodesFragment";
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java
index 7c1ec5ec1..6ee9ce467 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java
@@ -49,7 +49,7 @@ public class FyydSearchFragment extends Fragment {
private Button butRetry;
private TextView txtvEmpty;
- private FyydClient client = new FyydClient(AntennapodHttpClient.getHttpClient());
+ private final FyydClient client = new FyydClient(AntennapodHttpClient.getHttpClient());
/**
* List of podcasts retreived from the search
@@ -169,7 +169,7 @@ public class FyydSearchFragment extends Fragment {
progressBar.setVisibility(View.VISIBLE);
}
- void processSearchResult(FyydResponse response) {
+ private void processSearchResult(FyydResponse response) {
adapter.clear();
if (!response.getData().isEmpty()) {
adapter.clear();
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
index a0586fe16..829e1924a 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
@@ -10,7 +10,6 @@ import android.content.SharedPreferences;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.net.Uri;
-import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
@@ -34,6 +33,7 @@ import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.IntentUtils;
+import de.danoeh.antennapod.core.util.NetworkUtils;
import de.danoeh.antennapod.core.util.ShareUtils;
import de.danoeh.antennapod.core.util.ShownotesProvider;
import de.danoeh.antennapod.core.util.playback.Playable;
@@ -112,15 +112,20 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo
Bundle savedInstanceState) {
Log.d(TAG, "Creating view");
webvDescription = new WebView(getActivity().getApplicationContext());
- if (Build.VERSION.SDK_INT >= 11) {
- webvDescription.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
- }
+ webvDescription.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+
TypedArray ta = getActivity().getTheme().obtainStyledAttributes(new int[]
{android.R.attr.colorBackground});
- int backgroundColor = ta.getColor(0, UserPreferences.getTheme() ==
- R.style.Theme_AntennaPod_Dark ? Color.BLACK : Color.WHITE);
+ boolean black = UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark
+ || UserPreferences.getTheme() == R.style.Theme_AntennaPod_TrueBlack;
+ int backgroundColor = ta.getColor(0, black ? Color.BLACK : Color.WHITE);
+
ta.recycle();
webvDescription.setBackgroundColor(backgroundColor);
+ if (!NetworkUtils.networkAvailable()) {
+ webvDescription.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
+ // Use cached resources, even if they have expired
+ }
webvDescription.getSettings().setUseWideViewPort(false);
webvDescription.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
webvDescription.getSettings().setLoadWithOverviewMode(true);
@@ -203,7 +208,7 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo
}
- private View.OnLongClickListener webViewLongClickListener = new View.OnLongClickListener() {
+ private final View.OnLongClickListener webViewLongClickListener = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
@@ -238,17 +243,11 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo
ShareUtils.shareLink(getActivity(), selectedURL);
break;
case R.id.copy_url_item:
- if (android.os.Build.VERSION.SDK_INT >= 11) {
- ClipData clipData = ClipData.newPlainText(selectedURL,
- selectedURL);
- android.content.ClipboardManager cm = (android.content.ClipboardManager) getActivity()
- .getSystemService(Context.CLIPBOARD_SERVICE);
- cm.setPrimaryClip(clipData);
- } else {
- android.text.ClipboardManager cm = (android.text.ClipboardManager) getActivity()
- .getSystemService(Context.CLIPBOARD_SERVICE);
- cm.setText(selectedURL);
- }
+ ClipData clipData = ClipData.newPlainText(selectedURL,
+ selectedURL);
+ android.content.ClipboardManager cm = (android.content.ClipboardManager) getActivity()
+ .getSystemService(Context.CLIPBOARD_SERVICE);
+ cm.setPrimaryClip(clipData);
Toast t = Toast.makeText(getActivity(),
R.string.copied_url_msg, Toast.LENGTH_SHORT);
t.show();
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
index 7939dcb23..5075d022a 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
@@ -34,6 +34,8 @@ import com.bumptech.glide.Glide;
import com.joanzapata.iconify.Iconify;
import com.joanzapata.iconify.widget.IconButton;
+import de.danoeh.antennapod.core.service.playback.PlaybackService;
+import de.danoeh.antennapod.core.util.NetworkUtils;
import org.apache.commons.lang3.ArrayUtils;
import java.util.List;
@@ -183,13 +185,17 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
txtvTitle.setEllipsize(TextUtils.TruncateAt.END);
}
webvDescription = (WebView) layout.findViewById(R.id.webvDescription);
- if (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
- if (Build.VERSION.SDK_INT >= 11
- && Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
+ if (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark ||
+ UserPreferences.getTheme() == R.style.Theme_AntennaPod_TrueBlack) {
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
webvDescription.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
webvDescription.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.black));
}
+ if (!NetworkUtils.networkAvailable()) {
+ webvDescription.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
+ // Use cached resources, even if they have expired
+ }
webvDescription.getSettings().setUseWideViewPort(false);
webvDescription.getSettings().setLayoutAlgorithm(
WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
@@ -335,13 +341,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
openPodcast();
return true;
default:
- try {
- return FeedItemMenuHandler.onMenuItemClicked(getActivity(), menuItem.getItemId(), item);
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
- return true;
- }
+ return FeedItemMenuHandler.onMenuItemClicked(getActivity(), menuItem.getItemId(), item);
}
}
@@ -434,6 +434,16 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
butAction1Text = R.string.download_label;
}
}
+
+ FeedItem.State state = item.getState();
+ if (butAction2Text == R.string.delete_label && state == FeedItem.State.PLAYING && PlaybackService.isRunning) {
+ butAction2.setEnabled(false);
+ butAction2.setAlpha(0.5f);
+ } else {
+ butAction2.setEnabled(true);
+ butAction2.setAlpha(1.0f);
+ }
+
if(butAction1Icon != null && butAction1Text != 0) {
butAction1.setText(butAction1Icon +"\u0020\u0020" + getActivity().getString(butAction1Text));
Iconify.addIcons(butAction1);
@@ -450,7 +460,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
}
}
- private View.OnLongClickListener webViewLongClickListener = new View.OnLongClickListener() {
+ private final View.OnLongClickListener webViewLongClickListener = new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
@@ -483,17 +493,11 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
ShareUtils.shareLink(getActivity(), selectedURL);
break;
case R.id.copy_url_item:
- if (android.os.Build.VERSION.SDK_INT >= 11) {
- ClipData clipData = ClipData.newPlainText(selectedURL,
- selectedURL);
- android.content.ClipboardManager cm = (android.content.ClipboardManager) getActivity()
- .getSystemService(Context.CLIPBOARD_SERVICE);
- cm.setPrimaryClip(clipData);
- } else {
- android.text.ClipboardManager cm = (android.text.ClipboardManager) getActivity()
- .getSystemService(Context.CLIPBOARD_SERVICE);
- cm.setText(selectedURL);
- }
+ ClipData clipData = ClipData.newPlainText(selectedURL,
+ selectedURL);
+ android.content.ClipboardManager cm = (android.content.ClipboardManager) getActivity()
+ .getSystemService(Context.CLIPBOARD_SERVICE);
+ cm.setPrimaryClip(clipData);
Toast t = Toast.makeText(getActivity(),
R.string.copied_url_msg, Toast.LENGTH_SHORT);
t.show();
@@ -558,7 +562,7 @@ public class ItemFragment extends Fragment implements OnSwipeGesture {
}
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
+ private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override
public void update(EventDistributor eventDistributor, Integer arg) {
if ((arg & EVENTS) != 0) {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
index a118673a6..83d6f9615 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
@@ -7,7 +7,6 @@ import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.LightingColorFilter;
-import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.support.v4.view.MenuItemCompat;
@@ -22,7 +21,6 @@ import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageButton;
import android.widget.ImageView;
-import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
@@ -33,6 +31,7 @@ import com.joanzapata.iconify.Iconify;
import com.joanzapata.iconify.fonts.FontAwesomeIcons;
import com.joanzapata.iconify.widget.IconTextView;
+import de.danoeh.antennapod.activity.FeedSettingsActivity;
import org.apache.commons.lang3.Validate;
import java.util.List;
@@ -89,9 +88,9 @@ public class ItemlistFragment extends ListFragment {
| EventDistributor.PLAYER_STATUS_UPDATE;
public static final String EXTRA_SELECTED_FEEDITEM = "extra.de.danoeh.antennapod.activity.selected_feeditem";
- public static final String ARGUMENT_FEED_ID = "argument.de.danoeh.antennapod.feed_id";
+ private static final String ARGUMENT_FEED_ID = "argument.de.danoeh.antennapod.feed_id";
- protected FeedItemlistAdapter adapter;
+ private FeedItemlistAdapter adapter;
private ContextMenu contextMenu;
private AdapterView.AdapterContextMenuInfo lastMenuInfo = null;
@@ -223,13 +222,6 @@ public class ItemlistFragment extends ListFragment {
menu.findItem(R.id.share_link_item).setVisible(false);
menu.findItem(R.id.visit_website_item).setVisible(false);
}
- int[] attrs = { R.attr.action_bar_icon_color };
- TypedArray ta = getActivity().obtainStyledAttributes(UserPreferences.getTheme(), attrs);
- int textColor = ta.getColor(0, Color.GRAY);
- ta.recycle();
-
- menu.findItem(R.id.episode_actions).setIcon(new IconDrawable(getActivity(),
- FontAwesomeIcons.fa_gears).color(textColor).actionBarSize());
isUpdatingFeed = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
}
@@ -342,22 +334,7 @@ public class ItemlistFragment extends ListFragment {
return super.onContextItemSelected(item);
}
- try {
- return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
- } catch (DownloadRequestException e) {
- // context menu doesn't contain download functionality
- return true;
- }
- }
-
-
- @Override
- public void setListAdapter(ListAdapter adapter) {
- // This workaround prevents the ListFragment from setting a list adapter when its state is restored.
- // This is only necessary on API 10 because addFooterView throws an internal exception in this case.
- if (Build.VERSION.SDK_INT > 10 || insideOnFragmentLoaded) {
- super.setListAdapter(adapter);
- }
+ return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
}
@Override
@@ -417,7 +394,7 @@ public class ItemlistFragment extends ListFragment {
}
}
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
+ private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override
public void update(EventDistributor eventDistributor, Integer arg) {
@@ -514,6 +491,7 @@ public class ItemlistFragment extends ListFragment {
imgvBackground = (ImageView) header.findViewById(R.id.imgvBackground);
imgvCover = (ImageView) header.findViewById(R.id.imgvCover);
ImageButton butShowInfo = (ImageButton) header.findViewById(R.id.butShowInfo);
+ ImageButton butShowSettings = (ImageButton) header.findViewById(R.id.butShowSettings);
txtvInformation = (TextView) header.findViewById(R.id.txtvInformation);
txtvFailure = (IconTextView) header.findViewById(R.id.txtvFailure);
@@ -526,10 +504,12 @@ public class ItemlistFragment extends ListFragment {
loadFeedImage();
- butShowInfo.setOnClickListener(v -> {
+ butShowInfo.setOnClickListener(v -> showFeedInfo());
+ imgvCover.setOnClickListener(v -> showFeedInfo());
+ butShowSettings.setOnClickListener(v -> {
if (viewsCreated && itemsLoaded) {
- Intent startIntent = new Intent(getActivity(), FeedInfoActivity.class);
- startIntent.putExtra(FeedInfoActivity.EXTRA_FEED_ID,
+ Intent startIntent = new Intent(getActivity(), FeedSettingsActivity.class);
+ startIntent.putExtra(FeedSettingsActivity.EXTRA_FEED_ID,
feed.getId());
startActivity(startIntent);
}
@@ -537,6 +517,15 @@ public class ItemlistFragment extends ListFragment {
headerCreated = true;
}
+ private void showFeedInfo() {
+ if (viewsCreated && itemsLoaded) {
+ Intent startIntent = new Intent(getActivity(), FeedInfoActivity.class);
+ startIntent.putExtra(FeedInfoActivity.EXTRA_FEED_ID,
+ feed.getId());
+ startActivity(startIntent);
+ }
+ }
+
private void loadFeedImage() {
Glide.with(getActivity())
.load(feed.getImageLocation())
@@ -583,7 +572,7 @@ public class ItemlistFragment extends ListFragment {
}
}
- private FeedItemlistAdapter.ItemAccess itemAccess = new FeedItemlistAdapter.ItemAccess() {
+ private final FeedItemlistAdapter.ItemAccess itemAccess = new FeedItemlistAdapter.ItemAccess() {
@Override
public FeedItem getItem(int position) {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java
index 43dedad25..08610c1f3 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java
@@ -75,7 +75,7 @@ public class ItunesSearchFragment extends Fragment {
* Replace adapter data with provided search results from SearchTask.
* @param result List of Podcast objects containing search results
*/
- void updateData(List<Podcast> result) {
+ private void updateData(List<Podcast> result) {
this.searchResults = result;
adapter.clear();
if (result != null && result.size() > 0) {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
index 183c10f3d..6695ba427 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
@@ -1,14 +1,10 @@
package de.danoeh.antennapod.fragment;
import android.os.Bundle;
-import android.os.Handler;
-import android.support.design.widget.Snackbar;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.LayoutInflater;
-import android.view.Menu;
-import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
@@ -18,10 +14,7 @@ import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter;
import de.danoeh.antennapod.core.event.FeedItemEvent;
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.storage.DBReader;
-import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.FeedItemUtil;
@@ -76,33 +69,7 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
AllEpisodesRecycleAdapter.Holder holder = (AllEpisodesRecycleAdapter.Holder)viewHolder;
-
- Log.d(TAG, "remove(" + holder.getItemId() + ")");
- if (subscription != null) {
- subscription.unsubscribe();
- }
- FeedItem item = holder.getFeedItem();
- // we're marking it as unplayed since the user didn't actually play it
- // but they don't want it considered 'NEW' anymore
- DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId());
-
- final Handler h = new Handler(getActivity().getMainLooper());
- final Runnable r = () -> {
- FeedMedia media = item.getMedia();
- if (media != null && media.hasAlmostEnded() && UserPreferences.isAutoDelete()) {
- DBWriter.deleteFeedMediaOfItem(getActivity(), media.getId());
- }
- };
-
- Snackbar snackbar = Snackbar.make(root, getString(R.string.marked_as_seen_label),
- Snackbar.LENGTH_LONG);
- snackbar.setAction(getString(R.string.undo), v -> {
- DBWriter.markItemPlayed(FeedItem.NEW, item.getId());
- // don't forget to cancel the thing that's going to remove the media
- h.removeCallbacks(r);
- });
- snackbar.show();
- h.postDelayed(r, (int)Math.ceil(snackbar.getDuration() * 1.05f));
+ markItemAsSeenWithUndo(holder.getFeedItem());
}
@Override
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
index 441f0096c..fb6280021 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
@@ -199,7 +199,7 @@ public class PlaybackHistoryFragment extends ListFragment {
}
}
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
+ private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override
public void update(EventDistributor eventDistributor, Integer arg) {
@@ -224,7 +224,7 @@ public class PlaybackHistoryFragment extends ListFragment {
getActivity().supportInvalidateOptionsMenu();
}
- private FeedItemlistAdapter.ItemAccess itemAccess = new FeedItemlistAdapter.ItemAccess() {
+ private final FeedItemlistAdapter.ItemAccess itemAccess = new FeedItemlistAdapter.ItemAccess() {
@Override
public int getItemDownloadProgressPercent(FeedItem item) {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
index fccb86076..f5fdd4f9c 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
@@ -21,7 +21,6 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
-import android.widget.Toast;
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
@@ -46,7 +45,6 @@ import de.danoeh.antennapod.core.service.download.Downloader;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
-import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.Converter;
import de.danoeh.antennapod.core.util.FeedItemUtil;
@@ -109,7 +107,6 @@ public class QueueFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
- recyclerView.setAdapter(recyclerAdapter);
loadItems(true);
EventDistributor.getInstance().register(contentUpdate);
EventBus.getDefault().registerSticky(this);
@@ -328,6 +325,15 @@ public class QueueFragment extends Fragment {
case R.id.queue_sort_feed_title_desc:
QueueSorter.sort(getActivity(), QueueSorter.Rule.FEED_TITLE_DESC, true);
return true;
+ case R.id.queue_sort_random:
+ QueueSorter.sort(getActivity(), QueueSorter.Rule.RANDOM, true);
+ return true;
+ case R.id.queue_sort_smart_shuffle_asc:
+ QueueSorter.sort(getActivity(), QueueSorter.Rule.SMART_SHUFFLE_ASC, true);
+ return true;
+ case R.id.queue_sort_smart_shuffle_desc:
+ QueueSorter.sort(getActivity(), QueueSorter.Rule.SMART_SHUFFLE_DESC, true);
+ return true;
default:
return false;
}
@@ -363,13 +369,7 @@ public class QueueFragment extends Fragment {
DBWriter.moveQueueItemToBottom(selectedItem.getId(), true);
return true;
default:
- try {
- return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
- return true;
- }
+ return FeedItemMenuHandler.onMenuItemClicked(getActivity(), item.getItemId(), selectedItem);
}
}
@@ -395,17 +395,29 @@ public class QueueFragment extends Fragment {
itemTouchHelper = new ItemTouchHelper(
new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.RIGHT) {
+ // Position tracking whilst dragging
+ int dragFrom = -1;
+ int dragTo = -1;
+
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
+ int fromPosition = viewHolder.getAdapterPosition();
+ int toPosition = target.getAdapterPosition();
+
+ // Update tracked position
+ if(dragFrom == -1) {
+ dragFrom = fromPosition;
+ }
+ dragTo = toPosition;
+
int from = viewHolder.getAdapterPosition();
int to = target.getAdapterPosition();
- Log.d(TAG, "move(" + from + ", " + to + ")");
+ Log.d(TAG, "move(" + from + ", " + to + ") in memory");
if(from >= queue.size() || to >= queue.size()) {
return false;
}
queue.add(to, queue.remove(from));
recyclerAdapter.notifyItemMoved(from, to);
- DBWriter.moveQueueItem(from, to, true);
return true;
}
@@ -459,12 +471,25 @@ public class QueueFragment extends Fragment {
RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
+ // Check if drag finished
+ if(dragFrom != -1 && dragTo != -1 && dragFrom != dragTo) {
+ reallyMoved(dragFrom, dragTo);
+ }
+
+ dragFrom = dragTo = -1;
+
if (viewHolder instanceof QueueRecyclerAdapter.ItemTouchHelperViewHolder) {
QueueRecyclerAdapter.ItemTouchHelperViewHolder itemViewHolder =
(QueueRecyclerAdapter.ItemTouchHelperViewHolder) viewHolder;
itemViewHolder.onItemClear();
}
}
+
+ private void reallyMoved(int from, int to) {
+ // Write drag operation to database
+ Log.d(TAG, "Write to database move(" + dragFrom + ", " + dragTo + ")");
+ DBWriter.moveQueueItem(dragFrom, dragTo, true);
+ }
}
);
itemTouchHelper.attachToRecyclerView(recyclerView);
@@ -507,19 +532,23 @@ public class QueueFragment extends Fragment {
private void refreshInfoBar() {
String info = queue.size() + getString(R.string.episodes_suffix);
if(queue.size() > 0) {
- long duration = 0;
+ long timeLeft = 0;
+ float playbackSpeed = Float.valueOf(UserPreferences.getPlaybackSpeed());
for(FeedItem item : queue) {
if(item.getMedia() != null) {
- duration += item.getMedia().getDuration();
+ timeLeft +=
+ (item.getMedia().getDuration() - item.getMedia().getPosition())
+ / playbackSpeed;
}
}
info += " \u2022 ";
- info += Converter.getDurationStringLocalized(getActivity(), duration);
+ info += getString(R.string.time_left_label);
+ info += Converter.getDurationStringLocalized(getActivity(), timeLeft);
}
infoBar.setText(info);
}
- private QueueRecyclerAdapter.ItemAccess itemAccess = new QueueRecyclerAdapter.ItemAccess() {
+ private final QueueRecyclerAdapter.ItemAccess itemAccess = new QueueRecyclerAdapter.ItemAccess() {
@Override
public int getCount() {
return queue != null ? queue.size() : 0;
@@ -579,7 +608,7 @@ public class QueueFragment extends Fragment {
}
};
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
+ private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override
public void update(EventDistributor eventDistributor, Integer arg) {
if ((arg & EVENTS) != 0) {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java
index ba526edb3..66c59b7f7 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/RunningDownloadsFragment.java
@@ -75,7 +75,7 @@ public class RunningDownloadsFragment extends ListFragment {
}
- private DownloadlistAdapter.ItemAccess itemAccess = new DownloadlistAdapter.ItemAccess() {
+ private final DownloadlistAdapter.ItemAccess itemAccess = new DownloadlistAdapter.ItemAccess() {
@Override
public int getCount() {
return (downloaderList != null) ? downloaderList.size() : 0;
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
index 9626e6c2e..aec2bb536 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
@@ -16,6 +16,7 @@ import android.widget.GridView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
+import de.danoeh.antennapod.activity.MediaplayerInfoActivity;
import de.danoeh.antennapod.adapter.SubscriptionsAdapter;
import de.danoeh.antennapod.core.asynctask.FeedRemover;
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
@@ -26,6 +27,7 @@ import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.FeedItemUtil;
+import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.dialog.RenameFeedDialog;
import rx.Observable;
import rx.Subscription;
@@ -152,18 +154,39 @@ public class SubscriptionFragment extends Fragment {
Feed feed = (Feed)selectedObject;
switch(item.getItemId()) {
case R.id.mark_all_seen_item:
- Observable.fromCallable(() -> DBWriter.markFeedSeen(feed.getId()))
- .subscribeOn(Schedulers.newThread())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(result -> loadSubscriptions(),
- error -> Log.e(TAG, Log.getStackTraceString(error)));
+ ConfirmationDialog markAllSeenConfirmationDialog = new ConfirmationDialog(getActivity(),
+ R.string.mark_all_seen_label,
+ R.string.mark_all_seen_confirmation_msg) {
+
+ @Override
+ public void onConfirmButtonPressed(DialogInterface dialog) {
+ dialog.dismiss();
+
+ Observable.fromCallable(() -> DBWriter.markFeedSeen(feed.getId()))
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(result -> loadSubscriptions(),
+ error -> Log.e(TAG, Log.getStackTraceString(error)));
+ }
+ };
+ markAllSeenConfirmationDialog.createNewDialog().show();
return true;
case R.id.mark_all_read_item:
- Observable.fromCallable(() -> DBWriter.markFeedRead(feed.getId()))
- .subscribeOn(Schedulers.newThread())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(result -> loadSubscriptions(),
- error -> Log.e(TAG, Log.getStackTraceString(error)));
+ ConfirmationDialog markAllReadConfirmationDialog = new ConfirmationDialog(getActivity(),
+ R.string.mark_all_read_label,
+ R.string.mark_all_read_confirmation_msg) {
+
+ @Override
+ public void onConfirmButtonPressed(DialogInterface dialog) {
+ dialog.dismiss();
+ Observable.fromCallable(() -> DBWriter.markFeedRead(feed.getId()))
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(result -> loadSubscriptions(),
+ error -> Log.e(TAG, Log.getStackTraceString(error)));
+ }
+ };
+ markAllReadConfirmationDialog.createNewDialog().show();
return true;
case R.id.rename_item:
new RenameFeedDialog(getActivity(), feed).show();
@@ -190,8 +213,8 @@ public class SubscriptionFragment extends Fragment {
remover.skipOnCompletion = true;
int playerStatus = PlaybackPreferences.getCurrentPlayerStatus();
if(playerStatus == PlaybackPreferences.PLAYER_STATUS_PLAYING) {
- getActivity().sendBroadcast(new Intent(
- PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE));
+ IntentUtils.sendLocalBroadcast(getContext(), PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE);
+
}
}
remover.executeAsync();
@@ -210,7 +233,7 @@ public class SubscriptionFragment extends Fragment {
loadSubscriptions();
}
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
+ private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override
public void update(EventDistributor eventDistributor, Integer arg) {
if ((EVENTS & arg) != 0) {
@@ -220,7 +243,7 @@ public class SubscriptionFragment extends Fragment {
}
};
- private SubscriptionsAdapter.ItemAccess itemAccess = new SubscriptionsAdapter.ItemAccess() {
+ private final SubscriptionsAdapter.ItemAccess itemAccess = new SubscriptionsAdapter.ItemAccess() {
@Override
public int getCount() {
if (navDrawerData != null) {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java
index aff5069c6..b48027668 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/GpodnetMainFragment.java
@@ -20,7 +20,7 @@ import de.danoeh.antennapod.R;
*/
public class GpodnetMainFragment extends Fragment {
- public static final String TAG = "GpodnetMainFragment";
+ private static final String TAG = "GpodnetMainFragment";
private static final String PREF_LAST_TAB_POSITION = "tab_position";
private TabLayout tabLayout;
@@ -71,7 +71,7 @@ public class GpodnetMainFragment extends Fragment {
private static final int POS_TAGS = 1;
private static final int POS_SUGGESTIONS = 2;
- Resources resources;
+ final Resources resources;
public GpodnetPagerAdapter(FragmentManager fm, Resources resources) {
super(fm);
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java
index 15e9c9943..055358c64 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java
@@ -91,7 +91,7 @@ public abstract class PodcastListFragment extends Fragment {
return root;
}
- protected void onPodcastSelected(GpodnetPodcast selection) {
+ private void onPodcastSelected(GpodnetPodcast selection) {
Log.d(TAG, "Selected podcast: " + selection.toString());
Intent intent = new Intent(getActivity(), OnlineFeedViewActivity.class);
intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, selection.getUrl());
@@ -101,7 +101,7 @@ public abstract class PodcastListFragment extends Fragment {
protected abstract List<GpodnetPodcast> loadPodcastData(GpodnetService service) throws GpodnetServiceException;
- protected final void loadData() {
+ final void loadData() {
AsyncTask<Void, Void, List<GpodnetPodcast>> loaderTask = new AsyncTask<Void, Void, List<GpodnetPodcast>>() {
volatile Exception exception = null;
@@ -160,10 +160,6 @@ public abstract class PodcastListFragment extends Fragment {
}
};
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- loaderTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
- loaderTask.execute();
- }
+ loaderTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastTopListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastTopListFragment.java
index 33a35fa90..4f963756c 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastTopListFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastTopListFragment.java
@@ -1,11 +1,11 @@
package de.danoeh.antennapod.fragment.gpodnet;
+import java.util.List;
+
import de.danoeh.antennapod.core.gpoddernet.GpodnetService;
import de.danoeh.antennapod.core.gpoddernet.GpodnetServiceException;
import de.danoeh.antennapod.core.gpoddernet.model.GpodnetPodcast;
-import java.util.List;
-
/**
*
*/
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java
index 613e06805..10bd636dd 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SearchListFragment.java
@@ -73,7 +73,7 @@ public class SearchListFragment extends PodcastListFragment {
return service.searchPodcasts(query, 0);
}
- public void changeQuery(String query) {
+ private void changeQuery(String query) {
Validate.notNull(query);
this.query = query;
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java
index d2c7f32dd..1e46b1ac5 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java
@@ -135,11 +135,7 @@ public class TagListFragment extends ListFragment {
}
}
};
- if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
- loadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- } else {
- loadTask.execute();
- }
+ loadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
index 57b7c359c..ffdfa9516 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
@@ -17,7 +17,7 @@ import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.service.playback.PlaybackService;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DBWriter;
-import de.danoeh.antennapod.core.storage.DownloadRequestException;
+import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.ShareUtils;
@@ -87,7 +87,7 @@ public class FeedItemMenuHandler {
mi.setItemVisibility(R.id.add_to_queue_item, false);
}
- if (!showExtendedMenu || selectedItem.getLink() == null) {
+ if (!showExtendedMenu || !ShareUtils.hasLinkToShare(selectedItem)) {
mi.setItemVisibility(R.id.visit_website_item, false);
mi.setItemVisibility(R.id.share_link_item, false);
mi.setItemVisibility(R.id.share_link_with_position_item, false);
@@ -155,10 +155,10 @@ public class FeedItemMenuHandler {
}
public static boolean onMenuItemClicked(Context context, int menuItemId,
- FeedItem selectedItem) throws DownloadRequestException {
+ FeedItem selectedItem) {
switch (menuItemId) {
case R.id.skip_episode_item:
- context.sendBroadcast(new Intent(PlaybackService.ACTION_SKIP_CURRENT_EPISODE));
+ IntentUtils.sendLocalBroadcast(context, PlaybackService.ACTION_SKIP_CURRENT_EPISODE);
break;
case R.id.remove_item:
DBWriter.deleteFeedMediaOfItem(context, selectedItem.getMedia().getId());
@@ -217,7 +217,7 @@ public class FeedItemMenuHandler {
DBWriter.setFeedItemAutoDownload(selectedItem, false);
break;
case R.id.visit_website_item:
- Uri uri = Uri.parse(selectedItem.getLink());
+ Uri uri = Uri.parse(FeedItemUtil.getLinkWithFallback(selectedItem));
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
if(IntentUtils.isCallable(context, intent)) {
context.startActivity(intent);
diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java
index ac703e13e..66e229bdd 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java
@@ -20,7 +20,8 @@ public class MenuItemUtils extends de.danoeh.antennapod.core.menuhandler.MenuIte
public static void adjustTextColor(Context context, SearchView sv) {
if(Build.VERSION.SDK_INT < 14) {
EditText searchEditText = (EditText) sv.findViewById(R.id.search_src_text);
- if(UserPreferences.getTheme() == de.danoeh.antennapod.R.style.Theme_AntennaPod_Dark) {
+ if (UserPreferences.getTheme() == de.danoeh.antennapod.R.style.Theme_AntennaPod_Dark
+ || UserPreferences.getTheme() == R.style.Theme_AntennaPod_TrueBlack) {
searchEditText.setTextColor(Color.WHITE);
} else {
searchEditText.setTextColor(Color.BLACK);
diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/MasterSwitchPreference.java b/app/src/main/java/de/danoeh/antennapod/preferences/MasterSwitchPreference.java
new file mode 100644
index 000000000..e500267fe
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/preferences/MasterSwitchPreference.java
@@ -0,0 +1,47 @@
+package de.danoeh.antennapod.preferences;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.graphics.Typeface;
+import android.os.Build;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.PreferenceViewHolder;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.widget.TextView;
+import de.danoeh.antennapod.R;
+
+public class MasterSwitchPreference extends SwitchPreference {
+
+ public MasterSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ public MasterSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ public MasterSwitchPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public MasterSwitchPreference(Context context) {
+ super(context);
+ }
+
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+
+ TypedValue typedValue = new TypedValue();
+ getContext().getTheme().resolveAttribute(R.attr.master_switch_background, typedValue, true);
+ holder.itemView.setBackgroundColor(typedValue.data);
+
+ TextView title = (TextView) holder.findViewById(android.R.id.title);
+ if (title != null) {
+ title.setTypeface(title.getTypeface(), Typeface.BOLD);
+ }
+ }
+} \ No newline at end of file
diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/NumberPickerPreference.java b/app/src/main/java/de/danoeh/antennapod/preferences/NumberPickerPreference.java
new file mode 100644
index 000000000..20b07e486
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/preferences/NumberPickerPreference.java
@@ -0,0 +1,106 @@
+package de.danoeh.antennapod.preferences;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.text.InputFilter;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.EditText;
+import de.danoeh.antennapod.R;
+
+public class NumberPickerPreference extends Preference {
+ private Context context;
+ private int defaultValue = 0;
+ private int minValue = 0;
+ private int maxValue = Integer.MAX_VALUE;
+
+ public NumberPickerPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ init(context, attrs);
+ }
+
+ public NumberPickerPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(context, attrs);
+ }
+
+ public NumberPickerPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context, attrs);
+ }
+
+ public NumberPickerPreference(Context context) {
+ super(context);
+ this.context = context;
+ }
+
+ private void init(Context context, AttributeSet attrs) {
+ this.context = context;
+
+ for (int i = 0; i < attrs.getAttributeCount(); i++) {
+ String name = attrs.getAttributeName(i);
+ String value = attrs.getAttributeValue(i);
+ switch (name) {
+ case "defaultValue":
+ defaultValue = Integer.parseInt(value);
+ break;
+ case "minValue":
+ minValue = Integer.parseInt(value);
+ break;
+ case "maxValue":
+ maxValue = Integer.parseInt(value);
+ break;
+ }
+ }
+ }
+
+ @Override
+ protected void onClick() {
+ super.onClick();
+
+ View view = View.inflate(context, R.layout.numberpicker, null);
+ EditText number = view.findViewById(R.id.number);
+ number.setText(getSharedPreferences().getString(getKey(), ""+defaultValue));
+ number.setFilters(new InputFilter[]{(source, start, end, dest, dstart, dend) -> {
+ try {
+ String newVal = dest.toString().substring(0, dstart) + dest.toString().substring(dend);
+ newVal = newVal.substring(0, dstart) + source.toString() + newVal.substring(dstart);
+ int input = Integer.parseInt(newVal);
+ if (input >= minValue && input <= maxValue) {
+ return null;
+ }
+ } catch (NumberFormatException nfe) {
+ nfe.printStackTrace();
+ }
+ return "";
+ }});
+
+ AlertDialog dialog = new AlertDialog.Builder(context)
+ .setTitle(getTitle())
+ .setView(view)
+ .setNegativeButton(android.R.string.cancel, null)
+ .setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
+ try {
+ String numberString = number.getText().toString();
+ int value = Integer.parseInt(numberString);
+
+ if (value < minValue || value > maxValue) {
+ return;
+ }
+
+ getSharedPreferences().edit().putString(getKey(), "" + value).apply();
+
+ if (getOnPreferenceChangeListener() != null) {
+ getOnPreferenceChangeListener().onPreferenceChange(this, value);
+ }
+ } catch (NumberFormatException e) {
+ // Do not set value
+ }
+ })
+ .create();
+ dialog.show();
+ dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
index 1ca0d0109..e1fcc43c5 100644
--- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
+++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
@@ -16,29 +16,44 @@ import android.net.Uri;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Build;
-import android.preference.CheckBoxPreference;
-import android.preference.EditTextPreference;
-import android.preference.ListPreference;
-import android.preference.Preference;
-import android.preference.PreferenceManager;
-import android.preference.PreferenceScreen;
+import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
-import android.support.v4.content.ContextCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AlertDialog;
-import android.text.Editable;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.preference.CheckBoxPreference;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceFragmentCompat;
+import android.support.v7.preference.PreferenceManager;
+import android.support.v7.preference.PreferenceScreen;
import android.text.Html;
-import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
import android.util.Log;
-import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;
import com.afollestad.materialdialogs.MaterialDialog;
+import com.bytehamster.lib.preferencesearch.SearchConfiguration;
+import com.bytehamster.lib.preferencesearch.SearchPreference;
+import de.danoeh.antennapod.activity.AboutActivity;
+import de.danoeh.antennapod.activity.ImportExportActivity;
+import de.danoeh.antennapod.activity.MediaplayerActivity;
+import de.danoeh.antennapod.activity.OpmlImportFromPathActivity;
+import de.danoeh.antennapod.activity.PreferenceActivity;
+import de.danoeh.antennapod.activity.StatisticsActivity;
+import de.danoeh.antennapod.core.export.html.HtmlWriter;
+import de.danoeh.antennapod.core.export.opml.OpmlWriter;
+import de.danoeh.antennapod.core.service.GpodnetSyncService;
+import de.danoeh.antennapod.dialog.AuthenticationDialog;
+import de.danoeh.antennapod.dialog.AutoFlattrPreferenceDialog;
+import de.danoeh.antennapod.dialog.GpodnetSetHostnameDialog;
+import de.danoeh.antennapod.dialog.ProxyDialog;
+import de.danoeh.antennapod.dialog.VariableSpeedDialog;
+import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil;
import org.apache.commons.lang3.ArrayUtils;
import java.io.File;
@@ -46,40 +61,27 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
-import java.util.Comparator;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.CrashReportWriter;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.AboutActivity;
import de.danoeh.antennapod.activity.DirectoryChooserActivity;
import de.danoeh.antennapod.activity.MainActivity;
-import de.danoeh.antennapod.activity.MediaplayerActivity;
-import de.danoeh.antennapod.activity.PreferenceActivity;
-import de.danoeh.antennapod.activity.PreferenceActivityGingerbread;
-import de.danoeh.antennapod.activity.StatisticsActivity;
import de.danoeh.antennapod.asynctask.ExportWorker;
-import de.danoeh.antennapod.core.BuildConfig;
import de.danoeh.antennapod.core.export.ExportWriter;
-import de.danoeh.antennapod.core.export.html.HtmlWriter;
-import de.danoeh.antennapod.core.export.opml.OpmlWriter;
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.service.GpodnetSyncService;
import de.danoeh.antennapod.core.util.flattr.FlattrUtils;
-import de.danoeh.antennapod.dialog.AuthenticationDialog;
-import de.danoeh.antennapod.dialog.AutoFlattrPreferenceDialog;
import de.danoeh.antennapod.dialog.ChooseDataFolderDialog;
-import de.danoeh.antennapod.dialog.GpodnetSetHostnameDialog;
-import de.danoeh.antennapod.dialog.ProxyDialog;
-import de.danoeh.antennapod.dialog.VariableSpeedDialog;
import rx.Observable;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
+import static de.danoeh.antennapod.activity.PreferenceActivity.PARAM_RESOURCE;
+
/**
* Sets up a preference UI that lets the user change user preferences.
*/
@@ -88,19 +90,28 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
private static final String TAG = "PreferenceController";
- private static final String PREF_FLATTR_SETTINGS = "prefFlattrSettings";
+ private static final String PREF_SCREEN_USER_INTERFACE = "prefScreenInterface";
+ private static final String PREF_SCREEN_PLAYBACK = "prefScreenPlayback";
+ private static final String PREF_SCREEN_NETWORK = "prefScreenNetwork";
+ private static final String PREF_SCREEN_INTEGRATIONS = "prefScreenIntegrations";
+ private static final String PREF_SCREEN_STORAGE = "prefScreenStorage";
+ private static final String PREF_SCREEN_AUTODL = "prefAutoDownloadSettings";
+ private static final String PREF_SCREEN_FLATTR = "prefFlattrSettings";
+ private static final String PREF_SCREEN_GPODDER = "prefGpodderSettings";
+
private static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate";
private static final String PREF_FLATTR_REVOKE = "prefRevokeAccess";
private static final String PREF_AUTO_FLATTR_PREFS = "prefAutoFlattrPrefs";
private static final String PREF_OPML_EXPORT = "prefOpmlExport";
+ private static final String PREF_OPML_IMPORT = "prefOpmlImport";
private static final String PREF_HTML_EXPORT = "prefHtmlExport";
private static final String STATISTICS = "statistics";
+ private static final String IMPORT_EXPORT = "importExport";
private static final String PREF_ABOUT = "prefAbout";
private static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir";
- private static final String AUTO_DL_PREF_SCREEN = "prefAutoDownloadSettings";
private static final String PREF_PLAYBACK_SPEED_LAUNCHER = "prefPlaybackSpeedLauncher";
- public static final String PREF_PLAYBACK_REWIND_DELTA_LAUNCHER = "prefPlaybackRewindDeltaLauncher";
- public static final String PREF_PLAYBACK_FAST_FORWARD_DELTA_LAUNCHER = "prefPlaybackFastForwardDeltaLauncher";
+ private static final String PREF_PLAYBACK_REWIND_DELTA_LAUNCHER = "prefPlaybackRewindDeltaLauncher";
+ private static final String PREF_PLAYBACK_FAST_FORWARD_DELTA_LAUNCHER = "prefPlaybackFastForwardDeltaLauncher";
private static final String PREF_GPODNET_LOGIN = "pref_gpodnet_authenticate";
private static final String PREF_GPODNET_SETLOGIN_INFORMATION = "pref_gpodnet_setlogin_information";
private static final String PREF_GPODNET_SYNC = "pref_gpodnet_sync";
@@ -134,30 +145,51 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
.registerOnSharedPreferenceChangeListener(this);
}
- /**
- * Returns the preference activity that should be used on this device.
- *
- * @return PreferenceActivity if the API level is greater than 10, PreferenceActivityGingerbread otherwise.
- */
- public static Class<? extends Activity> getPreferenceActivity() {
- if (Build.VERSION.SDK_INT > 10) {
- return PreferenceActivity.class;
- } else {
- return PreferenceActivityGingerbread.class;
- }
- }
-
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- if(key.equals(UserPreferences.PREF_SONIC)) {
- CheckBoxPreference prefSonic = (CheckBoxPreference) ui.findPreference(UserPreferences.PREF_SONIC);
- if(prefSonic != null) {
- prefSonic.setChecked(sharedPreferences.getBoolean(UserPreferences.PREF_SONIC, false));
- }
+
+ }
+
+
+
+ public void onCreate(int screen) {
+ switch (screen) {
+ case R.xml.preferences:
+ setupMainScreen();
+ break;
+ case R.xml.preferences_network:
+ setupNetworkScreen();
+ break;
+ case R.xml.preferences_autodownload:
+ setupAutoDownloadScreen();
+ buildAutodownloadSelectedNetworksPreference();
+ setSelectedNetworksEnabled(UserPreferences.isEnableAutodownloadWifiFilter());
+ buildEpisodeCleanupPreference();
+ break;
+ case R.xml.preferences_playback:
+ setupPlaybackScreen();
+ PreferenceControllerFlavorHelper.setupFlavoredUI(ui);
+ buildSmartMarkAsPlayedPreference();
+ break;
+ case R.xml.preferences_integrations:
+ setupIntegrationsScreen();
+ break;
+ case R.xml.preferences_flattr:
+ setupFlattrScreen();
+ break;
+ case R.xml.preferences_gpodder:
+ setupGpodderScreen();
+ break;
+ case R.xml.preferences_storage:
+ setupStorageScreen();
+ break;
+ case R.xml.preferences_user_interface:
+ setupInterfaceScreen();
+ break;
}
}
- public void onCreate() {
+ private void setupInterfaceScreen() {
final Activity activity = ui.getActivity();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
@@ -172,22 +204,40 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
}
);
}
- ui.findPreference(PreferenceController.PREF_FLATTR_REVOKE).setOnPreferenceClickListener(
- preference -> {
- FlattrUtils.revokeAccessToken(activity);
- checkItemVisibility();
+ ui.findPreference(UserPreferences.PREF_THEME)
+ .setOnPreferenceChangeListener(
+ (preference, newValue) -> {
+ Intent i = new Intent(activity, MainActivity.class);
+ i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK
+ | Intent.FLAG_ACTIVITY_NEW_TASK);
+ activity.finish();
+ activity.startActivity(i);
+ return true;
+ }
+ );
+ ui.findPreference(UserPreferences.PREF_HIDDEN_DRAWER_ITEMS)
+ .setOnPreferenceClickListener(preference -> {
+ showDrawerPreferencesDialog();
return true;
- }
- );
- ui.findPreference(PreferenceController.PREF_ABOUT).setOnPreferenceClickListener(
- preference -> {
- activity.startActivity(new Intent(activity, AboutActivity.class));
+ });
+
+ ui.findPreference(UserPreferences.PREF_COMPACT_NOTIFICATION_BUTTONS)
+ .setOnPreferenceClickListener(preference -> {
+ showNotificationButtonsDialog();
return true;
- }
- );
- ui.findPreference(PreferenceController.STATISTICS).setOnPreferenceClickListener(
+ });
+
+ if (Build.VERSION.SDK_INT >= 26) {
+ ui.findPreference(UserPreferences.PREF_EXPANDED_NOTIFICATION).setVisible(false);
+ }
+ }
+
+ private void setupStorageScreen() {
+ final Activity activity = ui.getActivity();
+
+ ui.findPreference(PreferenceController.IMPORT_EXPORT).setOnPreferenceClickListener(
preference -> {
- activity.startActivity(new Intent(activity, StatisticsActivity.class));
+ activity.startActivity(new Intent(activity, ImportExportActivity.class));
return true;
}
);
@@ -195,6 +245,11 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
preference -> export(new OpmlWriter()));
ui.findPreference(PreferenceController.PREF_HTML_EXPORT).setOnPreferenceClickListener(
preference -> export(new HtmlWriter()));
+ ui.findPreference(PreferenceController.PREF_OPML_IMPORT).setOnPreferenceClickListener(
+ preference -> {
+ activity.startActivity(new Intent(activity, OpmlImportFromPathActivity.class));
+ return true;
+ });
ui.findPreference(PreferenceController.PREF_CHOOSE_DATA_DIR).setOnPreferenceClickListener(
preference -> {
if (Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT &&
@@ -228,130 +283,70 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
return true;
}
);
- ui.findPreference(UserPreferences.PREF_THEME)
- .setOnPreferenceChangeListener(
- (preference, newValue) -> {
- Intent i = new Intent(activity, MainActivity.class);
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
- i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK
- | Intent.FLAG_ACTIVITY_NEW_TASK);
- } else {
- i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- }
- activity.finish();
- activity.startActivity(i);
- return true;
+ ui.findPreference(UserPreferences.PREF_IMAGE_CACHE_SIZE).setOnPreferenceChangeListener(
+ (preference, o) -> {
+ if (o instanceof String) {
+ int newValue = Integer.parseInt((String) o) * 1024 * 1024;
+ if (newValue != UserPreferences.getImageCacheSize()) {
+ AlertDialog.Builder dialog = new AlertDialog.Builder(ui.getActivity());
+ dialog.setTitle(android.R.string.dialog_alert_title);
+ dialog.setMessage(R.string.pref_restart_required);
+ dialog.setPositiveButton(android.R.string.ok, null);
+ dialog.show();
}
- );
- ui.findPreference(UserPreferences.PREF_HIDDEN_DRAWER_ITEMS)
- .setOnPreferenceClickListener(preference -> {
- showDrawerPreferencesDialog();
- return true;
- });
+ return true;
+ }
+ return false;
+ }
+ );
+ }
- ui.findPreference(UserPreferences.PREF_COMPACT_NOTIFICATION_BUTTONS)
- .setOnPreferenceClickListener(preference -> {
- showNotificationButtonsDialog();
+ private void setupIntegrationsScreen() {
+ final AppCompatActivity activity = ui.getActivity();
+
+ ui.findPreference(PREF_SCREEN_FLATTR).setOnPreferenceClickListener(preference -> {
+ openScreen(R.xml.preferences_flattr, activity);
+ return true;
+ });
+ ui.findPreference(PREF_SCREEN_GPODDER).setOnPreferenceClickListener(preference -> {
+ openScreen(R.xml.preferences_gpodder, activity);
+ return true;
+ });
+ }
+
+ private void setupFlattrScreen() {
+ final AppCompatActivity activity = ui.getActivity();
+
+ ui.findPreference(PreferenceController.PREF_FLATTR_REVOKE).setOnPreferenceClickListener(
+ preference -> {
+ FlattrUtils.revokeAccessToken(activity);
+ checkFlattrItemVisibility();
return true;
- });
+ }
+ );
- ui.findPreference(UserPreferences.PREF_UPDATE_INTERVAL)
+ ui.findPreference(PreferenceController.PREF_AUTO_FLATTR_PREFS)
.setOnPreferenceClickListener(preference -> {
- showUpdateIntervalTimePreferencesDialog();
- return true;
- });
+ AutoFlattrPreferenceDialog.newAutoFlattrPreferenceDialog(activity,
+ new AutoFlattrPreferenceDialog.AutoFlattrPreferenceDialogInterface() {
+ @Override
+ public void onCancelled() {
- ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL).setOnPreferenceChangeListener(
- (preference, newValue) -> {
- if (newValue instanceof Boolean) {
- boolean enabled = (Boolean) newValue;
- ui.findPreference(UserPreferences.PREF_EPISODE_CACHE_SIZE).setEnabled(enabled);
- ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_BATTERY).setEnabled(enabled);
- ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER).setEnabled(enabled);
- setSelectedNetworksEnabled(enabled && UserPreferences.isEnableAutodownloadWifiFilter());
- }
- return true;
- });
- ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER)
- .setOnPreferenceChangeListener(
- (preference, newValue) -> {
- if (newValue instanceof Boolean) {
- setSelectedNetworksEnabled((Boolean) newValue);
- return true;
- } else {
- return false;
- }
- }
- );
- ui.findPreference(UserPreferences.PREF_PARALLEL_DOWNLOADS)
- .setOnPreferenceChangeListener(
- (preference, o) -> {
- if (o instanceof String) {
- try {
- int value = Integer.parseInt((String) o);
- if (1 <= value && value <= 50) {
- setParallelDownloadsText(value);
- return true;
- }
- } catch (NumberFormatException e) {
- return false;
}
- }
- return false;
- }
- );
- // validate and set correct value: number of downloads between 1 and 50 (inclusive)
- final EditText ev = ((EditTextPreference) ui.findPreference(UserPreferences.PREF_PARALLEL_DOWNLOADS)).getEditText();
- ev.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- if (s.length() > 0) {
- try {
- int value = Integer.parseInt(s.toString());
- if (value <= 0) {
- ev.setText("1");
- } else if (value > 50) {
- ev.setText("50");
- }
- } catch (NumberFormatException e) {
- ev.setText("6");
- }
- ev.setSelection(ev.getText().length());
- }
- }
- });
- ui.findPreference(UserPreferences.PREF_EPISODE_CACHE_SIZE)
- .setOnPreferenceChangeListener(
- (preference, o) -> {
- if (o instanceof String) {
- setEpisodeCacheSizeText(UserPreferences.readEpisodeCacheSize((String) o));
- }
- return true;
- }
- );
- ui.findPreference(PreferenceController.PREF_PLAYBACK_SPEED_LAUNCHER)
- .setOnPreferenceClickListener(preference -> {
- VariableSpeedDialog.showDialog(activity);
- return true;
- });
- ui.findPreference(PreferenceController.PREF_PLAYBACK_REWIND_DELTA_LAUNCHER)
- .setOnPreferenceClickListener(preference -> {
- MediaplayerActivity.showSkipPreference(activity, MediaplayerActivity.SkipDirection.SKIP_REWIND);
- return true;
- });
- ui.findPreference(PreferenceController.PREF_PLAYBACK_FAST_FORWARD_DELTA_LAUNCHER)
- .setOnPreferenceClickListener(preference -> {
- MediaplayerActivity.showSkipPreference(activity, MediaplayerActivity.SkipDirection.SKIP_FORWARD);
+ @Override
+ public void onConfirmed(boolean autoFlattrEnabled, float autoFlattrValue) {
+ UserPreferences.setAutoFlattrSettings(autoFlattrEnabled, autoFlattrValue);
+ checkFlattrItemVisibility();
+ }
+ });
return true;
});
+ }
+
+ private void setupGpodderScreen() {
+ final AppCompatActivity activity = ui.getActivity();
+
ui.findPreference(PreferenceController.PREF_GPODNET_SETLOGIN_INFORMATION)
.setOnPreferenceClickListener(preference -> {
AuthenticationDialog dialog = new AuthenticationDialog(activity,
@@ -399,45 +394,127 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
GpodnetSetHostnameDialog.createDialog(activity).setOnDismissListener(dialog -> updateGpodnetPreferenceScreen());
return true;
});
+ }
- ui.findPreference(PreferenceController.PREF_AUTO_FLATTR_PREFS)
+ private void setupPlaybackScreen() {
+ final Activity activity = ui.getActivity();
+
+ ui.findPreference(PreferenceController.PREF_PLAYBACK_SPEED_LAUNCHER)
.setOnPreferenceClickListener(preference -> {
- AutoFlattrPreferenceDialog.newAutoFlattrPreferenceDialog(activity,
- new AutoFlattrPreferenceDialog.AutoFlattrPreferenceDialogInterface() {
- @Override
- public void onCancelled() {
+ VariableSpeedDialog.showDialog(activity);
+ return true;
+ });
+ ui.findPreference(PreferenceController.PREF_PLAYBACK_REWIND_DELTA_LAUNCHER)
+ .setOnPreferenceClickListener(preference -> {
+ MediaplayerActivity.showSkipPreference(activity, MediaplayerActivity.SkipDirection.SKIP_REWIND);
+ return true;
+ });
+ ui.findPreference(PreferenceController.PREF_PLAYBACK_FAST_FORWARD_DELTA_LAUNCHER)
+ .setOnPreferenceClickListener(preference -> {
+ MediaplayerActivity.showSkipPreference(activity, MediaplayerActivity.SkipDirection.SKIP_FORWARD);
+ return true;
+ });
+ if (!PictureInPictureUtil.supportsPictureInPicture(activity)) {
+ ListPreference behaviour = (ListPreference) ui.findPreference(UserPreferences.PREF_VIDEO_BEHAVIOR);
+ behaviour.setEntries(R.array.video_background_behavior_options_without_pip);
+ behaviour.setEntryValues(R.array.video_background_behavior_values_without_pip);
+ }
+ }
- }
+ private void setupAutoDownloadScreen() {
+ ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL).setOnPreferenceChangeListener(
+ (preference, newValue) -> {
+ if (newValue instanceof Boolean) {
+ checkAutodownloadItemVisibility((Boolean) newValue);
+ }
+ return true;
+ });
+ ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER)
+ .setOnPreferenceChangeListener(
+ (preference, newValue) -> {
+ if (newValue instanceof Boolean) {
+ setSelectedNetworksEnabled((Boolean) newValue);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ );
+ ui.findPreference(UserPreferences.PREF_EPISODE_CACHE_SIZE)
+ .setOnPreferenceChangeListener(
+ (preference, o) -> {
+ if (o instanceof String) {
+ setEpisodeCacheSizeText(UserPreferences.readEpisodeCacheSize((String) o));
+ }
+ return true;
+ }
+ );
+ }
- @Override
- public void onConfirmed(boolean autoFlattrEnabled, float autoFlattrValue) {
- UserPreferences.setAutoFlattrSettings(autoFlattrEnabled, autoFlattrValue);
- checkItemVisibility();
- }
- });
+ private void setupNetworkScreen() {
+ final AppCompatActivity activity = ui.getActivity();
+ ui.findPreference(PREF_SCREEN_AUTODL).setOnPreferenceClickListener(preference -> {
+ openScreen(R.xml.preferences_autodownload, activity);
+ return true;
+ });
+ ui.findPreference(UserPreferences.PREF_UPDATE_INTERVAL)
+ .setOnPreferenceClickListener(preference -> {
+ showUpdateIntervalTimePreferencesDialog();
return true;
});
- ui.findPreference(UserPreferences.PREF_IMAGE_CACHE_SIZE).setOnPreferenceChangeListener(
- (preference, o) -> {
- if (o instanceof String) {
- int newValue = Integer.parseInt((String) o) * 1024 * 1024;
- if (newValue != UserPreferences.getImageCacheSize()) {
- AlertDialog.Builder dialog = new AlertDialog.Builder(ui.getActivity());
- dialog.setTitle(android.R.string.dialog_alert_title);
- dialog.setMessage(R.string.pref_restart_required);
- dialog.setPositiveButton(android.R.string.ok, null);
- dialog.show();
+ ui.findPreference(UserPreferences.PREF_PARALLEL_DOWNLOADS)
+ .setOnPreferenceChangeListener(
+ (preference, o) -> {
+ if (o instanceof Integer) {
+ setParallelDownloadsText((Integer) o);
+ }
+ return true;
}
- return true;
- }
- return false;
- }
- );
+ );
+ // validate and set correct value: number of downloads between 1 and 50 (inclusive)
ui.findPreference(PREF_PROXY).setOnPreferenceClickListener(preference -> {
ProxyDialog dialog = new ProxyDialog(ui.getActivity());
dialog.createDialog().show();
return true;
});
+ }
+
+ private void setupMainScreen() {
+ final AppCompatActivity activity = ui.getActivity();
+ setupSearch();
+ ui.findPreference(PREF_SCREEN_USER_INTERFACE).setOnPreferenceClickListener(preference -> {
+ openScreen(R.xml.preferences_user_interface, activity);
+ return true;
+ });
+ ui.findPreference(PREF_SCREEN_PLAYBACK).setOnPreferenceClickListener(preference -> {
+ openScreen(R.xml.preferences_playback, activity);
+ return true;
+ });
+ ui.findPreference(PREF_SCREEN_NETWORK).setOnPreferenceClickListener(preference -> {
+ openScreen(R.xml.preferences_network, activity);
+ return true;
+ });
+ ui.findPreference(PREF_SCREEN_INTEGRATIONS).setOnPreferenceClickListener(preference -> {
+ openScreen(R.xml.preferences_integrations, activity);
+ return true;
+ });
+ ui.findPreference(PREF_SCREEN_STORAGE).setOnPreferenceClickListener(preference -> {
+ openScreen(R.xml.preferences_storage, activity);
+ return true;
+ });
+
+ ui.findPreference(PreferenceController.PREF_ABOUT).setOnPreferenceClickListener(
+ preference -> {
+ activity.startActivity(new Intent(activity, AboutActivity.class));
+ return true;
+ }
+ );
+ ui.findPreference(PreferenceController.STATISTICS).setOnPreferenceClickListener(
+ preference -> {
+ activity.startActivity(new Intent(activity, StatisticsActivity.class));
+ return true;
+ }
+ );
ui.findPreference(PREF_KNOWN_ISSUES).setOnPreferenceClickListener(preference -> {
openInBrowser("https://github.com/AntennaPod/AntennaPod/labels/bug");
return true;
@@ -469,11 +546,76 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
ui.getActivity().startActivity(Intent.createChooser(emailIntent, intentTitle));
return true;
});
- PreferenceControllerFlavorHelper.setupFlavoredUI(ui);
- buildEpisodeCleanupPreference();
- buildSmartMarkAsPlayedPreference();
- buildAutodownloadSelectedNetworsPreference();
- setSelectedNetworksEnabled(UserPreferences.isEnableAutodownloadWifiFilter());
+ }
+
+ private void setupSearch() {
+ final AppCompatActivity activity = ui.getActivity();
+
+ SearchPreference searchPreference = (SearchPreference) ui.findPreference("searchPreference");
+ SearchConfiguration config = searchPreference.getSearchConfiguration();
+ config.setActivity(activity);
+ config.setFragmentContainerViewId(R.id.content);
+ config.setBreadcrumbsEnabled(true);
+
+ config.index()
+ .addBreadcrumb(getTitleOfPage(R.xml.preferences_user_interface))
+ .addFile(R.xml.preferences_user_interface);
+ config.index()
+ .addBreadcrumb(getTitleOfPage(R.xml.preferences_playback))
+ .addFile(R.xml.preferences_playback);
+ config.index()
+ .addBreadcrumb(getTitleOfPage(R.xml.preferences_network))
+ .addFile(R.xml.preferences_network);
+ config.index()
+ .addBreadcrumb(getTitleOfPage(R.xml.preferences_storage))
+ .addFile(R.xml.preferences_storage);
+ config.index()
+ .addBreadcrumb(getTitleOfPage(R.xml.preferences_network))
+ .addBreadcrumb(R.string.automation)
+ .addBreadcrumb(getTitleOfPage(R.xml.preferences_autodownload))
+ .addFile(R.xml.preferences_autodownload);
+ config.index()
+ .addBreadcrumb(getTitleOfPage(R.xml.preferences_integrations))
+ .addBreadcrumb(getTitleOfPage(R.xml.preferences_gpodder))
+ .addFile(R.xml.preferences_gpodder);
+ config.index()
+ .addBreadcrumb(getTitleOfPage(R.xml.preferences_integrations))
+ .addBreadcrumb(getTitleOfPage(R.xml.preferences_flattr))
+ .addFile(R.xml.preferences_flattr);
+ }
+
+ public PreferenceFragmentCompat openScreen(int preferences, AppCompatActivity activity) {
+ PreferenceFragmentCompat prefFragment = new PreferenceActivity.MainFragment();
+ Bundle args = new Bundle();
+ args.putInt(PARAM_RESOURCE, preferences);
+ prefFragment.setArguments(args);
+ activity.getSupportFragmentManager().beginTransaction()
+ .replace(R.id.content, prefFragment)
+ .addToBackStack(TAG).commit();
+ return prefFragment;
+ }
+
+ public static int getTitleOfPage(int preferences) {
+ switch (preferences) {
+ case R.xml.preferences_network:
+ return R.string.network_pref;
+ case R.xml.preferences_autodownload:
+ return R.string.pref_automatic_download_title;
+ case R.xml.preferences_playback:
+ return R.string.playback_pref;
+ case R.xml.preferences_storage:
+ return R.string.storage_pref;
+ case R.xml.preferences_user_interface:
+ return R.string.user_interface_label;
+ case R.xml.preferences_integrations:
+ return R.string.integrations_label;
+ case R.xml.preferences_flattr:
+ return R.string.flattr_label;
+ case R.xml.preferences_gpodder:
+ return R.string.gpodnet_main_label;
+ default:
+ return R.string.settings_label;
+ }
}
private boolean export(ExportWriter exportWriter) {
@@ -488,8 +630,8 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
subscription = observable.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(output -> {
- alert.setTitle(R.string.opml_export_success_title);
- String message = context.getString(R.string.opml_export_success_sum) + output.toString();
+ alert.setTitle(R.string.export_success_title);
+ String message = context.getString(R.string.export_success_sum, output.toString());
alert.setMessage(message);
alert.setPositiveButton(R.string.send_label, (dialog, which) -> {
Uri fileUri = FileProvider.getUriForFile(context.getApplicationContext(),
@@ -515,7 +657,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
alert.setTitle(R.string.export_error_label);
alert.setMessage(error.getMessage());
alert.show();
- }, () -> progressDialog.dismiss());
+ }, progressDialog::dismiss);
return true;
}
@@ -529,22 +671,41 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
}
}
- public void onResume() {
- checkItemVisibility();
- setUpdateIntervalText();
- setParallelDownloadsText(UserPreferences.getParallelDownloads());
- setEpisodeCacheSizeText(UserPreferences.getEpisodeCacheSize());
- setDataFolderText();
- GpodnetPreferences.registerOnSharedPreferenceChangeListener(gpoddernetListener);
- updateGpodnetPreferenceScreen();
+ public void onResume(int screen) {
+ switch (screen) {
+ case R.xml.preferences_network:
+ setUpdateIntervalText();
+ setParallelDownloadsText(UserPreferences.getParallelDownloads());
+ break;
+ case R.xml.preferences_autodownload:
+ setEpisodeCacheSizeText(UserPreferences.getEpisodeCacheSize());
+ checkAutodownloadItemVisibility(UserPreferences.isEnableAutodownload());
+ break;
+ case R.xml.preferences_storage:
+ setDataFolderText();
+ break;
+ case R.xml.preferences_integrations:
+ setIntegrationsItemVisibility();
+ return;
+ case R.xml.preferences_flattr:
+ checkFlattrItemVisibility();
+ break;
+ case R.xml.preferences_gpodder:
+ GpodnetPreferences.registerOnSharedPreferenceChangeListener(gpoddernetListener);
+ updateGpodnetPreferenceScreen();
+ break;
+ case R.xml.preferences_playback:
+ checkSonicItemVisibility();
+ break;
+ }
}
- public void onPause() {
+ public void unregisterGpodnet() {
GpodnetPreferences.unregisterOnSharedPreferenceChangeListener(gpoddernetListener);
}
- public void onStop() {
- if(subscription != null) {
+ public void unsubscribeExportSubscription() {
+ if (subscription != null) {
subscription.unsubscribe();
}
}
@@ -698,27 +859,32 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
}
}
+ private void setIntegrationsItemVisibility() {
+ ui.findPreference(PreferenceController.PREF_SCREEN_FLATTR).setEnabled(FlattrUtils.hasAPICredentials());
+ }
+
@SuppressWarnings("deprecation")
- private void checkItemVisibility() {
+ private void checkFlattrItemVisibility() {
boolean hasFlattrToken = FlattrUtils.hasToken();
- ui.findPreference(PreferenceController.PREF_FLATTR_SETTINGS).setEnabled(FlattrUtils.hasAPICredentials());
ui.findPreference(PreferenceController.PREF_FLATTR_AUTH).setEnabled(!hasFlattrToken);
ui.findPreference(PreferenceController.PREF_FLATTR_REVOKE).setEnabled(hasFlattrToken);
ui.findPreference(PreferenceController.PREF_AUTO_FLATTR_PREFS).setEnabled(hasFlattrToken);
+ }
- boolean autoDownload = UserPreferences.isEnableAutodownload();
+ private void checkAutodownloadItemVisibility(boolean autoDownload) {
ui.findPreference(UserPreferences.PREF_EPISODE_CACHE_SIZE).setEnabled(autoDownload);
ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_BATTERY).setEnabled(autoDownload);
ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER).setEnabled(autoDownload);
+ ui.findPreference(UserPreferences.PREF_EPISODE_CLEANUP).setEnabled(autoDownload);
+ ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_MOBILE).setEnabled(autoDownload);
setSelectedNetworksEnabled(autoDownload && UserPreferences.isEnableAutodownloadWifiFilter());
+ }
- ui.findPreference(PREF_SEND_CRASH_REPORT).setEnabled(CrashReportWriter.getFile().exists());
-
- if (Build.VERSION.SDK_INT >= 16) {
- ui.findPreference(UserPreferences.PREF_SONIC).setEnabled(true);
- } else {
- Preference prefSonic = ui.findPreference(UserPreferences.PREF_SONIC);
- prefSonic.setSummary("[Android 4.1+]\n" + prefSonic.getSummary());
+ private void checkSonicItemVisibility() {
+ if (Build.VERSION.SDK_INT < 16) {
+ ListPreference p = (ListPreference) ui.findPreference(UserPreferences.PREF_MEDIA_PLAYER);
+ p.setEntries(R.array.media_player_options_no_sonic);
+ p.setEntryValues(R.array.media_player_values_no_sonic);
}
}
@@ -778,7 +944,11 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
}
}
- private void buildAutodownloadSelectedNetworsPreference() {
+ private static String blankIfNull(String val) {
+ return val == null ? "" : val;
+ }
+
+ private void buildAutodownloadSelectedNetworksPreference() {
final Activity activity = ui.getActivity();
if (selectedNetworks != null) {
@@ -788,67 +958,63 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
WifiManager wifiservice = (WifiManager) activity.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
List<WifiConfiguration> networks = wifiservice.getConfiguredNetworks();
- if (networks != null) {
- Collections.sort(networks, new Comparator<WifiConfiguration>() {
- @Override
- public int compare(WifiConfiguration x, WifiConfiguration y) {
- return x.SSID.compareTo(y.SSID);
+ if (networks == null) {
+ Log.e(TAG, "Couldn't get list of configure Wi-Fi networks");
+ return;
+ }
+ Collections.sort(networks, (x, y) ->
+ blankIfNull(x.SSID).compareTo(blankIfNull(y.SSID)));
+ selectedNetworks = new CheckBoxPreference[networks.size()];
+ List<String> prefValues = Arrays.asList(UserPreferences
+ .getAutodownloadSelectedNetworks());
+ PreferenceScreen prefScreen = ui.getPreferenceScreen();
+ Preference.OnPreferenceClickListener clickListener = preference -> {
+ if (preference instanceof CheckBoxPreference) {
+ String key = preference.getKey();
+ List<String> prefValuesList = new ArrayList<>(
+ Arrays.asList(UserPreferences
+ .getAutodownloadSelectedNetworks())
+ );
+ boolean newValue = ((CheckBoxPreference) preference)
+ .isChecked();
+ Log.d(TAG, "Selected network " + key + ". New state: " + newValue);
+
+ int index = prefValuesList.indexOf(key);
+ if (index >= 0 && !newValue) {
+ // remove network
+ prefValuesList.remove(index);
+ } else if (index < 0 && newValue) {
+ prefValuesList.add(key);
}
- });
- selectedNetworks = new CheckBoxPreference[networks.size()];
- List<String> prefValues = Arrays.asList(UserPreferences
- .getAutodownloadSelectedNetworks());
- PreferenceScreen prefScreen = (PreferenceScreen) ui.findPreference(PreferenceController.AUTO_DL_PREF_SCREEN);
- Preference.OnPreferenceClickListener clickListener = preference -> {
- if (preference instanceof CheckBoxPreference) {
- String key = preference.getKey();
- List<String> prefValuesList = new ArrayList<>(
- Arrays.asList(UserPreferences
- .getAutodownloadSelectedNetworks())
- );
- boolean newValue = ((CheckBoxPreference) preference)
- .isChecked();
- Log.d(TAG, "Selected network " + key + ". New state: " + newValue);
-
- int index = prefValuesList.indexOf(key);
- if (index >= 0 && !newValue) {
- // remove network
- prefValuesList.remove(index);
- } else if (index < 0 && newValue) {
- prefValuesList.add(key);
- }
- UserPreferences.setAutodownloadSelectedNetworks(
- prefValuesList.toArray(new String[prefValuesList.size()])
- );
- return true;
- } else {
- return false;
- }
- };
- // create preference for each known network. attach listener and set
- // value
- for (int i = 0; i < networks.size(); i++) {
- WifiConfiguration config = networks.get(i);
-
- CheckBoxPreference pref = new CheckBoxPreference(activity);
- String key = Integer.toString(config.networkId);
- pref.setTitle(config.SSID);
- pref.setKey(key);
- pref.setOnPreferenceClickListener(clickListener);
- pref.setPersistent(false);
- pref.setChecked(prefValues.contains(key));
- selectedNetworks[i] = pref;
- prefScreen.addPreference(pref);
+ UserPreferences.setAutodownloadSelectedNetworks(
+ prefValuesList.toArray(new String[prefValuesList.size()])
+ );
+ return true;
+ } else {
+ return false;
}
- } else {
- Log.e(TAG, "Couldn't get list of configure Wi-Fi networks");
+ };
+ // create preference for each known network. attach listener and set
+ // value
+ for (int i = 0; i < networks.size(); i++) {
+ WifiConfiguration config = networks.get(i);
+
+ CheckBoxPreference pref = new CheckBoxPreference(activity);
+ String key = Integer.toString(config.networkId);
+ pref.setTitle(config.SSID);
+ pref.setKey(key);
+ pref.setOnPreferenceClickListener(clickListener);
+ pref.setPersistent(false);
+ pref.setChecked(prefValues.contains(key));
+ selectedNetworks[i] = pref;
+ prefScreen.addPreference(pref);
}
}
private void clearAutodownloadSelectedNetworsPreference() {
if (selectedNetworks != null) {
- PreferenceScreen prefScreen = (PreferenceScreen) ui.findPreference(PreferenceController.AUTO_DL_PREF_SCREEN);
+ PreferenceScreen prefScreen = ui.getPreferenceScreen();
for (CheckBoxPreference network : selectedNetworks) {
if (network != null) {
@@ -1013,11 +1179,16 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
public interface PreferenceUI {
+ void setFragment(PreferenceFragmentCompat fragment);
+ PreferenceFragmentCompat getFragment();
+
/**
* Finds a preference based on its key.
*/
Preference findPreference(CharSequence key);
- Activity getActivity();
+ PreferenceScreen getPreferenceScreen();
+
+ AppCompatActivity getActivity();
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/SwitchCompatPreference.java b/app/src/main/java/de/danoeh/antennapod/preferences/SwitchCompatPreference.java
deleted file mode 100644
index 10c11b88e..000000000
--- a/app/src/main/java/de/danoeh/antennapod/preferences/SwitchCompatPreference.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package de.danoeh.antennapod.preferences;
-
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.os.Build;
-import android.preference.CheckBoxPreference;
-import android.util.AttributeSet;
-
-import de.danoeh.antennapod.R;
-
-public class SwitchCompatPreference extends CheckBoxPreference {
-
- public SwitchCompatPreference(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- init();
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- public SwitchCompatPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- init();
- }
-
- public SwitchCompatPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
-
- public SwitchCompatPreference(Context context) {
- super(context);
- init();
- }
-
- private void init() {
- setWidgetLayoutResource(R.layout.preference_switch_layout);
- }
-} \ No newline at end of file
diff --git a/app/src/main/java/de/danoeh/antennapod/receiver/PlayerWidget.java b/app/src/main/java/de/danoeh/antennapod/receiver/PlayerWidget.java
deleted file mode 100644
index f0d4014ed..000000000
--- a/app/src/main/java/de/danoeh/antennapod/receiver/PlayerWidget.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package de.danoeh.antennapod.receiver;
-
-import java.util.Arrays;
-
-import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProvider;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.text.TextUtils;
-import android.util.Log;
-
-import de.danoeh.antennapod.core.service.playback.PlaybackService;
-import de.danoeh.antennapod.service.PlayerWidgetService;
-
-public class PlayerWidget extends AppWidgetProvider {
- private static final String TAG = "PlayerWidget";
- private static final String PREFS_NAME = "PlayerWidgetPrefs";
- private static final String KEY_ENABLED = "WidgetEnabled";
-
- @Override
- public void onReceive(Context context, Intent intent) {
- Log.d(TAG, "onReceive");
- super.onReceive(context, intent);
- // don't do anything if we're not enabled
- if (!isEnabled(context)) {
- return;
- }
-
- // these come from the PlaybackService when things should get updated
- if (TextUtils.equals(intent.getAction(), PlaybackService.FORCE_WIDGET_UPDATE)) {
- startUpdate(context);
- } else if (TextUtils.equals(intent.getAction(), PlaybackService.STOP_WIDGET_UPDATE)) {
- stopUpdate(context);
- }
- }
-
- @Override
- public void onEnabled(Context context) {
- super.onEnabled(context);
- Log.d(TAG, "Widget enabled");
- setEnabled(context, true);
- startUpdate(context);
- }
-
- @Override
- public void onUpdate(Context context, AppWidgetManager appWidgetManager,
- int[] appWidgetIds) {
- Log.d(TAG, "onUpdate() called with: " + "context = [" + context + "], appWidgetManager = [" + appWidgetManager + "], appWidgetIds = [" + Arrays.toString(appWidgetIds) + "]");
- startUpdate(context);
- }
-
- @Override
- public void onDisabled(Context context) {
- super.onDisabled(context);
- Log.d(TAG, "Widget disabled");
- setEnabled(context, false);
- stopUpdate(context);
- }
-
- private void startUpdate(Context context) {
- Log.d(TAG, "startUpdate() called with: " + "context = [" + context + "]");
- context.startService(new Intent(context, PlayerWidgetService.class));
- }
-
- private void stopUpdate(Context context) {
- Log.d(TAG, "stopUpdate() called with: " + "context = [" + context + "]");
- context.stopService(new Intent(context, PlayerWidgetService.class));
- }
-
- private boolean isEnabled(Context context) {
- SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
- return prefs.getBoolean(KEY_ENABLED, false);
- }
-
- private void setEnabled(Context context, boolean enabled) {
- SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
- prefs.edit().putBoolean(KEY_ENABLED, enabled).apply();
- }
-}
diff --git a/app/src/main/java/de/danoeh/antennapod/receiver/SPAReceiver.java b/app/src/main/java/de/danoeh/antennapod/receiver/SPAReceiver.java
index a373c5353..c9bd973cb 100644
--- a/app/src/main/java/de/danoeh/antennapod/receiver/SPAReceiver.java
+++ b/app/src/main/java/de/danoeh/antennapod/receiver/SPAReceiver.java
@@ -22,8 +22,8 @@ public class SPAReceiver extends BroadcastReceiver{
private static final String TAG = "SPAReceiver";
public static final String ACTION_SP_APPS_QUERY_FEEDS = "de.danoeh.antennapdsp.intent.SP_APPS_QUERY_FEEDS";
- public static final String ACTION_SP_APPS_QUERY_FEEDS_REPSONSE = "de.danoeh.antennapdsp.intent.SP_APPS_QUERY_FEEDS_RESPONSE";
- public static final String ACTION_SP_APPS_QUERY_FEEDS_REPSONSE_FEEDS_EXTRA = "feeds";
+ private static final String ACTION_SP_APPS_QUERY_FEEDS_REPSONSE = "de.danoeh.antennapdsp.intent.SP_APPS_QUERY_FEEDS_RESPONSE";
+ private static final String ACTION_SP_APPS_QUERY_FEEDS_REPSONSE_FEEDS_EXTRA = "feeds";
@Override
public void onReceive(Context context, Intent intent) {
diff --git a/app/src/main/java/de/danoeh/antennapod/service/PlayerWidgetService.java b/app/src/main/java/de/danoeh/antennapod/service/PlayerWidgetService.java
deleted file mode 100644
index b5bfb1ae4..000000000
--- a/app/src/main/java/de/danoeh/antennapod/service/PlayerWidgetService.java
+++ /dev/null
@@ -1,245 +0,0 @@
-package de.danoeh.antennapod.service;
-
-import android.app.PendingIntent;
-import android.app.Service;
-import android.appwidget.AppWidgetManager;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.Build;
-import android.os.IBinder;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.View;
-import android.widget.RemoteViews;
-
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.MainActivity;
-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.receiver.MediaButtonReceiver;
-import de.danoeh.antennapod.core.service.playback.PlaybackService;
-import de.danoeh.antennapod.core.service.playback.PlayerStatus;
-import de.danoeh.antennapod.core.storage.DBWriter;
-import de.danoeh.antennapod.core.util.Converter;
-import de.danoeh.antennapod.core.util.playback.Playable;
-import de.danoeh.antennapod.fragment.QueueFragment;
-import de.danoeh.antennapod.receiver.PlayerWidget;
-
-/**
- * Updates the state of the player widget
- */
-public class PlayerWidgetService extends Service {
- private static final String TAG = "PlayerWidgetService";
-
- private PlaybackService playbackService;
-
- /**
- * Controls write access to playbackservice reference
- */
- private Object psLock;
-
- /**
- * True while service is updating the widget
- */
- private volatile boolean isUpdating;
-
- public PlayerWidgetService() {
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- Log.d(TAG, "Service created");
- isUpdating = false;
- psLock = new Object();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- Log.d(TAG, "Service is about to be destroyed");
- if (playbackService != null) {
- Playable playable = playbackService.getPlayable();
- if (playable != null && playable instanceof FeedMedia) {
- FeedMedia media = (FeedMedia) playable;
- if (media.hasAlmostEnded()) {
- Log.d(TAG, "smart mark as read");
- FeedItem item = media.getItem();
- DBWriter.markItemPlayed(item, FeedItem.PLAYED, false);
- DBWriter.removeQueueItem(this, item, false);
- DBWriter.addItemToPlaybackHistory(media);
- if (item.getFeed().getPreferences().getCurrentAutoDelete() &&
- (!item.isTagged(FeedItem.TAG_FAVORITE) || !UserPreferences.shouldFavoriteKeepEpisode())) {
- Log.d(TAG, "Delete " + media.toString());
- DBWriter.deleteFeedMediaOfItem(this, media.getId());
- }
- }
- }
- }
-
- try {
- unbindService(mConnection);
- } catch (IllegalArgumentException e) {
- Log.w(TAG, "IllegalArgumentException when trying to unbind service");
- }
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
-
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- if (!isUpdating) {
- if (playbackService == null && PlaybackService.isRunning) {
- bindService(new Intent(this, PlaybackService.class),
- mConnection, 0);
- } else {
- startViewUpdaterIfNotRunning();
- }
- } else {
- Log.d(TAG, "Service was called while updating. Ignoring update request");
- }
- return Service.START_NOT_STICKY;
- }
-
- private void updateViews() {
- isUpdating = true;
-
- ComponentName playerWidget = new ComponentName(this, PlayerWidget.class);
- AppWidgetManager manager = AppWidgetManager.getInstance(this);
- RemoteViews views = new RemoteViews(getPackageName(),
- R.layout.player_widget);
- PendingIntent startMediaplayer = PendingIntent.getActivity(this, 0,
- PlaybackService.getPlayerActivityIntent(this), 0);
-
- Intent startApp = new Intent(getBaseContext(), MainActivity.class);
- startApp.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- startApp.putExtra(MainActivity.EXTRA_FRAGMENT_TAG, QueueFragment.TAG);
- PendingIntent startAppPending = PendingIntent.getActivity(getBaseContext(), 0, startApp, PendingIntent.FLAG_UPDATE_CURRENT);
-
- boolean nothingPlaying = false;
- if (playbackService != null) {
- final Playable media = playbackService.getPlayable();
- if (media != null) {
- PlayerStatus status = playbackService.getStatus();
- views.setOnClickPendingIntent(R.id.layout_left, startMediaplayer);
-
- views.setTextViewText(R.id.txtvTitle, media.getEpisodeTitle());
-
- String progressString = getProgressString();
- if (progressString != null) {
- views.setViewVisibility(R.id.txtvProgress, View.VISIBLE);
- views.setTextViewText(R.id.txtvProgress, progressString);
- }
-
- if (status == PlayerStatus.PLAYING) {
- views.setImageViewResource(R.id.butPlay, R.drawable.ic_pause_white_24dp);
- if (Build.VERSION.SDK_INT >= 15) {
- views.setContentDescription(R.id.butPlay, getString(R.string.pause_label));
- }
- } else {
- views.setImageViewResource(R.id.butPlay, R.drawable.ic_play_arrow_white_24dp);
- if (Build.VERSION.SDK_INT >= 15) {
- views.setContentDescription(R.id.butPlay, getString(R.string.play_label));
- }
- }
- views.setOnClickPendingIntent(R.id.butPlay,
- createMediaButtonIntent());
- } else {
- nothingPlaying = true;
- }
- } else {
- nothingPlaying = true;
- }
-
- if (nothingPlaying) {
- // start the app if they click anything
- views.setOnClickPendingIntent(R.id.layout_left, startAppPending);
- views.setOnClickPendingIntent(R.id.butPlay, startAppPending);
- views.setViewVisibility(R.id.txtvProgress, View.INVISIBLE);
- views.setTextViewText(R.id.txtvTitle,
- this.getString(R.string.no_media_playing_label));
- views.setImageViewResource(R.id.butPlay, R.drawable.ic_play_arrow_white_24dp);
- }
-
- manager.updateAppWidget(playerWidget, views);
- isUpdating = false;
- }
-
- /**
- * Creates an intent which fakes a mediabutton press
- */
- private PendingIntent createMediaButtonIntent() {
- KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN,
- KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE);
- Intent startingIntent = new Intent(
- MediaButtonReceiver.NOTIFY_BUTTON_RECEIVER);
- startingIntent.putExtra(Intent.EXTRA_KEY_EVENT, event);
-
- return PendingIntent.getBroadcast(this, 0, startingIntent, 0);
- }
-
- private String getProgressString() {
- int position = playbackService.getCurrentPosition();
- int duration = playbackService.getDuration();
- if (position > 0 && duration > 0) {
- return Converter.getDurationStringLong(position) + " / "
- + Converter.getDurationStringLong(duration);
- } else {
- return null;
- }
- }
-
- private ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- Log.d(TAG, "Connection to service established");
- synchronized (psLock) {
- if(service instanceof PlaybackService.LocalBinder) {
- playbackService = ((PlaybackService.LocalBinder) service).getService();
- startViewUpdaterIfNotRunning();
- }
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- synchronized (psLock) {
- playbackService = null;
- Log.d(TAG, "Disconnected from service");
- }
- }
-
- };
-
- private void startViewUpdaterIfNotRunning() {
- if (!isUpdating) {
- ViewUpdater updateThread = new ViewUpdater(this);
- updateThread.start();
- }
- }
-
- class ViewUpdater extends Thread {
- private static final String THREAD_NAME = "ViewUpdater";
- private PlayerWidgetService service;
-
- public ViewUpdater(PlayerWidgetService service) {
- super();
- setName(THREAD_NAME);
- this.service = service;
-
- }
-
- @Override
- public void run() {
- synchronized (psLock) {
- service.updateViews();
- }
- }
-
- }
-
-}
diff --git a/app/src/main/java/de/danoeh/antennapod/view/AspectRatioVideoView.java b/app/src/main/java/de/danoeh/antennapod/view/AspectRatioVideoView.java
index f930c912a..e79389fb3 100644
--- a/app/src/main/java/de/danoeh/antennapod/view/AspectRatioVideoView.java
+++ b/app/src/main/java/de/danoeh/antennapod/view/AspectRatioVideoView.java
@@ -25,6 +25,8 @@ public class AspectRatioVideoView extends VideoView {
private int mVideoWidth;
private int mVideoHeight;
+ private float mAvailableWidth = -1;
+ private float mAvailableHeight = -1;
public AspectRatioVideoView(Context context) {
this(context, null);
@@ -48,8 +50,13 @@ public class AspectRatioVideoView extends VideoView {
return;
}
- float heightRatio = (float) mVideoHeight / (float) getHeight();
- float widthRatio = (float) mVideoWidth / (float) getWidth();
+ if (mAvailableWidth < 0 || mAvailableHeight < 0) {
+ mAvailableWidth = getWidth();
+ mAvailableHeight = getHeight();
+ }
+
+ float heightRatio = (float) mVideoHeight / mAvailableHeight;
+ float widthRatio = (float) mVideoWidth / mAvailableWidth;
int scaledHeight;
int scaledWidth;
@@ -94,4 +101,15 @@ public class AspectRatioVideoView extends VideoView {
invalidate();
}
+ /**
+ * Sets the maximum size that the view might expand to
+ * @param width
+ * @param height
+ */
+ public void setAvailableSize(float width, float height) {
+ mAvailableWidth = width;
+ mAvailableHeight = height;
+ requestLayout();
+ }
+
}
diff --git a/app/src/main/java/de/danoeh/antennapod/view/SquareImageView.java b/app/src/main/java/de/danoeh/antennapod/view/SquareImageView.java
index 27b6ee2bc..7ce33e11f 100644
--- a/app/src/main/java/de/danoeh/antennapod/view/SquareImageView.java
+++ b/app/src/main/java/de/danoeh/antennapod/view/SquareImageView.java
@@ -1,13 +1,13 @@
package de.danoeh.antennapod.view;
import android.content.Context;
+import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
-import android.widget.ImageView;
/**
* From http://stackoverflow.com/a/19449488/6839
*/
-public class SquareImageView extends ImageView {
+public class SquareImageView extends AppCompatImageView {
public SquareImageView(Context context) {
super(context);
@@ -26,6 +26,7 @@ public class SquareImageView extends ImageView {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
+ //noinspection SuspiciousNameCombination
setMeasuredDimension(width, width);
}
diff --git a/app/src/main/play/ar/listing/fulldescription b/app/src/main/play/ar/listing/fulldescription
index 87b477fdc..27abb5532 100644
--- a/app/src/main/play/ar/listing/fulldescription
+++ b/app/src/main/play/ar/listing/fulldescription
@@ -1,4 +1,4 @@
-AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br>
+AntennaPod هو مدير للبودكاست واللاعب الذي يتيح لك الوصول الفوري إلى ملايين البودكاست المجانية والمدفوعة ، من البودكاسترات المستقلة إلى دور النشر الكبيرة مثل بي بي سي ، إن بي آر وسي إن إن. يمكنك إضافة واستيراد وتصدير خلاصاتهم الخالية من المتاعب باستخدام قاعدة بيانات بودكاست iTunes أو ملفات OPML أو عناوين URL RSS بسيطة. يمكنك توفير الجهد واستخدام طاقة البطارية واستخدام البيانات المتنقلة مع عناصر تحكم تلقائية قوية لتنزيل الحلقات (حدد الأوقات والفترات الزمنية وشبكات WiFi) وحذف الحلقات (استنادًا إلى إعداداتك المفضلة وتأخير الإعدادات).<br>
But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration.
Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads.
diff --git a/app/src/main/play/bg/listing/fulldescription b/app/src/main/play/bg/listing/fulldescription
new file mode 100644
index 000000000..16a005e22
--- /dev/null
+++ b/app/src/main/play/bg/listing/fulldescription
@@ -0,0 +1,43 @@
+AntennaPod е подкаст мениджър и плейър, който ви дава незабавен достъп до милиони безплатни и платени подкасти, от независими подкасти до големи издателства като BBC, NPR и CNN. Добавете, импортирайте и експортирайте своите емисии безпроблемно, като използвате базата данни на iTunes, OPML файлове или обикновени URL адреси. Спестете усилие, захранване на батерията и мобилни данни чрез мощни контролни механизми за автоматизиране на изтеглянето на епизоди (задайте часове, интервали и WiFi мрежи) и изтриването на епизоди (базирани на предпочитаните от вас и настройките за отлагане).<br>
+But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration.
+
+Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads.
+
+<b>Всички функции:</b><br>
+IMPORT, ORGANIZE AND PLAY<br>
+&#8226; Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br>
+&#8226; Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br>
+&#8226; Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br>
+&#8226; Access password-protected feeds and episodes<br>
+&#8226; Take advantage of paged feeds (www.podlove.org/paged-feeds)
+
+KEEP TRACK, SHARE & APPRECIATE<br>
+&#8226; Keep track of the best of the best by marking episodes as favourites<br>
+&#8226; Find that one episode through the playback history or by searching (titles and shownotes)<br>
+&#8226; Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br>
+&#8226; Support content creators with Flattr integration including automatic flattring
+
+CONTROL THE SYSTEM<br>
+&#8226; Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br>
+&#8226; Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br>
+&#8226; Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br>
+&#8226; Adapt to your environment using the light and dark theme<br>
+&#8226; Back-up your subscriptions with the gPodder.net integration and OPML export
+
+<b>Присъединете се към общността на AntennaPod!</b><br>
+AntennaPod се разработва активно от доброволци. Можете да допринесете с код или с коментар!
+
+GitHub е мястото за заявки за функции, отчети за грешки и участие:<br>
+https://www.github.com/AntennaPod/AntennaPod
+
+Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br>
+https://groups.google.com/forum/#!forum/antennapod
+
+Имате въпрос или искате да дадете отзиви?
+https://twitter.com/@AntennaPod
+
+Transifex е мястото за помощ при преводите:<br>
+https://www.transifex.com/antennapod/antennapod
+
+Check out our Beta Testing programme to get the latest features first:<br>
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/ca/listing/fulldescription b/app/src/main/play/ca/listing/fulldescription
index 87b477fdc..0e8d76e5e 100644
--- a/app/src/main/play/ca/listing/fulldescription
+++ b/app/src/main/play/ca/listing/fulldescription
@@ -1,43 +1,43 @@
-AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br>
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration.
-
-Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads.
-
-<b>All features:</b><br>
-IMPORT, ORGANIZE AND PLAY<br>
-&#8226; Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br>
-&#8226; Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br>
-&#8226; Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br>
-&#8226; Access password-protected feeds and episodes<br>
-&#8226; Take advantage of paged feeds (www.podlove.org/paged-feeds)
-
-KEEP TRACK, SHARE & APPRECIATE<br>
-&#8226; Keep track of the best of the best by marking episodes as favourites<br>
-&#8226; Find that one episode through the playback history or by searching (titles and shownotes)<br>
-&#8226; Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br>
-&#8226; Support content creators with Flattr integration including automatic flattring
-
-CONTROL THE SYSTEM<br>
-&#8226; Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br>
-&#8226; Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br>
-&#8226; Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br>
-&#8226; Adapt to your environment using the light and dark theme<br>
-&#8226; Back-up your subscriptions with the gPodder.net integration and OPML export
-
-<b>Join the AntennaPod community!</b><br>
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment!
-
-GitHub is the place to go for feature requests, bug reports and code contributions:<br>
+L'AntennaPod és un gestor i reproductor de podcasts que us dóna accés instantani a milions de podcasts gratuïts i de pagament, fets per podcasters independents o grans emissores com la BBC, l'NPR i la CNN. Afegiu, importeu i exporteu les seves subscripcions sense complicacions utilitzant la base de dades de podcasts de l'iTunes, fitxers OPML o enllaços RSS. Estalvieu esforços, bateria i consum de dades al mòbil amb potents controls d'automatització per a baixar episodis (especifiqueu hores, intervals i xarxes WiFi) i esborrar-los (basats en la vostra configuració sobre favorits i demores).<br>
+Però el més important: baixeu, transmeteu o afegiu episodis a la cua i gaudiu-ne a la vostra manera amb velocitats de reproducció ajustables, capacitat per a usar capítols i un temporitzador per a dormir. Fins i tot podeu demostrar la vostra estima pels creadors de continguts amb la nostra integració de Flattr.
+
+Fet per entusiastes del podcàsting, l'AntennaPod és lliure en tots els sentits del terme: codi obert, sense cost ni anuncis.
+
+<b>Totes les funcions:</b><br>
+IMPORTA, ORGANITZA I REPRODUEIX<br>
+&#8226; Afegeix i importa canals mitjançant els directoris iTunes i gPodder.net, fitxers OPML i enllaços RSS o Atom<br>
+&#8226; Gestiona la reproducció des de qualsevol banda: giny de la pantalla d'inici, notificacions del sistema i controls d'auriculars i Bluetooth.<br>
+&#8226; Gaudiu escoltant a la vostra manera amb velocitat de reproducció ajustable, capacitat per a usar capítols (MP3, VorbisComment i Podlove), record de la posició de reproducció i un temporitzador per a dormir avançat (agiteu per a reiniciar, abaixar el volum i reduir la velocitat de reproducció).<br>
+&#8226; Accediu a subscripcions i episodis protegits per contrasenya.<br>
+&#8226; Aprofiteu les subscripcions paginades (www.podlove.org/paged-feeds).
+
+FEU SEGUIMENT, COMPARTIU I AGRAÏU<br>
+&#8226; Seguiu el millor del millor marcant episodis com a favorits.<br>
+&#8226; Trobeu l'episodi que busqueu mitjançant l'historial de reproducció o la cerca (de títols i descripcions).<br>
+&#8226; Compartiu episodis i subscripcions mitjançant xarxes socials i correu electrònic, els serveis de gPodder.net i exportant a OPML.<br>
+&#8226; Recolzeu els creadors de continguts amb la integració de Flattr, fins i tot de forma automàtica.
+
+CONTROLEU EL SISTEMA<br>
+&#8226; Prengueu el control de les baixades automàtiques: trieu les subscripcions, exclogueu xarxes mòbils, trieu xarxes WiFi específiques, requeriu que el telèfon s'estigui carregat i establiu les hores o intervals.<br>
+&#8226; Gestioneu l'emmagatzematge ajustant la quantitat d'episodis en emmagatzematge temporal, l'esborrat intel·ligent (basat en els vostres favorits i l'estat de reproducció) i triant la vostra ubicació preferida.<br>
+&#8226; Feu servir l'AntennaPod en la vostra llengua (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH).<br>
+&#8226; Adapteu-vos al vostre entorn fent servir el tema clar o el fosc.<br>
+&#8226; Feu còpies de seguretat de les vostres subscripcions amb la integració amb gPodder.net i l'exportació a OPML.
+
+<b>Uniu-vos a la comunitat d'AntennaPod!</b><br>
+L'AntennaPod el desenvolupen voluntaris. Podeu col·laborar, amb codi o comentaris.
+
+Podeu proposar noves característiques, informar d'errors i aportar codi a GitHub:<br>
https://www.github.com/AntennaPod/AntennaPod
-Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br>
+Podeu compartir les vostres idees, els vostres moments de podcàsting favorits i la gratitud amb tots els voluntaris al nostre grup de Google:<br>
https://groups.google.com/forum/#!forum/antennapod
-Have a question or want to give us feedback?
+Teniu preguntes o voleu comentar-nos alguna cosa?
https://twitter.com/@AntennaPod
-Transifex is the place to help with translations:<br>
+Ens podeu ajudar amb les traduccions a Transifex:<br>
https://www.transifex.com/antennapod/antennapod
-Check out our Beta Testing programme to get the latest features first:<br>
+Consulteu el nostre programa de proves beta per a obtenir els primers<br> les últimes característiques:
https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/ca/listing/video b/app/src/main/play/ca/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/ca/listing/video
+++ /dev/null
diff --git a/app/src/main/play/contactPhone b/app/src/main/play/contactPhone
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/contactPhone
+++ /dev/null
diff --git a/app/src/main/play/cs-CZ/listing/video b/app/src/main/play/cs-CZ/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/cs-CZ/listing/video
+++ /dev/null
diff --git a/app/src/main/play/da-DK/listing/video b/app/src/main/play/da-DK/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/da-DK/listing/video
+++ /dev/null
diff --git a/app/src/main/play/de-DE/listing/video b/app/src/main/play/de-DE/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/de-DE/listing/video
+++ /dev/null
diff --git a/app/src/main/play/de/listing/fulldescription b/app/src/main/play/de/listing/fulldescription
index e5d7ec72a..0e09c5c29 100644
--- a/app/src/main/play/de/listing/fulldescription
+++ b/app/src/main/play/de/listing/fulldescription
@@ -1,4 +1,4 @@
-AntennaPod ist ein Podcast-Manager und -Player, der Dir unmittelbar Zugriff auf Millionen von freien und bezahlten Podcasts ermöglicht, angefangen von unabhängigen Podcastern zu großen Rundfunkanstalten oder Hörfunksendern wie BBC, NPR und CNN. Abonniere, importiere und exportiere deine Feeds mühelos mit Hilfe des iTunes-Verzeichnisses, OPML-Dateien oder einfachen RSS-URLs. Reduziere Aufwand, Stromverbrauch und Datenverbrauch durch die Kontrolle der Downloads (bestimmte Uhrzeiten, Intervalle, WiFi-Netze) und des Löschens von Episoden (basierend auf deinen Favoriten und weiteren Einstellungen).<br>
+AntennaPod ist ein Podcast-Manager und -Player, der Dir unmittelbar Zugriff auf Millionen von freien und kostenpflichtigen Podcasts ermöglicht, angefangen von unabhängigen Podcastern bis hin zu großen Rundfunkanstalten wie BBC, NPR und CNN. Abonniere, importiere und exportiere deine Feeds mühelos mit Hilfe des iTunes-Verzeichnisses, OPML-Dateien oder einfachen RSS-URLs. Reduziere Aufwand, Stromverbrauch und Datenverbrauch durch die Kontrolle der Downloads (bestimmte Uhrzeiten, Intervalle, WiFi-Netze) und des Löschens von Episoden (basierend auf deinen Favoriten und weiteren Einstellungen).<br>
Aber am wichtigsten: Downloade, streame oder füge Episoden zur Abspielliste hinzu und genieße sie mit einstellbarer Abspielgeschwindigkeit, Unterstützung von Kapiteln und Schlummerfunktion. Mit Flattr kannst du den Podcastern sogar deine Wertschätzung zeigen.
AntennaPod ist, von Podcast-Enthusiasten gemacht, frei im Sinne des Wortes: Open Source, keine Kosten, keine Werbung.
@@ -24,7 +24,7 @@ STEUER DAS SYSTEM<br>
&#8226; Passe das Aussehen mit dem hellen oder dunklen Theme an<br>
&#8226; Sichere deine Abonnements mit gPodder.net oder über den OPML-Export
-<b>Trete der AntennaPod-Community bei!</b><br>
+<b>Tritt der AntennaPod-Community bei!</b><br>
AntennaPod wird aktiv von Freiwilligen weiterentwickelt. Auch du kannst bei der Entwicklung mit Quellcode oder Kommentaren mitwirken!
Wir verwenden GitHub für Funktionswünsche (Feature Requests), Fehlerberichte (Bug Reports) und zum Beisteuern von Code (Code Contributions).
diff --git a/app/src/main/play/el/listing/fulldescription b/app/src/main/play/el/listing/fulldescription
index 87b477fdc..f0ec3ae38 100644
--- a/app/src/main/play/el/listing/fulldescription
+++ b/app/src/main/play/el/listing/fulldescription
@@ -1,11 +1,11 @@
-AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br>
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration.
+Το Antennapod είναι μία εφαρμογή διαχείρισης και εκτέλεσης podcasts που σας δίνει άμεση πρόσβαση σε εκατομμύρια δωρεάν και επί πληρωμή podcasts, από ανεξάρτητους podcasters έως μεγάλους εκδοτικούς οίκους όπως το BBC, NPR και CNN. Μπορείτε εύκολα να προσθέσετε, να εισάγετε και να εξάγετε τις ροές τους χρησιμοποιώντας τη βάση δεδομένων podcast του iTunes, αρχεία OPML ή απλά RSS URLs. Γλυτώστε προσπάθεια, μπαταρία και χρήση δεδομένων κινητής τηλεφωνίας με ισχυρές ρυθμίσεις αυτοματισμών για λήψη επεισοδίων (ορίστε τους χρόνους, τα διαστήματα και τα δίκτυα WiFi) και σβήστε επεισόδια (με βάση τα αγαπημένα σας και τις ρυθμίσεις καθυστέρησης).<br>
+Αλλά το πλέον σημαντικό: Κατεβάστε, κάντε stream ή βάλτε στη σειρά επεισόδια και απολαύστε τα όπως επιθυμήτε με ρυθμιζόμενη ταχύτητα αναπαραγωγής, υποστήριξη κεφάλαιων και χρονόμετρο απενεργοποίησης. Μπορείτε ακόμη και να δείξετε την αγάπη σας στους δημιουργούς περιεχομένου μέσω της ενσωμάτωσης του Flattr.
-Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads.
+Φτιαγμένο από λάτρη των podcast, το AntennaPod είναι ελεύθερο με όλες τις έννοιες της λέξης: ανοικτού λογισμικού, χωρίς κόστη, χωρίς διαφημίσεις.
-<b>All features:</b><br>
-IMPORT, ORGANIZE AND PLAY<br>
-&#8226; Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br>
+<b>Όλα τα χαρακτηριστικά:</b><br>
+ΕΙΣΑΓΩΓΉ, ΟΡΓΆΝΩΣΗ ΚΑΙ ΕΚΤΈΛΕΣΗ<br>
+&#8226; Προσθέστε και εισάγετε ροές μέσω των φακέλων του iTunes και του gPodder.net, αρχείων OPML και RSS ή συνδέσμους Atom<br>
&#8226; Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br>
&#8226; Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br>
&#8226; Access password-protected feeds and episodes<br>
@@ -24,20 +24,20 @@ CONTROL THE SYSTEM<br>
&#8226; Adapt to your environment using the light and dark theme<br>
&#8226; Back-up your subscriptions with the gPodder.net integration and OPML export
-<b>Join the AntennaPod community!</b><br>
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment!
+<b>Ενταχθείτε στη κοινότητα του AntennaPod!</b><br>
+Το AntennaPod βρίσκεται υπό ενεργή ανάπτυξη από εθελοντές. Μπορείτε και εσείς να συνεισφέρετε, με κώδικα ή με κάποιο σχόλιο.
-GitHub is the place to go for feature requests, bug reports and code contributions:<br>
+Το Github είναι το μέρος να επισκεφθείτε για να ζητήσετε καινούρια χαρακτηριστικά, να αναφέρετε σφάλματα και για συνεισφορά κώδικα:<br>
https://www.github.com/AntennaPod/AntennaPod
-Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br>
+Το Google Group μας είναι το μέρος να μοιραστείτε τις ιδέες σας, τις αγαπημένες σας στιγμές ενασχόλησης με τα podcasts και ευγνωμοσύνη σε όλους τους εθελοντές:<br>
https://groups.google.com/forum/#!forum/antennapod
-Have a question or want to give us feedback?
+Έχετε κάποια ερώτηση ή θέλετε να μας δώσετε κάποια ανατροφοδότηση;
https://twitter.com/@AntennaPod
-Transifex is the place to help with translations:<br>
+Το Transifex είναι το μέρος για να βοηθήσετε με τις μεταφράσεις:<br>
https://www.transifex.com/antennapod/antennapod
-Check out our Beta Testing programme to get the latest features first:<br>
+Ελέγξτε το πρόγραμμά μας Beta Testing για να λαμβάνετε τα τελευταία χαρακτηριστικά πρώτοι:<br>
https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/en-US/listing/featureGraphic/feature-graphic.png b/app/src/main/play/en-US/listing/featureGraphic/feature-graphic.png
new file mode 100644
index 000000000..3b5261b28
--- /dev/null
+++ b/app/src/main/play/en-US/listing/featureGraphic/feature-graphic.png
Binary files differ
diff --git a/app/src/main/play/en-US/listing/video b/app/src/main/play/en-US/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/en-US/listing/video
+++ /dev/null
diff --git a/app/src/main/play/es-ES/listing/video b/app/src/main/play/es-ES/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/es-ES/listing/video
+++ /dev/null
diff --git a/app/src/main/play/es/listing/fulldescription b/app/src/main/play/es/listing/fulldescription
index 2f1c8861a..96f914f26 100644
--- a/app/src/main/play/es/listing/fulldescription
+++ b/app/src/main/play/es/listing/fulldescription
@@ -1,4 +1,4 @@
-AntennaPod is un gestor y reproductor de podcast que te da acceso instantáneo a millones de podcast gratuitos y de pago, desde podcasters independientes a grandes estaciones como la BBC, NPR y CNN. Agrega, importa y exporta las fuentes de manera sencilla usando el listado de iTunes, archivos OPML o las URL de tipo RSS. Ahorra esfuerzo, batería y datos con los controles de descarga (a horas o intervalos específicos, o redes WiFi) y de borrado de episodios (basado en favoritos y ajustes de tiempo).<br>
+AntennaPod es un gestor y reproductor de podcast que te da acceso instantáneo a millones de podcast gratuitos y pagos, desde podcasters independientes a grandes estaciones como la BBC, NPR y CNN. Agrega, importa y exporta las fuentes de manera sencilla usando el listado de iTunes, archivos OPML o las URL de tipo RSS. Ahorre esfuerzo, energía de la batería y uso de datos móviles con potentes controles de automatización para descargar episodios (especifique horarios, intervalos y redes WiFi) y elimine episodios (según sus preferencias y configuraciones de demora).<br>
Y lo más importante: descarga, escucha en stream y disfrutalos como quieras con velocidad de reproducción variable, soporte para capítulos y temporizador de sueño. Incluso puedes mostrar tu gratitud a los creadores de contenido mediante Flattr.
Hecho por entusiastas del podcasting, AntennaPod es libre, gratuito y sin publicidad.
diff --git a/app/src/main/play/fa/listing/fulldescription b/app/src/main/play/fa/listing/fulldescription
index 87b477fdc..0a005f962 100644
--- a/app/src/main/play/fa/listing/fulldescription
+++ b/app/src/main/play/fa/listing/fulldescription
@@ -1,5 +1,5 @@
-AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br>
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration.
+AntennaPod یک نرم افزار مدیریت و پخش پادکست میباشد که به شما امکان دسترسی سریع به میلیون ها پادکست رایگان و پرداخت شده ، از طریق انتشارات بزرگ و مستقل مانند بی بی سی، NPR و CNN را می دهد. همچنین شما میتوانید از پایگاه داده iTunes podcast، فایل های OPML یا URL های ساده RSS، استفاده نمایید ، آنها را اضافه کنید ،اطلاعالت خود را وارد و یا از انها فایل پشتیبان تهیه کنید.. صرفه جویی در زمان جستجو ، قدرت باتری و استفاده از داده های تلفن همراه با استفاده از ترفندهای قدرتمند اتوماسیون برای دانلود قسمت ها (تعیین زمان، فواصل و شبکه های WiFi) و حذف قسمت (بر اساس علاقه مندی های خود و تنظیمات تاخیر)<br>
+ما مهمتر از همه: دانلود، پخش یا پخش قسمت ها و لذت بردن از آنهاست، سرعت پخش قابل تنظیم، به هر سرعتی که شما علاقه دارید ، با پشتیبانی فصل ( قسمتها ) و یک تایمر برای خواب .حتی شما میتوانید علاقه خود را با سازندگان محتوا با استفاده از Flattr integration ما ، نشان دهید.
Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads.
diff --git a/app/src/main/play/fr-FR/listing/video b/app/src/main/play/fr-FR/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/fr-FR/listing/video
+++ /dev/null
diff --git a/app/src/main/play/he_IL/listing/fulldescription b/app/src/main/play/he_IL/listing/fulldescription
index b4ac8ca6c..4ccee5452 100644
--- a/app/src/main/play/he_IL/listing/fulldescription
+++ b/app/src/main/play/he_IL/listing/fulldescription
@@ -1,43 +1,43 @@
-AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br>
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration.
+היישומון אנטנה־פּוֹד הוא נגן ומנהל פודקאסטים שמעניק לך גישה ישירה למיליונים של פודקאסטים בחינם ובתשלום, החל ממגישי פודקאסטים עצמאיים ועד למפיצים גדולים כגון BBC,‏ NPR ו־CNN. ניתן להוסיף, לייבא ולייצא את ההזנות שלהם בקלות יחסית באמצעות מסד נתוני הפודקאסטים של iTunes, קובצי OPML או כתובות של RSS. מאפשר לך לחסוך במאמץ, סוללה ותקשורת נתונים עם פקדי אוטומציה להורדה של פרקים (לפי זמנים, הפרשי זמן ורשתות אלחוטיות) ומחיקה של פרקים (על בסיס הגדרות המועדפים וההשהיה שלך).<br>
+אבל הכי חשוב: ניתן להוריד, להזרים או לסדר רשימות של פרקים וליהנות מהם בכל דרך שמתאימה לך עם מהירויות נגינה משתנות, תמיכה במקטעים ומתזמן שינה. ניתן אפילו להביע את חיבתך ליוצרי התוכן עם שילוב של Flattr ביישומון.
מיוצרת על ידי חובבי פודקאסטים, אנטנהפוד הינה תוכנה חינמית בכל מובן המילה: קוד פתוח, ללא עלות וללא פרסומות.
-<b>All features:</b><br>
-IMPORT, ORGANIZE AND PLAY<br>
-&#8226; Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br>
-&#8226; Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br>
-&#8226; Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br>
-&#8226; Access password-protected feeds and episodes<br>
-&#8226; Take advantage of paged feeds (www.podlove.org/paged-feeds)
-
-KEEP TRACK, SHARE & APPRECIATE<br>
-&#8226; Keep track of the best of the best by marking episodes as favourites<br>
-&#8226; Find that one episode through the playback history or by searching (titles and shownotes)<br>
-&#8226; Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br>
-&#8226; Support content creators with Flattr integration including automatic flattring
-
-CONTROL THE SYSTEM<br>
-&#8226; Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br>
-&#8226; Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br>
-&#8226; Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br>
-&#8226; Adapt to your environment using the light and dark theme<br>
-&#8226; Back-up your subscriptions with the gPodder.net integration and OPML export
-
-<b>Join the AntennaPod community!</b><br>
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment!
-
-GitHub is the place to go for feature requests, bug reports and code contributions:<br>
+<b>כל התכונות:</b><br>
+ייבוא, ארגון ונגינה<br>
+&#8226; ניתן להוסיף ולייבא הזנות דרך הספריות של iTunes ושל gPodder.net, קובצי OPML וקישורי RSS או Atom<br>
+&#8226; ניתן לנהל את הנגינה מכל מקום: וידג׳ט על מסך הבית, התרעות המערכת ופקדי שקע אוזניות ובלוטות׳<br>
+&#8226; פשוט ליהנות בדרך שלך עם מהירות נגינה משתנה, תמיכה במקטעים (MP3, VorbisComment ו־Podlove), שמירת מיקום הנגינה ומתזמן שינה מתקדם (ניתן לנער כדי לאפס, להנמיך את עצמך השמע ולהאט את מהירות הנגינה)<br>
+&#8226; גישה להזנות ולפרקים המוגנים בססמה<br>
+&#8226; ניתן להשתמש בעימודי ההזנות שלנו (www.podlove.org/paged-feeds)
+
+מעקב, שיתוף והבעת הערכה<br>
+&#8226; מעקב אחר הטובים שבטובים על ידי סימון פרקים כמועדפים<br>
+&#8226; ניתן לאתר פרק אחד דרך היסטוריית הנגינה או על ידי חיפוש (כותרות והערות פרק)<br>
+&#8226; ניתן לשתף פרקים והזנות דרך אפשרויות מתקדמות ברשתות חברתיות ודוא״ל, שירותי gPodder.net ודרך ייצוא OPML<br>
+&#8226; ניתן לתמוך בעורכי תוכן עם שילוב של Flattr לתוך המערכת לרבות תרומה אוטומטית
+
+שליטה במערכת<br>
+&#8226; ניתן לשלוט על הורדה אוטומטית: לבחור הזנות, להחריג רשתות סלולריות, לבחור רשתות אלחוטיות מסוימות, לדרוש מהטלפון להיות בטעינה ולהגדיר מועדים או מרווחי זמן<br>
+&#8226; ניתן לנהל את האחסון על ידי הגדרת כמות הפרקים שנשמרים במטמון, מחיקה חכמה (בהתבסס על המועדפים ומצב הנגינה שלך) ובחירת המיקום המועדף עליך<br>
+&#8226; ניתן להשתמש באנטנה־פּוֹד בשפה שלך (HE, EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br>
+&#8226; התאמה לסביבה שלך באמצעות ערכות עיצוב בהירה וכהה<br>
+&#8226; גיבוי התמיכה שלך עם שילוב מול gPodder.net וייצוא של OPML
+
+<b>מזמינים אותך להצטרף לקהילת אנטנה־פּוֹד!</b><br>
+את תהליכי הפיתוח הפעילים של אנטנה־פּוֹד מובילים מתנדבים. ניתן לתרום גם כן, עם קוד או עם הערה!
+
+GitHub הוא המקום בו אנו מרכזים את בקשות התכונות, דיווחי התקלות ותרומות הקוד:<br>
https://www.github.com/AntennaPod/AntennaPod
-Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br>
+הקבוצה שלנו ב־Google היא המקום לשתף את הרעיונות שלך, רגעי הפודקאסט המועדפים עליך ואת הערכתך לכל המתנדבים:<br>
https://groups.google.com/forum/#!forum/antennapod
-Have a question or want to give us feedback?
+יש לך שאלה או שמעניין אותך לתת לנו משוב?
https://twitter.com/@AntennaPod
-Transifex is the place to help with translations:<br>
+Transifex הוא המקום לסייע בתרגומים:<br>
https://www.transifex.com/antennapod/antennapod
-Check out our Beta Testing programme to get the latest features first:<br>
+מזמינים אותך לחקור את תכנית הבדיקות שלנו כדי לקבל את התכונות העדכניות ביותר לפני כולם:<br>
https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/hi-IN/listing/video b/app/src/main/play/hi-IN/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/hi-IN/listing/video
+++ /dev/null
diff --git a/app/src/main/play/it-IT/listing/video b/app/src/main/play/it-IT/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/it-IT/listing/video
+++ /dev/null
diff --git a/app/src/main/play/it/listing/fulldescription b/app/src/main/play/it/listing/fulldescription
index 307f86117..3d0425660 100644
--- a/app/src/main/play/it/listing/fulldescription
+++ b/app/src/main/play/it/listing/fulldescription
@@ -1,36 +1,36 @@
-AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br>
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration.
+AntennaPod è un gestore e player di podcast che ti dà accesso istantaneo a milioni di podcast gratuiti e a pagamento, da podcaster indipendenti a grandi case editrici come BBC, NPR e CNN. Aggiungi, Importa ed esporta facilmente i Feed dal database di iTunes, file OPML oppure semplici collegamenti RSS. Risparmia fatica, batteria e dati con potenti controlli automatici per scaricare gli episodi (specifica orari, intervalli e reti WiFi) ed eliminare gli episodi.<br>
+Ma soprattutto: Scarica, fai Stream o metti in coda gli episodi e goditeli come preferisci cambiando la velocità di riproduzione, saltando tra capitoli e impostando lo sleep timer. Puoi persino mostrare il tuo amore attraverso l'integrazione con Flattr.
-Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads.
+Creato da amatori del podcast, AntennaPod è <i>free</i> in tutti i sensi: open-source, nessun costo, nessuna pubblicità.
<b>Tutte le funzioni:</b><br>
IMPORTA, ORGANIZZA E RIPRODUCI<br>
-&#8226; Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br>
-&#8226; Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br>
-&#8226; Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br>
+&#8226; Aggiungi ed importa i feed tramite i database di iTunes e gPodder.net, file OPML e link RSS o Atom<br>
+&#8226; Gestisci la riproduzione in ogni modo: attraverso il widget per la home, le notifiche di sistema oppure tramite i controlli sulle cuffie, sia cablate che bluetooth<br>
+&#8226; Goditi l'ascolto a modo tuo attraverso la velocità di riproduzione regolabile, il supporto ai capitoli (MP3, VorbisComment e Podlove), la memoria della posizione di riproduzione e un timer di riproduzione avanzato (scuoti per reimpostare, abbassamento del volume e rallentamento di riproduzione)<br>
&#8226; Accedi a feed ed episodi protetti da password<br>
-&#8226; Take advantage of paged feeds (www.podlove.org/paged-feeds)
+&#8226; Approfitta dei <i>paged feeds</i> (www.podlove.org/paged-feeds)
-TIENI TRACCIA, CONDIVIDI & APPREZZA<br>
-&#8226; Keep track of the best of the best by marking episodes as favourites<br>
-&#8226; Find that one episode through the playback history or by searching (titles and shownotes)<br>
-&#8226; Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br>
-&#8226; Support content creators with Flattr integration including automatic flattring
+TIENI TRACCIA, CONDIVIDI E APPREZZA<br>
+&#8226; Tieni traccia degli episodi migliori aggiungendoli ai preferiti<br>
+&#8226; Trova episodi specifici nella cronologia di riproduzione o cercando tra titoli e descrizioni<br>
+&#8226; Condividi episodi e feed attraverso le opzioni avanzate di condivisione verso social e emali, i servizi online di gPodder.net e l'esportazione in file OPML<br>
+&#8226; Supporta i creatori attraverso Flattr consentendo anche il <i>flattring</i> automatico
CONTROLLA IL SISTEMA<br>
-&#8226; Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br>
-&#8226; Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br>
+&#8226; Prendi il controllo dei download automatici: scegli i Feed, escludi le reti cellulari, seleziona reti WiFi specifiche, attiva solo a telefono in carica e imposta orari e intervalli.<br>
+&#8226; Gestisci la memoria impostando il numero massimo di episodi scaricati, l'eliminazione automatica (basata sui tuoi preferiti e lo stato di riproduzione) e selezionando la tua posizione preferita in memoria<br>
&#8226; Utilizza AntennaPod nella tua lingua (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br>
-&#8226; Adapt to your environment using the light and dark theme<br>
-&#8226; Back-up your subscriptions with the gPodder.net integration and OPML export
+&#8226; Adatta all'ambiente usando il tema chiaro e quello scuro<br>
+&#8226; Fai il backup delle tue iscrizione con gPodder.net e l'esportazione OPML
<b>Unisciti alla comunità di AntennaPod!</b><br>
-AntennaPod is under active development by volunteers. You can contribute too, with code or with comment!
+AntennaPod è in fase attiva di sviluppo da parte di volontari. Anche te puoi contribuire, con codice o commenti!
-GitHub is the place to go for feature requests, bug reports and code contributions:<br>
+Per chiedere nuove funzioni, contribuire con del codice o segnalare problemi, puoi trovarci su GitHub:
https://www.github.com/AntennaPod/AntennaPod
-Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br>
+Il nostro Gruppo Google è il posto giusto per condividere le tue idee, i tuoi più bei momenti di podcasting e per mostrare gratitudine ai volontari<br>
https://groups.google.com/forum/#!forum/antennapod
Hai una domanda o vuoi fornirci un feedback?
diff --git a/app/src/main/play/it_IT/listing/fulldescription b/app/src/main/play/it_IT/listing/fulldescription
index eb2abb40d..31fa64d69 100644
--- a/app/src/main/play/it_IT/listing/fulldescription
+++ b/app/src/main/play/it_IT/listing/fulldescription
@@ -1,28 +1,28 @@
AntennaPod è un riproduttore e gestore di podcast che ti da accesso immediato a milioni di podcast gratuiti e a pagamento, dai podcaster indipendenti alle più grandi emittenti come BBC, NPR e CNN. Aggiungi, importa e esporta in modo semplici usando il database di podcast di iTunes, da file OPML o da semplici URL RSS. Risparmia fatica, batteria e dati con il potente controllo automatizzato per il download di episodi (orari specifici, intervalli e reti WiFi) e l'eliminazione degli episodi.<br>
-But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration.
+Ancora più importante: scarica, ascolta in streaming o metti in coda gli episodi e goditeli quando e come vuoi grazie alla velocità di riproduzione personalizzabile, al supporto per i capitoli e al timer di spegnimento. Puoi anche ringraziare i creatori di contenuti grazie all'integrazione con Flattr.
Creato da amanti dei podcast, AntennaPod è libero in tutti i sensi: open source, gratis, senza pubblicità.
<b>Funzioni:</b><br>
IMPORTA, ORGANIZZA E RIPRODUCI<br>
&#8226; Aggiungi e importa feed via iTunes, gPodder.net, file OPML e link RSS o Atom<br>
-&#8226; Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br>
-&#8226; Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br>
+&#8226; Gestisci la riproduzione da dove vuoi: widget sulla schermata Home, notifiche di sistema e controlli sugli auricolari e via bluetooth. <br>
+&#8226; Divertiti ad ascoltare nel modo che preferisci grazie alla velocità di riproduzione variabile, il supporto ai capitoli (MP3, VorbisComment e Podlove), la memorizzazione dell'avanzamento di riproduzione e un timer di spegnimento avanzato (scuoti per resettare, volume basso e rallentamento della velocità)<br>
&#8226; Accedi a feed e episodi protetti da password<br>
-&#8226; Take advantage of paged feeds (www.podlove.org/paged-feeds)
+&#8226; Sfrutta i vantaggi dei paged feeds (www.podlove.org/paged-feeds)
TIENI TRACCIA, CONDIVIDI & APPREZZA<br>
-&#8226; Keep track of the best of the best by marking episodes as favourites<br>
-&#8226; Find that one episode through the playback history or by searching (titles and shownotes)<br>
-&#8226; Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br>
+&#8226; Tieni traccia del meglio del meglio segnando gli episodi come Preferiti<br>
+&#8226; Trova l'episodio specifico grazie alla cronologia di riproduzione o al sistema di ricerca (titoli e note dell'episodio)<br>
+&#8226; Condividi gli episodi e i feed tramite le avanzate opzioni social ed email, il servizio gPodder.net e l'esportazione in OPML<br>
&#8226; Supporta i creatori di contenuti tramite l'integrazione con Flattr e il flattring automatico
CONTROLLA IL SISTEMA<br>
-&#8226; Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br>
-&#8226; Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br>
+&#8226; Prendi il controllo grazie ai download automatici: scegli i feed, escludi le reti mobili, seleziona reti WiFi specifiche, richiedi che il telefono sia in carica e imposta tempi e intervalli di aggiornamento<br>
+&#8226; Gestisci lo spazio impostando l'occupazione massima, la cancellazione intelligente (basata sui Preferiti e sullo stato di riproduzione) e selezionando la posizione che preferisci <br>
&#8226; Usa AntennaPod nella tua lingua (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br>
-&#8226; Adapt to your environment using the light and dark theme<br>
-&#8226; Back-up your subscriptions with the gPodder.net integration and OPML export
+&#8226; Adattati all'ambiente in cui ti trovi con i temi Chiaro e Scuro.<br>
+&#8226; Salva le sottoscrizioni grazie all'integrazione con gPodder.net e l'esportazione OPML
<b>Entra nella community di AntennaPod!</b><br>
AntennaPod è sviluppato da volontari. Anche tu puoi contribuire, con il codice o con dei commenti!
@@ -30,7 +30,7 @@ AntennaPod è sviluppato da volontari. Anche tu puoi contribuire, con il codice
GitHub è il posto nel quale fare richieste, segnalare bug e contribuire allo sviluppo:<br>
https://www.github.com/AntennaPod/AntennaPod
-Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br>
+Il nostro gruppo Google è il luogo ideale dove condividere le idee, stimolare momenti di podcasting e ringraziare tutti i volontari:<br>
https://groups.google.com/forum/#!forum/antennapod
Hai una domanda o vuoi darci un feedback?
diff --git a/app/src/main/play/iw-IL/listing/video b/app/src/main/play/iw-IL/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/iw-IL/listing/video
+++ /dev/null
diff --git a/app/src/main/play/ja-JP/listing/video b/app/src/main/play/ja-JP/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/ja-JP/listing/video
+++ /dev/null
diff --git a/app/src/main/play/ko-KR/listing/video b/app/src/main/play/ko-KR/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/ko-KR/listing/video
+++ /dev/null
diff --git a/app/src/main/play/ms_MY/listing/fulldescription b/app/src/main/play/ms_MY/listing/fulldescription
new file mode 100644
index 000000000..87b477fdc
--- /dev/null
+++ b/app/src/main/play/ms_MY/listing/fulldescription
@@ -0,0 +1,43 @@
+AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br>
+But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration.
+
+Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads.
+
+<b>All features:</b><br>
+IMPORT, ORGANIZE AND PLAY<br>
+&#8226; Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br>
+&#8226; Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br>
+&#8226; Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br>
+&#8226; Access password-protected feeds and episodes<br>
+&#8226; Take advantage of paged feeds (www.podlove.org/paged-feeds)
+
+KEEP TRACK, SHARE & APPRECIATE<br>
+&#8226; Keep track of the best of the best by marking episodes as favourites<br>
+&#8226; Find that one episode through the playback history or by searching (titles and shownotes)<br>
+&#8226; Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br>
+&#8226; Support content creators with Flattr integration including automatic flattring
+
+CONTROL THE SYSTEM<br>
+&#8226; Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br>
+&#8226; Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br>
+&#8226; Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br>
+&#8226; Adapt to your environment using the light and dark theme<br>
+&#8226; Back-up your subscriptions with the gPodder.net integration and OPML export
+
+<b>Join the AntennaPod community!</b><br>
+AntennaPod is under active development by volunteers. You can contribute too, with code or with comment!
+
+GitHub is the place to go for feature requests, bug reports and code contributions:<br>
+https://www.github.com/AntennaPod/AntennaPod
+
+Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br>
+https://groups.google.com/forum/#!forum/antennapod
+
+Have a question or want to give us feedback?
+https://twitter.com/@AntennaPod
+
+Transifex is the place to help with translations:<br>
+https://www.transifex.com/antennapod/antennapod
+
+Check out our Beta Testing programme to get the latest features first:<br>
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/nb_NO/listing/fulldescription b/app/src/main/play/nb_NO/listing/fulldescription
index 11bc6fd9f..460a880fe 100644
--- a/app/src/main/play/nb_NO/listing/fulldescription
+++ b/app/src/main/play/nb_NO/listing/fulldescription
@@ -18,7 +18,7 @@ FØLG MED, DEL OG SETT PRIS PÅ<br>
&#8226; Støtt innholdsskapere med Flattr-integrasjon gjennom automatisk &#171;flattring&#187;
KONTROLLER SYSTEMET<br>
-&#8226; Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br>
+&#8226; Ta kontroll over automatiske nedlastninger: velg feeds, ekskluder mobil tilkobling, spesifiser Wifi-nettverk, krev at telefonen er tilkoblet lader, sett tidspunk eller intervaller<br>
&#8226; Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br>
&#8226; Bruk AntennaPod i ditt språk (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br>
&#8226; Tilpass appens stil ved å bruke det mørke eller lyse temaet<br>
@@ -33,11 +33,11 @@ https://www.github.com/AntennaPod/AntennaPod
Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br>
https://groups.google.com/forum/#!forum/antennapod
-Have a question or want to give us feedback?
+Har du spørsmål eller vil du gi oss tilbakemelding?
https://twitter.com/@AntennaPod
-Transifex is the place to help with translations:<br>
+Transifex er stedet for å hjelpe til med oversettinger:<br>
https://www.transifex.com/antennapod/antennapod
-Check out our Beta Testing programme to get the latest features first:<br>
+Sjekk ut vårt program for betatesting for å få de nyeste funksjonene først:<br>
https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/nl-NL/listing/video b/app/src/main/play/nl-NL/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/nl-NL/listing/video
+++ /dev/null
diff --git a/app/src/main/play/pl-PL/listing/video b/app/src/main/play/pl-PL/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/pl-PL/listing/video
+++ /dev/null
diff --git a/app/src/main/play/pt-BR/listing/video b/app/src/main/play/pt-BR/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/pt-BR/listing/video
+++ /dev/null
diff --git a/app/src/main/play/pt-PT/listing/video b/app/src/main/play/pt-PT/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/pt-PT/listing/video
+++ /dev/null
diff --git a/app/src/main/play/ro/listing/video b/app/src/main/play/ro/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/ro/listing/video
+++ /dev/null
diff --git a/app/src/main/play/ru-RU/listing/video b/app/src/main/play/ru-RU/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/ru-RU/listing/video
+++ /dev/null
diff --git a/app/src/main/play/sl_SI/listing/fulldescription b/app/src/main/play/sl_SI/listing/fulldescription
new file mode 100644
index 000000000..87b477fdc
--- /dev/null
+++ b/app/src/main/play/sl_SI/listing/fulldescription
@@ -0,0 +1,43 @@
+AntennaPod is a podcast manager and player that gives you instant access to millions of free and paid podcasts, from independent podcasters to large publishing houses such as the BBC, NPR and CNN. Add, import and export their feeds hassle-free using the iTunes podcast database, OPML files or simple RSS URLs. Save effort, battery power and mobile data usage with powerful automation controls for downloading episodes (specify times, intervals and WiFi networks) and deleting episodes (based your favourites and delay settings).<br>
+But most importantly: Download, stream or queue episodes and enjoy them the way you like with adjustable playback speeds, chapter support and a sleep timer. You can even show your love to the content creators with our Flattr integration.
+
+Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads.
+
+<b>All features:</b><br>
+IMPORT, ORGANIZE AND PLAY<br>
+&#8226; Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br>
+&#8226; Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br>
+&#8226; Enjoy listening your way with adjustable playback speed, chapter support (MP3, VorbisComment and Podlove), remembered playback position and an advanced sleep timer (shake to reset, lower volume and slow down playback)<br>
+&#8226; Access password-protected feeds and episodes<br>
+&#8226; Take advantage of paged feeds (www.podlove.org/paged-feeds)
+
+KEEP TRACK, SHARE & APPRECIATE<br>
+&#8226; Keep track of the best of the best by marking episodes as favourites<br>
+&#8226; Find that one episode through the playback history or by searching (titles and shownotes)<br>
+&#8226; Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br>
+&#8226; Support content creators with Flattr integration including automatic flattring
+
+CONTROL THE SYSTEM<br>
+&#8226; Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br>
+&#8226; Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br>
+&#8226; Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br>
+&#8226; Adapt to your environment using the light and dark theme<br>
+&#8226; Back-up your subscriptions with the gPodder.net integration and OPML export
+
+<b>Join the AntennaPod community!</b><br>
+AntennaPod is under active development by volunteers. You can contribute too, with code or with comment!
+
+GitHub is the place to go for feature requests, bug reports and code contributions:<br>
+https://www.github.com/AntennaPod/AntennaPod
+
+Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br>
+https://groups.google.com/forum/#!forum/antennapod
+
+Have a question or want to give us feedback?
+https://twitter.com/@AntennaPod
+
+Transifex is the place to help with translations:<br>
+https://www.transifex.com/antennapod/antennapod
+
+Check out our Beta Testing programme to get the latest features first:<br>
+https://www.github.com/AntennaPod/AntennaPod/wiki/Help-test-AntennaPod \ No newline at end of file
diff --git a/app/src/main/play/sv-SE/listing/video b/app/src/main/play/sv-SE/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/sv-SE/listing/video
+++ /dev/null
diff --git a/app/src/main/play/tr-TR/listing/video b/app/src/main/play/tr-TR/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/tr-TR/listing/video
+++ /dev/null
diff --git a/app/src/main/play/uk/listing/video b/app/src/main/play/uk/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/uk/listing/video
+++ /dev/null
diff --git a/app/src/main/play/vi/listing/fulldescription b/app/src/main/play/vi/listing/fulldescription
index 87b477fdc..9519b5da1 100644
--- a/app/src/main/play/vi/listing/fulldescription
+++ b/app/src/main/play/vi/listing/fulldescription
@@ -3,7 +3,7 @@ But most importantly: Download, stream or queue episodes and enjoy them the way
Made by podcast-enthousiast, AntennaPod is free in all senses of the word: open source, no costs, no ads.
-<b>All features:</b><br>
+Mọi tính năng:
IMPORT, ORGANIZE AND PLAY<br>
&#8226; Add and import feeds via the iTunes and gPodder.net directories, OPML files and RSS or Atom links<br>
&#8226; Manage playback from anywhere: homescreen widget, system notification and earplug and bluetooth controls<br>
@@ -17,14 +17,14 @@ KEEP TRACK, SHARE & APPRECIATE<br>
&#8226; Share episodes and feeds through advanced social media and email options, the gPodder.net services and via OPML export<br>
&#8226; Support content creators with Flattr integration including automatic flattring
-CONTROL THE SYSTEM<br>
+ĐIỀU KHIỂN HỆ THỐNG
&#8226; Take control over automated downloading: choose feeds, exclude mobile networks, select specific WiFi networks, require the phone to be charging and set times or intervals<br>
&#8226; Manage storage by setting the amount of cached episodes, smart deletion (based on your favourites and play status) and selecting your preferred location<br>
&#8226; Use AntennaPod in your language (EN, DE, CS, NL, NB, JA, PT, ES, SV, CA, UK, FR, KO, TR, ZH)<br>
&#8226; Adapt to your environment using the light and dark theme<br>
&#8226; Back-up your subscriptions with the gPodder.net integration and OPML export
-<b>Join the AntennaPod community!</b><br>
+Tham gia cộng đồng AntennaPod!
AntennaPod is under active development by volunteers. You can contribute too, with code or with comment!
GitHub is the place to go for feature requests, bug reports and code contributions:<br>
@@ -33,7 +33,7 @@ https://www.github.com/AntennaPod/AntennaPod
Our Google Group is the place to share your ideas, favourite podcasting moments and gratitude to all the volunteers:<br>
https://groups.google.com/forum/#!forum/antennapod
-Have a question or want to give us feedback?
+Có một thắc mắc hay muốn phản hồi cho chúng tôi?
https://twitter.com/@AntennaPod
Transifex is the place to help with translations:<br>
diff --git a/app/src/main/play/zh-CN/listing/video b/app/src/main/play/zh-CN/listing/video
deleted file mode 100644
index e69de29bb..000000000
--- a/app/src/main/play/zh-CN/listing/video
+++ /dev/null
diff --git a/app/src/main/res/layout-v14/authentication_dialog.xml b/app/src/main/res/layout-v14/authentication_dialog.xml
deleted file mode 100644
index 00e74c9e1..000000000
--- a/app/src/main/res/layout-v14/authentication_dialog.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical" >
-
- <EditText
- android:id="@+id/etxtUsername"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:layout_margin="16dp"
- android:hint="@string/username_label"
- android:focusable="true"
- android:focusableInTouchMode="true"
- android:cursorVisible="true"/>
-
- <EditText
- android:id="@+id/etxtPassword"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:layout_margin="16dp"
- android:inputType="textPassword"
- android:hint="@string/password_label"
- android:focusable="true"
- android:focusableInTouchMode="true"
- android:cursorVisible="true"/>
-
- <CheckBox
- android:id="@+id/chkSaveUsernamePassword"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_margin="16dp"
- android:text="@string/save_username_password_label"/>
- </LinearLayout>
-
- <RelativeLayout
- android:id="@+id/footer"
- android:layout_width="fill_parent"
- android:layout_height="48dp" >
-
- <View
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:layout_alignParentTop="true"
- android:background="?android:attr/dividerVertical" />
-
- <View
- android:id="@+id/horizontal_divider"
- android:layout_width="1dip"
- android:layout_height="fill_parent"
- android:layout_alignParentTop="true"
- android:layout_centerHorizontal="true"
- android:layout_marginBottom="4dp"
- android:layout_marginTop="4dp"
- android:background="?android:attr/dividerVertical" />
-
- <Button
- android:id="@+id/butCancel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:layout_toLeftOf="@id/horizontal_divider"
- android:background="?android:attr/selectableItemBackground"
- android:text="@string/cancel_label" />
-
- <Button
- android:id="@+id/butConfirm"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"
- android:layout_toRightOf="@id/horizontal_divider"
- android:background="?android:attr/selectableItemBackground"
- android:text="@string/confirm_label" />
- </RelativeLayout>
-
-</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout-v14/directory_chooser.xml b/app/src/main/res/layout-v14/directory_chooser.xml
deleted file mode 100644
index 14e2f6a38..000000000
--- a/app/src/main/res/layout-v14/directory_chooser.xml
+++ /dev/null
@@ -1,114 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:background="@android:color/darker_gray">
-
- <RelativeLayout
- android:id="@+id/footer"
- android:layout_width="fill_parent"
- android:layout_height="48dp"
- android:layout_alignParentBottom="true" >
-
- <View
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:layout_alignParentTop="true"
- android:background="?android:attr/dividerVertical" />
-
- <View
- android:id="@+id/horizontal_divider"
- android:layout_width="1dip"
- android:layout_height="fill_parent"
- android:layout_alignParentTop="true"
- android:layout_centerHorizontal="true"
- android:layout_marginBottom="4dp"
- android:layout_marginTop="4dp"
- android:background="?android:attr/dividerVertical" />
-
- <Button
- android:id="@+id/butCancel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:layout_toLeftOf="@id/horizontal_divider"
- android:background="?android:attr/selectableItemBackground"
- android:text="@string/cancel_label" />
-
- <Button
- android:id="@+id/butConfirm"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"
- android:layout_toRightOf="@id/horizontal_divider"
- android:background="?android:attr/selectableItemBackground"
- android:text="@string/confirm_label" />
- </RelativeLayout>
-
- <RelativeLayout
- android:id="@+id/directory_info"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true" >
-
- <ImageButton
- android:id="@+id/butNavUp"
- android:contentDescription="@string/navigate_upwards_label"
- android:layout_width="60dp"
- android:layout_height="60dp"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:background="?attr/selectableItemBackground"
- android:src="?attr/navigation_up"
- tools:src="@drawable/navigation_up"
- tools:background="@android:color/holo_green_dark" />
-
- <TextView
- android:id="@+id/txtvSelectedFolderLabel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:layout_marginLeft="8dp"
- android:layout_marginRight="8dp"
- android:layout_marginTop="8dp"
- android:layout_toRightOf="@id/butNavUp"
- android:text="@string/selected_folder_label"
- android:textStyle="bold"
- tools:background="@android:color/holo_green_dark">
- </TextView>
-
- <TextView
- android:id="@+id/txtvSelectedFolder"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_below="@id/txtvSelectedFolderLabel"
- android:layout_margin="8dp"
- android:layout_toRightOf="@id/butNavUp"
- android:ellipsize="start"
- android:scrollHorizontally="true"
- android:singleLine="true"
- tools:text="/path/to/selected/folder"
- tools:background="@android:color/holo_green_dark"/>
-
- <View
- android:id="@+id/divider"
- android:layout_width="match_parent"
- android:layout_height="1dp"
- android:layout_below="@id/butNavUp"
- android:background="@color/holo_blue_light" />
- </RelativeLayout>
-
- <ListView
- android:id="@+id/directory_list"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_above="@id/footer"
- android:layout_below="@id/directory_info" />
-
-</RelativeLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout-v14/download_authentication_activity.xml b/app/src/main/res/layout-v14/download_authentication_activity.xml
deleted file mode 100644
index f6925dc3a..000000000
--- a/app/src/main/res/layout-v14/download_authentication_activity.xml
+++ /dev/null
@@ -1,98 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <TextView
- android:id="@+id/txtvTitle"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/authentication_notification_title"
- android:layout_alignParentTop="true"
- android:textSize="@dimen/text_size_large"
- android:layout_margin="16dp"
- android:textColor="@color/holo_blue_light"
- android:textStyle="italic"/>
-
- <TextView
- android:id="@+id/txtvDescription"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/authentication_notification_msg"
- android:layout_below="@id/txtvTitle"
- android:textSize="@dimen/text_size_medium"
- android:textColor="?android:attr/textColorSecondary"
- android:layout_margin="16dp"/>
-
- <EditText
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_margin="16dp"
- android:id="@+id/etxtUsername"
- android:hint="@string/username_label"
- android:layout_below="@id/txtvDescription"
- android:focusable="true"
- android:focusableInTouchMode="true"
- android:cursorVisible="true"/>
-
- <EditText
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_margin="16dp"
- android:id="@+id/etxtPassword"
- android:hint="@string/password_label"
- android:inputType="textPassword"
- android:layout_below="@id/etxtUsername"
- android:focusable="true"
- android:focusableInTouchMode="true"
- android:cursorVisible="true"/>
-
- <RelativeLayout
- android:id="@+id/footer"
- android:layout_width="fill_parent"
- android:layout_height="48dp"
- android:focusableInTouchMode="true"
- android:layout_alignParentBottom="true">
-
- <View
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:layout_alignParentTop="true"
- android:background="?android:attr/dividerVertical"/>
-
- <View
- android:id="@+id/horizontal_divider"
- android:layout_width="1dip"
- android:layout_height="fill_parent"
- android:layout_alignParentTop="true"
- android:layout_centerHorizontal="true"
- android:layout_marginBottom="4dp"
- android:layout_marginTop="4dp"
- android:background="?android:attr/dividerVertical"/>
-
- <Button
- android:id="@+id/butCancel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:layout_toLeftOf="@id/horizontal_divider"
- android:background="?android:attr/selectableItemBackground"
- android:text="@string/cancel_label"/>
-
- <Button
- android:id="@+id/butConfirm"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"
- android:layout_toRightOf="@id/horizontal_divider"
- android:background="?android:attr/selectableItemBackground"
- android:text="@string/confirm_label"/>
- </RelativeLayout>
-
-
-</RelativeLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout-v14/opml_selection.xml b/app/src/main/res/layout-v14/opml_selection.xml
deleted file mode 100644
index 3133debd1..000000000
--- a/app/src/main/res/layout-v14/opml_selection.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <RelativeLayout
- android:id="@+id/footer"
- android:layout_width="fill_parent"
- android:layout_height="48dp"
- android:layout_alignParentBottom="true" >
-
- <View
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:layout_alignParentTop="true"
- android:background="?android:attr/dividerVertical" />
-
- <View
- android:id="@+id/horizontal_divider"
- android:layout_width="1dip"
- android:layout_height="fill_parent"
- android:layout_alignParentTop="true"
- android:layout_centerHorizontal="true"
- android:layout_marginBottom="4dp"
- android:layout_marginTop="4dp"
- android:background="?android:attr/dividerVertical" />
-
- <Button
- android:id="@+id/butCancel"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:layout_toLeftOf="@id/horizontal_divider"
- android:background="?android:attr/selectableItemBackground"
- android:text="@string/cancel_label" />
-
- <Button
- android:id="@+id/butConfirm"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"
- android:layout_toRightOf="@id/horizontal_divider"
- android:background="?android:attr/selectableItemBackground"
- android:text="@string/confirm_label" />
- </RelativeLayout>
-
- <ListView
- android:id="@+id/feedlist"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_above="@id/footer"
- android:layout_alignParentTop="true"
- tools:listitem="@android:layout/simple_list_item_multiple_choice" >
- </ListView>
-
-</RelativeLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout-v14/time_dialog.xml b/app/src/main/res/layout-v14/time_dialog.xml
deleted file mode 100644
index ba4249268..000000000
--- a/app/src/main/res/layout-v14/time_dialog.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:gravity="center">
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
-
- <EditText
- android:id="@+id/etxtTime"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_margin="8dp"
- android:ems="2"
- android:hint="@string/enter_time_here_label"
- android:inputType="number"
- android:maxLength="2" >
-
- <requestFocus />
- </EditText>
-
- <Spinner
- android:id="@+id/spTimeUnit"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="8dp"
- android:layout_marginTop="8dp" />
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:text="@string/timer_about_to_expire_label"
- android:textSize="16sp" />
-
- <CheckBox
- android:id="@+id/cbShakeToReset"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/shake_to_reset_label" />
-
- <CheckBox
- android:id="@+id/cbVibrate"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/timer_vibration_label" />
-
- <CheckBox
- android:id="@+id/chAutoEnable"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/auto_enable_label" />
-
- </LinearLayout>
-
-</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/about.xml b/app/src/main/res/layout/about.xml
index 02e232d9a..42f5e1245 100644
--- a/app/src/main/res/layout/about.xml
+++ b/app/src/main/res/layout/about.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/webvContainer"
+ android:id="@+id/webViewContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<WebView
- android:id="@+id/webvAbout"
+ android:id="@+id/webViewAbout"
android:layout_width="match_parent"
android:layout_height="match_parent" />
diff --git a/app/src/main/res/layout/all_episodes_fragment.xml b/app/src/main/res/layout/all_episodes_fragment.xml
index 5336fb8ce..7dd447bb2 100644
--- a/app/src/main/res/layout/all_episodes_fragment.xml
+++ b/app/src/main/res/layout/all_episodes_fragment.xml
@@ -13,7 +13,9 @@
android:scrollbarStyle="outsideOverlay"
android:paddingTop="@dimen/list_vertical_padding"
android:paddingBottom="@dimen/list_vertical_padding"
- android:clipToPadding="false"/>
+ android:clipToPadding="false"
+ tools:listitem="@layout/new_episodes_listitem"
+ tools:itemCount="13"/>
<ProgressBar
android:id="@+id/progLoading"
@@ -22,7 +24,7 @@
android:layout_gravity="center"
android:indeterminateOnly="true"
android:visibility="gone"
- tools:visibility="visible"
+ tools:visibility="gone"
tools:layout_width="match_parent"
tools:layout_height="64dp"
tools:background="@android:color/holo_red_light"/>
diff --git a/app/src/main/res/layout/authentication_dialog.xml b/app/src/main/res/layout/authentication_dialog.xml
index e18ab42eb..00e74c9e1 100644
--- a/app/src/main/res/layout/authentication_dialog.xml
+++ b/app/src/main/res/layout/authentication_dialog.xml
@@ -1,14 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical">
+ android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:orientation="vertical" >
<EditText
android:id="@+id/etxtUsername"
@@ -39,30 +38,50 @@
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="@string/save_username_password_label"/>
+ </LinearLayout>
+ <RelativeLayout
+ android:id="@+id/footer"
+ android:layout_width="fill_parent"
+ android:layout_height="48dp" >
- </LinearLayout>
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:layout_alignParentTop="true"
+ android:background="?android:attr/dividerVertical" />
- <LinearLayout
- style="@android:style/ButtonBar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
+ <View
+ android:id="@+id/horizontal_divider"
+ android:layout_width="1dip"
+ android:layout_height="fill_parent"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:layout_marginBottom="4dp"
+ android:layout_marginTop="4dp"
+ android:background="?android:attr/dividerVertical" />
<Button
- android:id="@+id/butConfirm"
- android:layout_width="0dp"
+ android:id="@+id/butCancel"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginRight="8dp"
- android:text="@string/confirm_label"
- android:layout_weight="1"/>
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_toLeftOf="@id/horizontal_divider"
+ android:background="?android:attr/selectableItemBackground"
+ android:text="@string/cancel_label" />
<Button
- android:id="@+id/butCancel"
- android:text="@string/cancel_label"
- android:layout_width="0dp"
+ android:id="@+id/butConfirm"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_weight="1"/>
- </LinearLayout>
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ android:layout_toRightOf="@id/horizontal_divider"
+ android:background="?android:attr/selectableItemBackground"
+ android:text="@string/confirm_label" />
+ </RelativeLayout>
</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/cover_fragment.xml b/app/src/main/res/layout/cover_fragment.xml
index 9ad1ff9c6..b1e93a195 100644
--- a/app/src/main/res/layout/cover_fragment.xml
+++ b/app/src/main/res/layout/cover_fragment.xml
@@ -16,6 +16,7 @@
android:scaleType="fitCenter"
app:layout_aspectRatio="100%"
app:layout_widthPercent="82%"
+ android:transitionName="coverTransition"
tools:src="@android:drawable/sym_def_app_icon" />
<LinearLayout
@@ -37,6 +38,7 @@
android:maxLines="2"
android:ellipsize="end"
android:text="Podcast"
+ android:textIsSelectable="true"
android:textColor="?android:attr/textColorSecondary" />
</LinearLayout>
@@ -60,6 +62,7 @@
android:maxLines="2"
android:ellipsize="end"
android:text="Episode"
+ android:textIsSelectable="true"
android:textColor="?android:attr/textColorPrimary" />
</LinearLayout>
diff --git a/app/src/main/res/layout/directory_chooser.xml b/app/src/main/res/layout/directory_chooser.xml
index 635a73cf4..14e2f6a38 100644
--- a/app/src/main/res/layout/directory_chooser.xml
+++ b/app/src/main/res/layout/directory_chooser.xml
@@ -2,30 +2,53 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
- android:layout_height="match_parent" >
+ android:layout_height="match_parent"
+ tools:background="@android:color/darker_gray">
- <LinearLayout
+ <RelativeLayout
android:id="@+id/footer"
- style="@android:style/ButtonBar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:orientation="horizontal" >
+ android:layout_width="fill_parent"
+ android:layout_height="48dp"
+ android:layout_alignParentBottom="true" >
- <Button
- android:id="@+id/butConfirm"
- android:layout_width="0px"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/confirm_label" />
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:layout_alignParentTop="true"
+ android:background="?android:attr/dividerVertical" />
+
+ <View
+ android:id="@+id/horizontal_divider"
+ android:layout_width="1dip"
+ android:layout_height="fill_parent"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:layout_marginBottom="4dp"
+ android:layout_marginTop="4dp"
+ android:background="?android:attr/dividerVertical" />
<Button
android:id="@+id/butCancel"
- android:layout_width="0px"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_weight="1"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_toLeftOf="@id/horizontal_divider"
+ android:background="?android:attr/selectableItemBackground"
android:text="@string/cancel_label" />
- </LinearLayout>
+
+ <Button
+ android:id="@+id/butConfirm"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ android:layout_toRightOf="@id/horizontal_divider"
+ android:background="?android:attr/selectableItemBackground"
+ android:text="@string/confirm_label" />
+ </RelativeLayout>
<RelativeLayout
android:id="@+id/directory_info"
@@ -56,7 +79,7 @@
android:layout_toRightOf="@id/butNavUp"
android:text="@string/selected_folder_label"
android:textStyle="bold"
- tools:background="@android:color/holo_blue_bright">
+ tools:background="@android:color/holo_green_dark">
</TextView>
<TextView
@@ -71,7 +94,7 @@
android:scrollHorizontally="true"
android:singleLine="true"
tools:text="/path/to/selected/folder"
- tools:background="@android:color/holo_blue_bright"/>
+ tools:background="@android:color/holo_green_dark"/>
<View
android:id="@+id/divider"
diff --git a/app/src/main/res/layout/download_authentication_activity.xml b/app/src/main/res/layout/download_authentication_activity.xml
index 27604973a..f6925dc3a 100644
--- a/app/src/main/res/layout/download_authentication_activity.xml
+++ b/app/src/main/res/layout/download_authentication_activity.xml
@@ -48,28 +48,51 @@
android:focusableInTouchMode="true"
android:cursorVisible="true"/>
- <LinearLayout
+ <RelativeLayout
android:id="@+id/footer"
- style="@android:style/ButtonBar"
android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:orientation="horizontal">
+ android:layout_height="48dp"
+ android:focusableInTouchMode="true"
+ android:layout_alignParentBottom="true">
- <Button
- android:id="@+id/butConfirm"
- android:layout_width="0px"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/confirm_label"/>
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:layout_alignParentTop="true"
+ android:background="?android:attr/dividerVertical"/>
+
+ <View
+ android:id="@+id/horizontal_divider"
+ android:layout_width="1dip"
+ android:layout_height="fill_parent"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:layout_marginBottom="4dp"
+ android:layout_marginTop="4dp"
+ android:background="?android:attr/dividerVertical"/>
<Button
android:id="@+id/butCancel"
- android:layout_width="0px"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_weight="1"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_toLeftOf="@id/horizontal_divider"
+ android:background="?android:attr/selectableItemBackground"
android:text="@string/cancel_label"/>
- </LinearLayout>
+
+ <Button
+ android:id="@+id/butConfirm"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ android:layout_toRightOf="@id/horizontal_divider"
+ android:background="?android:attr/selectableItemBackground"
+ android:text="@string/confirm_label"/>
+ </RelativeLayout>
</RelativeLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/downloaded_episodeslist_item.xml b/app/src/main/res/layout/downloaded_episodeslist_item.xml
index 760b6b9db..770b88c7e 100644
--- a/app/src/main/res/layout/downloaded_episodeslist_item.xml
+++ b/app/src/main/res/layout/downloaded_episodeslist_item.xml
@@ -1,9 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
- android:layout_height="@dimen/listitem_threeline_height"
+ android:layout_height="wrap_content"
android:orientation="horizontal"
tools:background="@android:color/darker_gray">
@@ -18,64 +17,68 @@
android:contentDescription="@string/cover_label"
android:scaleType="centerCrop"
tools:src="@drawable/ic_stat_antenna_default"
- tools:background="@android:color/holo_green_dark" />
+ tools:background="@android:color/holo_green_dark"/>
+
- <RelativeLayout
+ <LinearLayout
android:layout_width="0dp"
- android:layout_height="@dimen/thumbnail_length_downloaded_item"
+ android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/listitem_threeline_textleftpadding"
android:layout_marginRight="@dimen/listitem_threeline_textrightpadding"
android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
+ android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding"
android:layout_weight="1"
+ android:orientation="vertical"
tools:background="@android:color/holo_red_dark">
<TextView
android:id="@+id/txtvTitle"
style="@style/AntennaPod.TextView.ListItemPrimaryTitle"
- android:layout_width="0dp"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"
- android:layout_centerVertical="true"
android:layout_marginBottom="4dp"
tools:text="Downloaded episode title"
- tools:background="@android:color/holo_green_dark" />
+ tools:background="@android:color/holo_green_dark"/>
- <TextView
- android:id="@+id/txtvSize"
- style="@style/AntennaPod.TextView.ListItemSecondaryTitle"
- android:layout_width="wrap_content"
+ <LinearLayout
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentBottom="true"
- tools:text="23 MB"
- tools:background="@android:color/holo_green_dark" />
+ tools:background="@android:color/holo_red_dark" >
- <TextView
- android:id="@+id/txtvPublished"
- style="@style/AntennaPod.TextView.ListItemSecondaryTitle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_alignParentBottom="true"
- android:layout_marginLeft="8dp"
- tools:text="Jan 23"
- tools:background="@android:color/holo_green_dark" />
+ <TextView
+ android:id="@+id/txtvSize"
+ style="@style/AntennaPod.TextView.ListItemSecondaryTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ tools:text="23 MB"
+ tools:background="@android:color/holo_green_dark"/>
+
+ <View
+ android:layout_width="0dip"
+ android:layout_height="1dip"
+ android:layout_weight="1" />
+
+ <ImageView
+ android:id="@+id/imgvInPlaylist"
+ android:layout_width="@dimen/enc_icons_size"
+ android:layout_height="@dimen/enc_icons_size"
+ android:contentDescription="@string/in_queue_label"
+ android:src="?attr/stat_playlist"
+ android:visibility="visible"
+ tools:src="@drawable/ic_list_white_24dp"
+ tools:background="@android:color/holo_red_light"/>
- <ImageView
- android:id="@+id/imgvInPlaylist"
- android:layout_width="@dimen/enc_icons_size"
- android:layout_height="@dimen/enc_icons_size"
- android:layout_toLeftOf="@id/txtvPublished"
- android:layout_alignParentBottom="true"
- android:contentDescription="@string/in_queue_label"
- android:src="?attr/stat_playlist"
- android:visibility="visible"
- tools:src="@drawable/ic_list_white_24dp"
- tools:background="@android:color/holo_red_light" />
+ <TextView
+ android:id="@+id/txtvPublished"
+ style="@style/AntennaPod.TextView.ListItemSecondaryTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="8dp"
+ tools:text="Jan 23"
+ tools:background="@android:color/holo_green_dark"/>
- </RelativeLayout>
+ </LinearLayout>
+ </LinearLayout>
<include layout="@layout/vertical_list_divider"/>
diff --git a/app/src/main/res/layout/downloadlist_item.xml b/app/src/main/res/layout/downloadlist_item.xml
index e7694502b..97f3ac1a1 100644
--- a/app/src/main/res/layout/downloadlist_item.xml
+++ b/app/src/main/res/layout/downloadlist_item.xml
@@ -2,13 +2,13 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
- android:layout_height="@dimen/listitem_threeline_height"
+ android:layout_height="wrap_content"
android:orientation="horizontal"
tools:background="@android:color/darker_gray">
<LinearLayout
android:layout_width="0dp"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
diff --git a/app/src/main/res/layout/downloadlog_item.xml b/app/src/main/res/layout/downloadlog_item.xml
index 7b4773bca..712dda63e 100644
--- a/app/src/main/res/layout/downloadlog_item.xml
+++ b/app/src/main/res/layout/downloadlog_item.xml
@@ -8,12 +8,13 @@
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingBottom="8dp"
+ android:descendantFocusability="blocksDescendants"
tools:background="@android:color/darker_gray">
<com.joanzapata.iconify.widget.IconTextView
android:id="@+id/txtvIcon"
- android:layout_width="48dp"
- android:layout_height="48dp"
+ android:layout_width="48sp"
+ android:layout_height="48sp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:textSize="48sp"
diff --git a/app/src/main/res/layout/ellipsize_start_listitem.xml b/app/src/main/res/layout/ellipsize_start_listitem.xml
index f737b60d3..4a70ff982 100644
--- a/app/src/main/res/layout/ellipsize_start_listitem.xml
+++ b/app/src/main/res/layout/ellipsize_start_listitem.xml
@@ -13,7 +13,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/text_size_small"
- android:lines="1"
android:singleLine="true"
android:layout_margin="16dp"
android:ellipsize="start"
diff --git a/app/src/main/res/layout/external_player_fragment.xml b/app/src/main/res/layout/external_player_fragment.xml
index fb7abde55..dc890807c 100644
--- a/app/src/main/res/layout/external_player_fragment.xml
+++ b/app/src/main/res/layout/external_player_fragment.xml
@@ -1,89 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout
+<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/fragmentLayout"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:visibility="gone">
+ android:layout_height="@dimen/external_player_height"
+ android:visibility="gone"
+ android:background="?attr/selectableItemBackground">
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="@dimen/external_player_height">
-
- <ImageView
- android:id="@+id/imgvCover"
- android:contentDescription="@string/cover_label"
- android:layout_width="@dimen/external_player_height"
- android:layout_height="@dimen/external_player_height"
- android:adjustViewBounds="true"
- android:cropToPadding="true"
- android:scaleType="centerCrop"
- tools:src="@drawable/ic_drag_vertical_white_48dp"
- tools:background="@android:color/holo_green_dark"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"/>
+ <ImageView
+ android:id="@+id/imgvCover"
+ android:contentDescription="@string/cover_label"
+ android:layout_width="@dimen/external_player_height"
+ android:layout_height="@dimen/external_player_height"
+ android:adjustViewBounds="true"
+ android:cropToPadding="true"
+ android:scaleType="centerCrop"
+ tools:src="@drawable/ic_drag_vertical_white_48dp"
+ tools:background="@android:color/holo_green_dark"
+ android:transitionName="coverTransition"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"/>
- <ProgressBar
- android:id="@+id/episodeProgress"
- android:layout_width="match_parent"
- android:layout_height="4dp"
- android:layout_toRightOf="@id/imgvCover"
- android:layout_toEndOf="@id/imgvCover"
- android:layout_alignParentTop="true"
- style="?attr/progressBarTheme"
- android:indeterminate="false"
- tools:progress="100"/>
-
- <ImageButton
- android:id="@+id/butPlay"
- android:layout_width="52dp"
- android:layout_height="52dp"
- android:layout_alignParentRight="true"
- android:layout_alignParentEnd="true"
- android:layout_below="@id/episodeProgress"
- android:layout_centerVertical="true"
- android:contentDescription="@string/pause_label"
- android:background="?attr/selectableItemBackground"
- tools:src="@drawable/ic_play_arrow_white_36dp"/>
+ <ProgressBar
+ android:id="@+id/episodeProgress"
+ android:layout_width="match_parent"
+ android:layout_height="4dp"
+ android:layout_toRightOf="@id/imgvCover"
+ android:layout_toEndOf="@id/imgvCover"
+ android:layout_alignParentTop="true"
+ style="?attr/progressBarTheme"
+ android:indeterminate="false"
+ tools:progress="100"/>
- <TextView
- android:id="@+id/txtvTitle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_marginBottom="26dp"
- android:layout_toRightOf="@id/imgvCover"
- android:layout_toEndOf="@id/imgvCover"
- android:layout_marginLeft="16dp"
- android:layout_marginStart="16dp"
- android:layout_toLeftOf="@id/butPlay"
- android:layout_toStartOf="@id/butPlay"
- style="@style/Base.TextAppearance.AppCompat.Body1"
- android:ellipsize="end"
- android:maxLines="1"
- tools:text="Episode title that is too long and will cause the text to wrap"/>
+ <ImageButton
+ android:id="@+id/butPlay"
+ android:layout_width="52dp"
+ android:layout_height="52dp"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentEnd="true"
+ android:layout_below="@id/episodeProgress"
+ android:layout_centerVertical="true"
+ android:contentDescription="@string/pause_label"
+ android:background="?attr/selectableItemBackground"
+ android:src="?attr/av_play_big"
+ tools:src="@drawable/ic_play_arrow_white_36dp"/>
- <TextView
- android:id="@+id/txtvAuthor"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/episodeProgress"
- android:layout_marginTop="26dp"
- android:layout_toRightOf="@id/imgvCover"
- android:layout_toEndOf="@id/imgvCover"
- android:layout_marginLeft="16dp"
- android:layout_marginStart="16dp"
- android:layout_toLeftOf="@id/butPlay"
- android:layout_toStartOf="@id/butPlay"
- style="@style/TextAppearance.AppCompat.Body1"
- android:textColor="?android:attr/textColorSecondary"
- android:ellipsize="end"
- android:maxLines="1"
- tools:text="Episode author that is too long and will cause the text to wrap"/>
+ <TextView
+ android:id="@+id/txtvTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_marginBottom="26dp"
+ android:layout_toRightOf="@id/imgvCover"
+ android:layout_toEndOf="@id/imgvCover"
+ android:layout_marginLeft="16dp"
+ android:layout_marginStart="16dp"
+ android:layout_toLeftOf="@id/butPlay"
+ android:layout_toStartOf="@id/butPlay"
+ style="@style/Base.TextAppearance.AppCompat.Body1"
+ android:ellipsize="end"
+ android:maxLines="1"
+ tools:text="Episode title that is too long and will cause the text to wrap"/>
- </RelativeLayout>
+ <TextView
+ android:id="@+id/txtvAuthor"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/episodeProgress"
+ android:layout_marginTop="26dp"
+ android:layout_toRightOf="@id/imgvCover"
+ android:layout_toEndOf="@id/imgvCover"
+ android:layout_marginLeft="16dp"
+ android:layout_marginStart="16dp"
+ android:layout_toLeftOf="@id/butPlay"
+ android:layout_toStartOf="@id/butPlay"
+ style="@style/TextAppearance.AppCompat.Body1"
+ android:textColor="?android:attr/textColorSecondary"
+ android:ellipsize="end"
+ android:maxLines="1"
+ tools:text="Episode author that is too long and will cause the text to wrap"/>
-</LinearLayout>
+</RelativeLayout>
diff --git a/app/src/main/res/layout/feedinfo.xml b/app/src/main/res/layout/feedinfo.xml
index 4b545e3cc..bb544d289 100644
--- a/app/src/main/res/layout/feedinfo.xml
+++ b/app/src/main/res/layout/feedinfo.xml
@@ -6,48 +6,7 @@
android:layout_height="match_parent"
android:orientation="vertical">
- <RelativeLayout
- android:id="@+id/header"
- android:focusable="true"
- android:focusableInTouchMode="true"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
- android:layout_marginTop="8dp">
-
- <ImageView
- android:id="@+id/imgvCover"
- android:contentDescription="@string/cover_label"
- android:layout_width="80dp"
- android:layout_height="80dp"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- tools:src="@drawable/ic_stat_antenna_default"
- tools:background="@android:color/holo_green_dark"/>
-
- <TextView
- android:id="@+id/txtvTitle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_marginLeft="8dp"
- android:layout_alignTop="@id/imgvCover"
- android:layout_toRightOf="@id/imgvCover"
- android:layout_alignBottom="@id/imgvCover"
- style="@style/AntennaPod.TextView.Heading"
- tools:text="Feed title"
- tools:background="@android:color/holo_green_dark"/>
-
- <View
- android:id="@+id/divider"
- android:layout_width="match_parent"
- android:layout_height="1dp"
- android:layout_below="@id/imgvCover"
- android:layout_marginTop="8dp"
- android:background="@color/holo_blue_light"/>
- </RelativeLayout>
+ <include layout="@layout/feeditemlist_header" />
<ScrollView
android:id="@+id/scrollView"
@@ -57,7 +16,8 @@
android:scrollbarStyle="outsideOverlay"
android:paddingLeft="16dp"
android:paddingRight="16dp"
- android:paddingBottom="8dp">
+ android:paddingBottom="8dp"
+ android:clipToPadding="false">
<LinearLayout
android:layout_width="match_parent"
@@ -86,9 +46,10 @@
tools:background="@android:color/holo_red_light"/>
<TextView
- android:id="@+id/txtvAuthor"
+ android:id="@+id/txtvDetailsAuthor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:textIsSelectable="true"
app:layout_row="0"
app:layout_column="1"
tools:text="Daniel Oeh"
@@ -111,6 +72,7 @@
android:id="@+id/txtvLanguage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:textIsSelectable="true"
app:layout_row="1"
app:layout_column="1"
tools:text="English"
@@ -133,6 +95,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingBottom="4dp"
+ android:background="?attr/selectableItemBackground"
app:layout_row="2"
app:layout_column="1"
app:layout_gravity="fill"
@@ -143,200 +106,6 @@
</android.support.v7.widget.GridLayout>
<TextView
- android:id="@+id/txtvSettings"
- style="@style/AntennaPod.TextView.Heading"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/podcast_settings_label"
- android:layout_marginTop="8dp"/>
-
- <android.support.v7.widget.GridLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- app:columnCount="2"
- app:rowCount="1">
-
- <TextView
- android:id="@+id/txtvFeedAutoDelete"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/auto_delete_label"
- app:layout_row="0"
- app:layout_column="0"
- app:layout_gravity="center_vertical"
- android:layout_marginRight="10dp" />
-
- <Spinner
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:id="@+id/spnAutoDelete"
- android:entries="@array/spnAutoDeleteItems"
- android:layout_marginTop="8dp"
- app:layout_row="0"
- app:layout_column="1"
- android:spinnerMode="dropdown"
- app:layout_gravity="center"
- android:dropDownWidth="wrap_content"
- android:clickable="true" />
- </android.support.v7.widget.GridLayout>
-
- <CheckBox
- android:id="@+id/cbxKeepUpdated"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:text="@string/keep_updated"
- android:enabled="true"
- android:textColor="?android:attr/textColorPrimary"
- tools:background="@android:color/holo_red_light"
- android:checked="true" />
-
- <TextView
- android:id="@+id/txtvAuthentication"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:text="@string/authentication_label"
- android:textSize="@dimen/text_size_medium"
- android:textColor="?android:attr/textColorPrimary"/>
-
- <TextView
- android:id="@+id/txtvAuthenticationDescr"
- android:text="@string/authentication_descr"
- android:textSize="@dimen/text_size_small"
- android:textColor="?android:attr/textColorPrimary"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"/>
-
- <android.support.v7.widget.GridLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- app:columnCount="2"
- app:rowCount="3"
- android:layout_gravity="center_horizontal">
-
- <TextView
- android:id="@+id/txtvUsername"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="8dp"
- android:layout_marginBottom="8dp"
- app:layout_row="0"
- app:layout_column="0"
- android:text="@string/username_label"
- android:textColor="?android:attr/textColorPrimary"/>
-
- <EditText
- android:id="@+id/etxtUsername"
- android:layout_width="140sp"
- android:layout_height="wrap_content"
- app:layout_row="0"
- app:layout_column="1"
- android:hint="@string/username_label"
- android:focusable="true"
- android:focusableInTouchMode="true"
- android:cursorVisible="true"/>
-
- <TextView
- android:id="@+id/txtvPassword"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="8dp"
- android:layout_marginBottom="8dp"
- app:layout_row="1"
- app:layout_column="0"
- android:text="@string/password_label"
- android:textColor="?android:attr/textColorPrimary"
- android:focusable="true"
- android:focusableInTouchMode="true"
- android:cursorVisible="true"/>
-
- <EditText
- android:id="@+id/etxtPassword"
- android:layout_width="140sp"
- android:layout_height="wrap_content"
- app:layout_row="1"
- app:layout_column="1"
- android:hint="@string/password_label"
- android:inputType="textPassword"/>
-
- </android.support.v7.widget.GridLayout>
-
- <TextView
- android:id="@+id/txtvAutoDownloadSettings"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:text="@string/auto_download_settings_label"
- android:textSize="@dimen/text_size_medium"
- android:textColor="?android:attr/textColorPrimary"/>
-
- <CheckBox
- android:id="@+id/cbxAutoDownload"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:text="@string/auto_download_label"
- android:enabled="false"
- android:textColor="?android:attr/textColorPrimary"
- tools:background="@android:color/holo_red_light"
- android:checked="false" />
-
- <TextView
- android:id="@+id/txtvEpisodeFilters"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:text="@string/episode_filters_label"
- android:textSize="@dimen/text_size_medium"
- android:textColor="?android:attr/textColorPrimary"/>
-
- <TextView
- android:id="@+id/txtvEpisodeFiltersDescription"
- android:text="@string/episode_filters_description"
- android:textSize="@dimen/text_size_small"
- android:textColor="?android:attr/textColorPrimary"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"/>
-
- <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/radio_filter_group"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:gravity="center"
- android:orientation="horizontal">
- <RadioButton android:id="@+id/radio_filter_include"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/episode_filters_include"
- android:onClick="onRadioButtonClicked"/>
- <RadioButton android:id="@+id/radio_filter_exclude"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/episode_filters_exclude"
- android:onClick="onRadioButtonClicked"/>
- </RadioGroup>
-
- <EditText
- android:id="@+id/etxtEpisodeFilterText"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:lines="8"
- android:minLines="1"
- android:maxLines="20"
- android:scrollbars="vertical"
- android:hint="@string/episode_filters_hint"
- android:focusable="true"
- android:focusableInTouchMode="true"
- android:cursorVisible="true"/>
-
- <TextView
style="@style/AntennaPod.TextView.Heading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -348,6 +117,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
+ android:textIsSelectable="true"
android:text="@string/design_time_lorem_ipsum"
tools:background="@android:color/holo_green_dark"/>
diff --git a/app/src/main/res/layout/feeditemlist_header.xml b/app/src/main/res/layout/feeditemlist_header.xml
index 361b583c9..1478e35d7 100644
--- a/app/src/main/res/layout/feeditemlist_header.xml
+++ b/app/src/main/res/layout/feeditemlist_header.xml
@@ -4,6 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:background="@color/feed_image_bg"
tools:context="de.danoeh.antennapod.activity.MainActivity"
tools:background="@android:color/darker_gray">
@@ -29,11 +30,10 @@
<ImageButton
android:id="@+id/butShowInfo"
- android:layout_width="48dp"
- android:layout_height="48dp"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
- android:layout_marginBottom="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="8dp"
android:background="?attr/selectableItemBackground"
@@ -41,6 +41,19 @@
android:src="@drawable/ic_info_white_24dp"
tools:background="@android:color/holo_green_dark"/>
+ <ImageButton
+ android:id="@+id/butShowSettings"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
+ android:background="?attr/selectableItemBackground"
+ android:contentDescription="@string/show_feed_settings_label"
+ android:src="@drawable/ic_settings_white_24dp"
+ tools:background="@android:color/holo_green_dark"
+ android:layout_below="@+id/butShowInfo"
+ android:layout_marginBottom="16dp"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentEnd="true"/>
+
<TextView
android:id="@+id/txtvTitle"
style="@style/AntennaPod.TextView.Heading"
@@ -62,12 +75,12 @@
<TextView
android:id="@+id/txtvAuthor"
- android:layout_width="wrap_content"
+ android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_below="@id/txtvTitle"
android:layout_marginBottom="16dp"
android:layout_marginLeft="16dp"
- android:layout_marginRight="16dp"
+ android:layout_toLeftOf="@id/butShowSettings"
android:layout_toRightOf="@id/imgvCover"
android:ellipsize="end"
android:lines="1"
@@ -76,7 +89,7 @@
android:textColor="@color/white"
android:textSize="@dimen/text_size_small"
tools:text="Podcast author"
- tools:background="@android:color/holo_green_dark" />
+ tools:background="@android:color/holo_green_dark"/>
<com.joanzapata.iconify.widget.IconTextView
android:id="@+id/txtvFailure"
diff --git a/app/src/main/res/layout/feeditemlist_item.xml b/app/src/main/res/layout/feeditemlist_item.xml
index d2b85e7df..5a2f091ec 100644
--- a/app/src/main/res/layout/feeditemlist_item.xml
+++ b/app/src/main/res/layout/feeditemlist_item.xml
@@ -5,7 +5,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
- android:layout_height="@dimen/listitem_threeline_height"
+ android:layout_height="wrap_content"
android:orientation="horizontal"
tools:background="@android:color/darker_gray">
@@ -14,6 +14,8 @@
android:layout_height="match_parent"
android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding"
android:layout_weight="1"
+ android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
+ android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding"
tools:background="@android:color/holo_orange_dark">
<TextView
@@ -23,7 +25,6 @@
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
- android:layout_marginTop="16dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
tools:text="NEW"
@@ -36,8 +37,7 @@
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
- android:layout_marginBottom="8dp"
- android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
+ android:layout_marginBottom="4dp"
android:layout_toLeftOf="@id/statusUnread"
tools:text="Episode title"
tools:background="@android:color/holo_green_dark" />
@@ -101,8 +101,7 @@
tools:background="@android:color/holo_blue_light"
android:max="100"
android:progress="42"
- android:indeterminate="false"
- />
+ android:indeterminate="false" />
</RelativeLayout>
diff --git a/app/src/main/res/layout/feedsettings.xml b/app/src/main/res/layout/feedsettings.xml
new file mode 100644
index 000000000..23d116d4c
--- /dev/null
+++ b/app/src/main/res/layout/feedsettings.xml
@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <include layout="@layout/feeditemlist_header" />
+
+ <ScrollView
+ android:id="@+id/scrollView"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:scrollbarStyle="outsideOverlay"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:paddingBottom="8dp"
+ android:clipToPadding="false">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <android.support.v7.widget.GridLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ app:columnCount="2"
+ app:rowCount="1">
+
+ <TextView
+ android:id="@+id/txtvFeedAutoDelete"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/auto_delete_label"
+ app:layout_row="0"
+ app:layout_column="0"
+ app:layout_gravity="center_vertical"
+ android:layout_marginRight="10dp" />
+
+ <Spinner
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:id="@+id/spnAutoDelete"
+ android:entries="@array/spnAutoDeleteItems"
+ android:layout_marginTop="8dp"
+ app:layout_row="0"
+ app:layout_column="1"
+ android:spinnerMode="dropdown"
+ app:layout_gravity="center"
+ android:dropDownWidth="wrap_content"
+ android:clickable="true" />
+ </android.support.v7.widget.GridLayout>
+
+ <CheckBox
+ android:id="@+id/cbxKeepUpdated"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="@string/keep_updated"
+ android:enabled="true"
+ android:textColor="?android:attr/textColorPrimary"
+ tools:background="@android:color/holo_red_light"
+ android:checked="true" />
+
+ <TextView
+ android:id="@+id/txtvAuthentication"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="@string/authentication_label"
+ android:textSize="@dimen/text_size_medium"
+ android:textColor="?android:attr/textColorPrimary"/>
+
+ <TextView
+ android:id="@+id/txtvAuthenticationDescr"
+ android:text="@string/authentication_descr"
+ android:textSize="@dimen/text_size_small"
+ android:textColor="?android:attr/textColorPrimary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"/>
+
+ <android.support.v7.widget.GridLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ app:columnCount="2"
+ app:rowCount="3"
+ android:layout_gravity="center_horizontal">
+
+ <TextView
+ android:id="@+id/txtvUsername"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="8dp"
+ android:layout_marginBottom="8dp"
+ app:layout_row="0"
+ app:layout_column="0"
+ android:text="@string/username_label"
+ android:textColor="?android:attr/textColorPrimary"/>
+
+ <EditText
+ android:id="@+id/etxtUsername"
+ android:layout_width="140sp"
+ android:layout_height="wrap_content"
+ app:layout_row="0"
+ app:layout_column="1"
+ android:hint="@string/username_label"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:cursorVisible="true"/>
+
+ <TextView
+ android:id="@+id/txtvPassword"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="8dp"
+ android:layout_marginBottom="8dp"
+ app:layout_row="1"
+ app:layout_column="0"
+ android:text="@string/password_label"
+ android:textColor="?android:attr/textColorPrimary" />
+
+ <EditText
+ android:id="@+id/etxtPassword"
+ android:layout_width="140sp"
+ android:layout_height="wrap_content"
+ app:layout_row="1"
+ app:layout_column="1"
+ android:hint="@string/password_label"
+ android:inputType="textPassword"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:cursorVisible="true"/>
+
+ </android.support.v7.widget.GridLayout>
+
+ <TextView
+ android:id="@+id/txtvAutoDownloadSettings"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="@string/auto_download_settings_label"
+ android:textSize="@dimen/text_size_medium"
+ android:textColor="?android:attr/textColorPrimary"/>
+
+ <CheckBox
+ android:id="@+id/cbxAutoDownload"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="@string/auto_download_label"
+ android:enabled="false"
+ android:textColor="?android:attr/textColorPrimary"
+ tools:background="@android:color/holo_red_light"
+ android:checked="false" />
+
+ <TextView
+ android:id="@+id/txtvEpisodeFilters"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="@string/episode_filters_label"
+ android:textSize="@dimen/text_size_medium"
+ android:textColor="?android:attr/textColorPrimary"/>
+
+ <TextView
+ android:id="@+id/txtvEpisodeFiltersDescription"
+ android:text="@string/episode_filters_description"
+ android:textSize="@dimen/text_size_small"
+ android:textColor="?android:attr/textColorPrimary"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"/>
+
+ <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/radio_filter_group"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:gravity="center"
+ android:orientation="horizontal">
+ <RadioButton android:id="@+id/radio_filter_include"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/episode_filters_include" />
+ <RadioButton android:id="@+id/radio_filter_exclude"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/episode_filters_exclude" />
+ </RadioGroup>
+
+ <EditText
+ android:id="@+id/etxtEpisodeFilterText"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:lines="8"
+ android:minLines="1"
+ android:maxLines="20"
+ android:scrollbars="vertical"
+ android:hint="@string/episode_filters_hint"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:cursorVisible="true"/>
+
+ </LinearLayout>
+
+ </ScrollView>
+
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/import_export_activity.xml b/app/src/main/res/layout/import_export_activity.xml
new file mode 100644
index 000000000..97ff34e41
--- /dev/null
+++ b/app/src/main/res/layout/import_export_activity.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:id="@+id/import_export_layout"
+ android:padding="8dp"
+ android:clipToPadding="false">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/import_export_warning"
+ android:gravity="center_horizontal"/>
+
+ <Button
+ android:text="@string/label_export"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/button_export"
+ android:layout_marginTop="24dp"/>
+
+ <Button
+ android:text="@string/label_import"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/button_import"/>
+ </LinearLayout>
+</ScrollView>
diff --git a/app/src/main/res/layout/main.xml b/app/src/main/res/layout/main.xml
index c05132b42..6cabcdff2 100644
--- a/app/src/main/res/layout/main.xml
+++ b/app/src/main/res/layout/main.xml
@@ -6,7 +6,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ <RelativeLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
diff --git a/app/src/main/res/layout/mediaplayerinfo_activity.xml b/app/src/main/res/layout/mediaplayerinfo_activity.xml
index 0f68b503e..21c4940b5 100644
--- a/app/src/main/res/layout/mediaplayerinfo_activity.xml
+++ b/app/src/main/res/layout/mediaplayerinfo_activity.xml
@@ -110,9 +110,9 @@
android:layout_centerHorizontal="true"
android:background="?attr/selectableItemBackground"
android:contentDescription="@string/pause_label"
- android:src="?attr/av_pause"
+ android:src="?attr/av_play"
android:scaleType="fitCenter"
- tools:src="@drawable/ic_pause_white_36dp"
+ tools:src="@drawable/ic_play_arrow_white_24dp"
tools:background="@android:color/holo_green_dark" />
<ImageButton
@@ -152,6 +152,7 @@
android:src="?attr/av_fast_forward"
android:textSize="@dimen/text_size_medium"
android:textAllCaps="false"
+ android:maxLines="1"
tools:visibility="gone"
tools:background="@android:color/holo_green_dark" />
diff --git a/app/src/main/res/layout/nav_list.xml b/app/src/main/res/layout/nav_list.xml
index 7e72bb39b..e2fe61e28 100644
--- a/app/src/main/res/layout/nav_list.xml
+++ b/app/src/main/res/layout/nav_list.xml
@@ -15,7 +15,8 @@
android:layout_alignParentBottom="true"
android:background="?attr/selectableItemBackground"
android:contentDescription="@string/settings_label"
- android:orientation="horizontal">
+ android:orientation="horizontal"
+ android:focusable="true">
<ImageView
android:id="@+id/imgvCover"
@@ -31,7 +32,7 @@
android:scaleType="centerCrop"
android:src="?attr/ic_settings"
tools:background="@android:color/holo_orange_dark"
- tools:src="@android:drawable/sym_def_app_icon"></ImageView>
+ tools:src="@android:drawable/sym_def_app_icon" />
<TextView
android:layout_width="wrap_content"
@@ -69,5 +70,5 @@
android:paddingTop="@dimen/list_vertical_padding"
android:scrollbarStyle="outsideOverlay"
tools:background="@android:color/holo_purple"
- tools:listitem="@layout/nav_listitem"></ListView>
+ tools:listitem="@layout/nav_listitem" />
</RelativeLayout>
diff --git a/app/src/main/res/layout/new_episodes_listitem.xml b/app/src/main/res/layout/new_episodes_listitem.xml
index 944711aec..5e0d7451b 100644
--- a/app/src/main/res/layout/new_episodes_listitem.xml
+++ b/app/src/main/res/layout/new_episodes_listitem.xml
@@ -10,10 +10,10 @@
<LinearLayout
android:id="@+id/content"
android:layout_width="match_parent"
- android:layout_height="@dimen/listitem_threeline_height"
+ android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:orientation="horizontal"
- tools:background="@android:color/darker_gray">
+ android:gravity="center_vertical">
<RelativeLayout
android:layout_width="wrap_content"
@@ -41,20 +41,18 @@
android:layout_alignRight="@id/txtvPlaceholder"
android:layout_alignBottom="@id/txtvPlaceholder"
android:contentDescription="@string/cover_label"
- tools:src="@drawable/ic_stat_antenna_default"
- tools:background="@android:color/holo_green_dark" />
+ tools:src="@tools:sample/avatars" />
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding"
android:layout_marginLeft="@dimen/listitem_threeline_textleftpadding"
android:layout_marginRight="@dimen/listitem_threeline_textrightpadding"
android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
- android:layout_weight="1"
- tools:background="@android:color/white" >
+ android:layout_weight="1">
<TextView
@@ -64,7 +62,8 @@
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
- android:layout_marginLeft="8dp"/>
+ android:layout_marginLeft="8dp"
+ tools:text="@sample/episodes.json/data/status_label"/>
<TextView
android:id="@+id/txtvTitle"
@@ -74,8 +73,7 @@
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_toLeftOf="@id/statusUnread"
- tools:text="Episode title"
- tools:background="@android:color/holo_green_dark" />
+ tools:text="@sample/episodes.json/data/title" />
<RelativeLayout
android:id="@+id/bottom_bar"
@@ -84,8 +82,7 @@
android:layout_below="@id/txtvTitle"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
- android:layout_alignParentRight="true"
- tools:background="@android:color/holo_red_light" >
+ android:layout_alignParentRight="true">
<TextView
android:id="@+id/txtvDuration"
@@ -93,8 +90,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
- tools:text="00:42:23"
- tools:background="@android:color/holo_blue_dark" />
+ tools:text="@sample/episodes.json/data/duration" />
<ImageView
android:id="@+id/imgvInPlaylist"
@@ -104,8 +100,7 @@
android:layout_marginLeft="8dp"
android:contentDescription="@string/in_queue_label"
android:src="?attr/stat_playlist"
- tools:src="@drawable/ic_list_grey600_24dp"
- tools:background="@android:color/black" />
+ tools:src="@sample/inplaylist" />
<TextView
android:id="@+id/txtvPublished"
@@ -115,16 +110,14 @@
android:layout_alignParentTop="true"
android:layout_toLeftOf="@id/imgvInPlaylist"
android:ellipsize="end"
- tools:text="Jan 23"
- tools:background="@android:color/holo_green_dark" />
+ tools:text="@sample/episodes.json/data/published_at" />
<ProgressBar
android:id="@+id/pbar_progress"
- style="?android:attr/progressBarStyleHorizontal"
+ style="?attr/progressBarTheme"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="4dp"
android:layout_below="@id/txtvDuration"
- android:layout_marginTop="-2dp"
android:max="100" />
</RelativeLayout>
diff --git a/app/src/main/res/layout/numberpicker.xml b/app/src/main/res/layout/numberpicker.xml
new file mode 100644
index 000000000..813326bd6
--- /dev/null
+++ b/app/src/main/res/layout/numberpicker.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="32dp">
+
+ <EditText
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:inputType="numberDecimal"
+ android:ems="10"
+ android:selectAllOnFocus="true"
+ android:id="@+id/number" />
+
+</LinearLayout>
diff --git a/app/src/main/res/layout/opml_import.xml b/app/src/main/res/layout/opml_import.xml
index 2a67e7ee1..ac75cb8b3 100644
--- a/app/src/main/res/layout/opml_import.xml
+++ b/app/src/main/res/layout/opml_import.xml
@@ -6,7 +6,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="8dp"
android:paddingLeft="16dp"
diff --git a/app/src/main/res/layout/opml_selection.xml b/app/src/main/res/layout/opml_selection.xml
index d08ebd0bd..3133debd1 100644
--- a/app/src/main/res/layout/opml_selection.xml
+++ b/app/src/main/res/layout/opml_selection.xml
@@ -4,28 +4,50 @@
android:layout_width="match_parent"
android:layout_height="match_parent" >
- <LinearLayout
+ <RelativeLayout
android:id="@+id/footer"
- style="@android:style/ButtonBar"
android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:orientation="horizontal" >
+ android:layout_height="48dp"
+ android:layout_alignParentBottom="true" >
- <Button
- android:id="@+id/butConfirm"
- android:layout_width="0px"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/confirm_label" />
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:layout_alignParentTop="true"
+ android:background="?android:attr/dividerVertical" />
+
+ <View
+ android:id="@+id/horizontal_divider"
+ android:layout_width="1dip"
+ android:layout_height="fill_parent"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:layout_marginBottom="4dp"
+ android:layout_marginTop="4dp"
+ android:background="?android:attr/dividerVertical" />
<Button
android:id="@+id/butCancel"
- android:layout_width="0px"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_weight="1"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:layout_toLeftOf="@id/horizontal_divider"
+ android:background="?android:attr/selectableItemBackground"
android:text="@string/cancel_label" />
- </LinearLayout>
+
+ <Button
+ android:id="@+id/butConfirm"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ android:layout_toRightOf="@id/horizontal_divider"
+ android:background="?android:attr/selectableItemBackground"
+ android:text="@string/confirm_label" />
+ </RelativeLayout>
<ListView
android:id="@+id/feedlist"
diff --git a/app/src/main/res/layout/player_widget.xml b/app/src/main/res/layout/player_widget.xml
deleted file mode 100644
index d9f442f96..000000000
--- a/app/src/main/res/layout/player_widget.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:padding="@dimen/widget_margin" >
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="#262C31" >
-
- <ImageButton
- android:id="@+id/butPlay"
- android:contentDescription="@string/play_label"
- android:layout_width="56dp"
- android:layout_height="match_parent"
- android:layout_alignParentRight="true"
- android:layout_margin="12dp"
- android:background="@drawable/borderless_button_dark"
- android:src="@drawable/ic_play_arrow_white_24dp" />
-
- <LinearLayout
- android:id="@+id/layout_left"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_alignParentLeft="true"
- android:layout_toLeftOf="@id/butPlay"
- android:background="@drawable/borderless_button_dark"
- android:gravity="center_vertical"
- android:orientation="vertical" >
-
- <TextView
- android:id="@+id/txtvTitle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_margin="8dp"
- android:maxLines="1"
- android:text="@string/no_media_playing_label"
- android:textColor="@color/white"
- android:textSize="@dimen/text_size_medium"
- android:textStyle="bold" />
-
- <TextView
- android:id="@+id/txtvProgress"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_margin="8dp"
- android:textColor="?android:attr/textColorSecondary" />
- </LinearLayout>
- </RelativeLayout>
-
-</FrameLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/preference_switch_layout.xml b/app/src/main/res/layout/preference_switch_layout.xml
deleted file mode 100644
index 54fa74061..000000000
--- a/app/src/main/res/layout/preference_switch_layout.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<android.support.v7.widget.SwitchCompat
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@android:id/checkbox"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@null"
- android:clickable="false"
- android:focusable="false" /> \ No newline at end of file
diff --git a/app/src/main/res/layout/queue_listitem.xml b/app/src/main/res/layout/queue_listitem.xml
index 8de80e355..7d18b386d 100644
--- a/app/src/main/res/layout/queue_listitem.xml
+++ b/app/src/main/res/layout/queue_listitem.xml
@@ -9,7 +9,7 @@
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="@dimen/listitem_threeline_height"
+ android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:orientation="horizontal"
android:gravity="center_vertical"
@@ -122,11 +122,10 @@
<ProgressBar
android:id="@+id/progressBar"
- style="?android:attr/progressBarStyleHorizontal"
+ style="?attr/progressBarTheme"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="4dp"
android:layout_below="@id/txtvProgressLeft"
- android:layout_marginTop="-2dp"
android:max="100"
tools:background="@android:color/holo_blue_light" />
diff --git a/app/src/main/res/layout/searchlist_item.xml b/app/src/main/res/layout/searchlist_item.xml
index a8b8e7b62..83ba39cd5 100644
--- a/app/src/main/res/layout/searchlist_item.xml
+++ b/app/src/main/res/layout/searchlist_item.xml
@@ -2,8 +2,10 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
- android:layout_height="@dimen/listitem_threeline_height"
- tools:background="@android:color/darker_gray">
+ android:layout_height="wrap_content"
+ tools:background="@android:color/darker_gray"
+ android:paddingTop="@dimen/listitem_threeline_verticalpadding"
+ android:paddingBottom="@dimen/listitem_threeline_verticalpadding">
<ImageView
android:id="@+id/imgvFeedimage"
@@ -11,9 +13,7 @@
android:layout_height="@dimen/thumbnail_length_itemlist"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
- android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding"
android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding"
- android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
android:contentDescription="@string/cover_label"
android:scaleType="centerCrop"
tools:src="@drawable/ic_stat_antenna_default"
@@ -24,7 +24,6 @@
android:layout_height="match_parent"
android:layout_marginLeft="@dimen/listitem_iconwithtext_textleftpadding"
android:layout_marginRight="@dimen/listitem_threeline_verticalpadding"
- android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
android:layout_toRightOf="@id/imgvFeedimage"
android:orientation="vertical"
tools:background="@android:color/holo_red_dark">
diff --git a/app/src/main/res/layout/secondary_action.xml b/app/src/main/res/layout/secondary_action.xml
index b2aea03f8..1f4d9e4e6 100644
--- a/app/src/main/res/layout/secondary_action.xml
+++ b/app/src/main/res/layout/secondary_action.xml
@@ -9,5 +9,4 @@
android:focusable="false"
android:focusableInTouchMode="false"
tools:ignore="ContentDescription"
- tools:src="@drawable/ic_play_arrow_grey600_36dp"
- tools:background="@android:color/holo_green_dark" />
+ tools:src="@sample/secondaryaction" />
diff --git a/app/src/main/res/layout/simplechapter_item.xml b/app/src/main/res/layout/simplechapter_item.xml
index 21bbc9545..28cdb08c3 100644
--- a/app/src/main/res/layout/simplechapter_item.xml
+++ b/app/src/main/res/layout/simplechapter_item.xml
@@ -2,7 +2,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
- android:layout_height="@dimen/listitem_threeline_height"
+ android:layout_height="wrap_content"
android:orientation="horizontal"
tools:background="@android:color/darker_gray">
diff --git a/app/src/main/res/layout/splash.xml b/app/src/main/res/layout/splash.xml
new file mode 100644
index 000000000..71b6cd15a
--- /dev/null
+++ b/app/src/main/res/layout/splash.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ProgressBar
+ style="?android:attr/progressBarStyle"
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_alignParentBottom="true"
+ android:layout_centerHorizontal="true"
+ android:layout_margin="36dp"
+ android:id="@+id/progressBar"/>
+</RelativeLayout>
diff --git a/app/src/main/res/layout/subscription_item.xml b/app/src/main/res/layout/subscription_item.xml
index 8f0539dfa..502fa8672 100644
--- a/app/src/main/res/layout/subscription_item.xml
+++ b/app/src/main/res/layout/subscription_item.xml
@@ -11,7 +11,7 @@
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="centerCrop"
- tools:src="@drawable/ic_launcher">
+ tools:src="@mipmap/ic_launcher_round">
</de.danoeh.antennapod.view.SquareImageView>
<com.joanzapata.iconify.widget.IconTextView
diff --git a/app/src/main/res/layout/time_dialog.xml b/app/src/main/res/layout/time_dialog.xml
index 0290ce708..ba4249268 100644
--- a/app/src/main/res/layout/time_dialog.xml
+++ b/app/src/main/res/layout/time_dialog.xml
@@ -8,7 +8,7 @@
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:orientation="horizontal">
+ android:orientation="horizontal" >
<EditText
android:id="@+id/etxtTime"
@@ -18,9 +18,11 @@
android:layout_margin="8dp"
android:ems="2"
android:hint="@string/enter_time_here_label"
-
android:inputType="number"
- android:maxLength="2" />
+ android:maxLength="2" >
+
+ <requestFocus />
+ </EditText>
<Spinner
android:id="@+id/spTimeUnit"
@@ -28,7 +30,6 @@
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp" />
-
</LinearLayout>
<LinearLayout
diff --git a/app/src/main/res/layout/videoplayer_activity.xml b/app/src/main/res/layout/videoplayer_activity.xml
index 4db663e19..10fbf8f49 100644
--- a/app/src/main/res/layout/videoplayer_activity.xml
+++ b/app/src/main/res/layout/videoplayer_activity.xml
@@ -3,7 +3,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:id="@+id/videoframe">
<de.danoeh.antennapod.view.AspectRatioVideoView
android:id="@+id/videoview"
@@ -103,6 +104,7 @@
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/txtvLength"
android:layout_toRightOf="@+id/txtvPosition"
+ android:layout_centerInParent="true"
android:max="500" />
</RelativeLayout>
diff --git a/app/src/main/res/menu/allepisodes_context.xml b/app/src/main/res/menu/allepisodes_context.xml
index 7398b9118..28493c5b6 100644
--- a/app/src/main/res/menu/allepisodes_context.xml
+++ b/app/src/main/res/menu/allepisodes_context.xml
@@ -7,6 +7,12 @@
android:menuCategory="container"
android:title="@string/skip_episode_label" />
+
+ <item
+ android:id="@+id/mark_as_seen_item"
+ android:menuCategory="container"
+ android:title="@string/mark_as_seen_label" />
+
<item
android:id="@+id/mark_read_item"
android:menuCategory="container"
diff --git a/app/src/main/res/menu/downloads_completed.xml b/app/src/main/res/menu/downloads_completed.xml
index dc2996893..a88d93913 100644
--- a/app/src/main/res/menu/downloads_completed.xml
+++ b/app/src/main/res/menu/downloads_completed.xml
@@ -6,7 +6,8 @@
<item
android:id="@+id/episode_actions"
android:menuCategory="container"
- android:title="@string/episode_actions"
+ android:title="@string/batch_edit"
+ android:icon="?attr/checkbox_multiple"
custom:showAsAction="always">
</item>
diff --git a/app/src/main/res/menu/feedlist.xml b/app/src/main/res/menu/feedlist.xml
index 0646dc70f..3882cdff1 100644
--- a/app/src/main/res/menu/feedlist.xml
+++ b/app/src/main/res/menu/feedlist.xml
@@ -12,7 +12,8 @@
<item
android:id="@+id/episode_actions"
android:menuCategory="container"
- android:title="@string/episode_actions"
+ android:icon="?attr/checkbox_multiple"
+ android:title="@string/batch_edit"
custom:showAsAction="always">
</item>
<item
diff --git a/app/src/main/res/menu/mediaplayer.xml b/app/src/main/res/menu/mediaplayer.xml
index 530eb3400..98c7478a6 100644
--- a/app/src/main/res/menu/mediaplayer.xml
+++ b/app/src/main/res/menu/mediaplayer.xml
@@ -41,6 +41,14 @@
android:title="@string/visit_website_label"
android:visible="false">
</item>
+
+ <item
+ android:id="@+id/player_go_to_picture_in_picture"
+ custom:showAsAction="collapseActionView"
+ android:title="@string/player_go_to_picture_in_picture"
+ android:visible="false">
+ </item>
+
<item
android:id="@+id/share_item"
android:icon="?attr/social_share"
diff --git a/app/src/main/res/menu/queue.xml b/app/src/main/res/menu/queue.xml
index a5fe85865..7b82cbef3 100644
--- a/app/src/main/res/menu/queue.xml
+++ b/app/src/main/res/menu/queue.xml
@@ -90,6 +90,25 @@
android:title="@string/descending"/>
</menu>
</item>
+
+ <item
+ android:id="@+id/queue_sort_random"
+ android:title="@string/random">
+ </item>
+
+ <item
+ android:id="@+id/queue_sort_smart_shuffle"
+ android:title="@string/smart_shuffle">
+
+ <menu>
+ <item
+ android:id="@+id/queue_sort_smart_shuffle_asc"
+ android:title="@string/ascending"/>
+ <item
+ android:id="@+id/queue_sort_smart_shuffle_desc"
+ android:title="@string/descending"/>
+ </menu>
+ </item>
</menu>
</item>
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index e81115627..dfc2f4b1a 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -1,347 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
+ xmlns:android="http://schemas.android.com/apk/res/android">
- <PreferenceCategory android:title="@string/user_interface_label">
- <com.afollestad.materialdialogs.prefs.MaterialListPreference
- android:entryValues="@array/theme_values"
- android:entries="@array/theme_options"
- android:title="@string/pref_set_theme_title"
- android:key="prefTheme"
- android:summary="@string/pref_set_theme_sum"
- android:defaultValue="0"
- app:useStockLayout="true"/>
- <PreferenceScreen
- android:key="prefDrawerSettings"
- android:summary="@string/pref_nav_drawer_sum"
- android:title="@string/pref_nav_drawer_title">
- <Preference
- android:key="prefHiddenDrawerItems"
- android:summary="@string/pref_nav_drawer_items_sum"
- android:title="@string/pref_nav_drawer_items_title" />
- <com.afollestad.materialdialogs.prefs.MaterialListPreference
- android:entryValues="@array/nav_drawer_feed_order_values"
- android:entries="@array/nav_drawer_feed_order_options"
- android:title="@string/pref_nav_drawer_feed_order_title"
- android:key="prefDrawerFeedOrder"
- android:summary="@string/pref_nav_drawer_feed_order_sum"
- android:defaultValue="0"
- app:useStockLayout="true"/>
- <com.afollestad.materialdialogs.prefs.MaterialListPreference
- android:entryValues="@array/nav_drawer_feed_counter_values"
- android:entries="@array/nav_drawer_feed_counter_options"
- android:title="@string/pref_nav_drawer_feed_counter_title"
- android:key="prefDrawerFeedIndicator"
- android:summary="@string/pref_nav_drawer_feed_counter_sum"
- android:defaultValue="0"
- app:useStockLayout="true"/>
- </PreferenceScreen>
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="false"
- android:enabled="true"
- android:key="prefExpandNotify"
- android:summary="@string/pref_expandNotify_sum"
- android:title="@string/pref_expandNotify_title"/>
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="true"
- android:enabled="true"
- android:key="prefPersistNotify"
- android:summary="@string/pref_persistNotify_sum"
- android:title="@string/pref_persistNotify_title"/>
- <Preference
- android:key="prefCompactNotificationButtons"
- android:summary="@string/pref_compact_notification_buttons_sum"
- android:title="@string/pref_compact_notification_buttons_title"/>
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="true"
- android:enabled="true"
- android:key="prefLockscreenBackground"
- android:summary="@string/pref_lockscreen_background_sum"
- android:title="@string/pref_lockscreen_background_title"/>
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="true"
- android:enabled="true"
- android:key="prefShowDownloadReport"
- android:summary="@string/pref_showDownloadReport_sum"
- android:title="@string/pref_showDownloadReport_title"/>
- </PreferenceCategory>
+ <com.bytehamster.lib.preferencesearch.SearchPreference
+ android:key="searchPreference" />
- <PreferenceCategory android:title="@string/queue_label">
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="false"
- android:enabled="true"
- android:key="prefQueueAddToFront"
- android:summary="@string/pref_queueAddToFront_sum"
- android:title="@string/pref_queueAddToFront_title"/>
- </PreferenceCategory>
+ <Preference
+ android:key="prefScreenInterface"
+ android:title="@string/user_interface_label"
+ android:icon="?attr/type_video" />
- <PreferenceCategory android:title="@string/playback_pref">
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="true"
- android:enabled="false"
- android:key="prefSonic"
- android:summary="@string/pref_sonic_message"
- android:title="@string/pref_sonic_title"/>
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="true"
- android:enabled="true"
- android:key="prefPauseOnHeadsetDisconnect"
- android:summary="@string/pref_pauseOnDisconnect_sum"
- android:title="@string/pref_pauseOnHeadsetDisconnect_title"/>
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="true"
- android:enabled="true"
- android:dependency="prefPauseOnHeadsetDisconnect"
- android:key="prefUnpauseOnHeadsetReconnect"
- android:summary="@string/pref_unpauseOnHeadsetReconnect_sum"
- android:title="@string/pref_unpauseOnHeadsetReconnect_title"/>
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="false"
- android:enabled="true"
- android:dependency="prefPauseOnHeadsetDisconnect"
- android:key="prefUnpauseOnBluetoothReconnect"
- android:summary="@string/pref_unpauseOnBluetoothReconnect_sum"
- android:title="@string/pref_unpauseOnBluetoothReconnect_title"/>
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="false"
- android:enabled="true"
- android:key="prefHardwareForwardButtonSkips"
- android:summary="@string/pref_hardwareForwardButtonSkips_sum"
- android:title="@string/pref_hardwareForwardButtonSkips_title"/>
- <Preference
- android:key="prefPlaybackFastForwardDeltaLauncher"
- android:summary="@string/pref_fast_forward_sum"
- android:title="@string/pref_fast_forward" />
- <Preference
- android:key="prefPlaybackRewindDeltaLauncher"
- android:summary="@string/pref_rewind_sum"
- android:title="@string/pref_rewind" />
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="false"
- android:enabled="true"
- android:key="prefHardwarePreviousButtonRestarts"
- android:summary="@string/pref_hardwarePreviousButtonRestarts_sum"
- android:title="@string/pref_hardwarePreviousButtonRestarts_title"/>
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="true"
- android:enabled="true"
- android:key="prefFollowQueue"
- android:summary="@string/pref_followQueue_sum"
- android:title="@string/pref_followQueue_title"/>
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="true"
- android:enabled="true"
- android:key="prefSkipKeepsEpisode"
- android:summary="@string/pref_skip_keeps_episodes_sum"
- android:title="@string/pref_skip_keeps_episodes_title"/>
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="true"
- android:enabled="true"
- android:key="prefFavoriteKeepsEpisode"
- android:summary="@string/pref_favorite_keeps_episodes_sum"
- android:title="@string/pref_favorite_keeps_episodes_title"/>
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="false"
- android:enabled="true"
- android:key="prefAutoDelete"
- android:summary="@string/pref_auto_delete_sum"
- android:title="@string/pref_auto_delete_title"/>
- <com.afollestad.materialdialogs.prefs.MaterialListPreference
- android:defaultValue="30"
- android:entries="@array/smart_mark_as_played_values"
- android:entryValues="@array/smart_mark_as_played_values"
- android:key="prefSmartMarkAsPlayedSecs"
- android:summary="@string/pref_smart_mark_as_played_sum"
- android:title="@string/pref_smart_mark_as_played_title"
- app:useStockLayout="true"/>
- <Preference
- android:key="prefPlaybackSpeedLauncher"
- android:summary="@string/pref_playback_speed_sum"
- android:title="@string/pref_playback_speed_title" />
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="false"
- android:enabled="true"
- android:key="prefPauseForFocusLoss"
- android:summary="@string/pref_pausePlaybackForFocusLoss_sum"
- android:title="@string/pref_pausePlaybackForFocusLoss_title" />
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="true"
- android:enabled="true"
- android:key="prefResumeAfterCall"
- android:summary="@string/pref_resumeAfterCall_sum"
- android:title="@string/pref_resumeAfterCall_title"/>
+ <Preference
+ android:key="prefScreenPlayback"
+ android:title="@string/playback_pref"
+ android:icon="?attr/av_play" />
- </PreferenceCategory>
- <PreferenceCategory android:title="@string/network_pref">
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="true"
- android:enabled="true"
- android:key="prefEnqueueDownloaded"
- android:summary="@string/pref_enqueue_downloaded_summary"
- android:title="@string/pref_enqueue_downloaded_title" />
- <Preference
- android:key="prefAutoUpdateIntervall"
- android:summary="@string/pref_autoUpdateIntervallOrTime_sum"
- android:title="@string/pref_autoUpdateIntervallOrTime_title"/>
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="false"
- android:enabled="true"
- android:key="prefMobileUpdate"
- android:summary="@string/pref_mobileUpdate_sum"
- android:title="@string/pref_mobileUpdate_title"/>
- <com.afollestad.materialdialogs.prefs.MaterialListPreference
- android:defaultValue="-1"
- android:entries="@array/episode_cleanup_entries"
- android:key="prefEpisodeCleanup"
- android:title="@string/pref_episode_cleanup_title"
- android:summary="@string/pref_episode_cleanup_summary"
- android:entryValues="@array/episode_cleanup_values"
- app:useStockLayout="true"/>
- <com.afollestad.materialdialogs.prefs.MaterialEditTextPreference
- android:defaultValue="4"
- android:inputType="number"
- android:key="prefParallelDownloads"
- android:title="@string/pref_parallel_downloads_title"
- app:useStockLayout="true"/>
- <PreferenceScreen
- android:summary="@string/pref_automatic_download_sum"
- android:key="prefAutoDownloadSettings"
- android:title="@string/pref_automatic_download_title">
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:key="prefEnableAutoDl"
- android:title="@string/pref_automatic_download_title"
- android:defaultValue="false"/>
- <com.afollestad.materialdialogs.prefs.MaterialListPreference
- android:defaultValue="25"
- android:entries="@array/episode_cache_size_entries"
- android:key="prefEpisodeCacheSize"
- android:title="@string/pref_episode_cache_title"
- android:entryValues="@array/episode_cache_size_values"
- app:useStockLayout="true"/>
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:key="prefEnableAutoDownloadOnBattery"
- android:title="@string/pref_automatic_download_on_battery_title"
- android:summary="@string/pref_automatic_download_on_battery_sum"
- android:defaultValue="true"/>
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:key="prefEnableAutoDownloadOnMobile"
- android:title="@string/pref_autodl_allow_on_mobile_title"
- android:summary="@string/pref_autodl_allow_on_mobile_sum"
- android:defaultValue="false"/>
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:key="prefEnableAutoDownloadWifiFilter"
- android:title="@string/pref_autodl_wifi_filter_title"
- android:summary="@string/pref_autodl_wifi_filter_sum"/>
- </PreferenceScreen>
- <Preference
- android:key="prefProxy"
- android:summary="@string/pref_proxy_sum"
- android:title="@string/pref_proxy_title" />
-
- </PreferenceCategory>
+ <Preference
+ android:key="prefScreenNetwork"
+ android:title="@string/network_pref"
+ android:icon="?attr/ic_swap" />
- <PreferenceCategory android:title="@string/services_label">
- <PreferenceScreen
- android:key="prefFlattrSettings"
- android:title="@string/flattr_label">
- <PreferenceScreen
- android:key="pref_flattr_authenticate"
- android:summary="@string/pref_flattr_auth_sum"
- android:title="@string/pref_flattr_auth_title">
- <intent android:action=".activities.FlattrAuthActivity"/>
- </PreferenceScreen>
+ <Preference
+ android:key="prefScreenIntegrations"
+ android:title="@string/integrations_label"
+ android:icon="?attr/ic_unfav" />
- <Preference
- android:key="prefAutoFlattrPrefs"
- android:summary="@string/pref_auto_flattr_sum"
- android:title="@string/pref_auto_flattr_title" />
- <Preference
- android:key="prefRevokeAccess"
- android:summary="@string/pref_revokeAccess_sum"
- android:title="@string/pref_revokeAccess_title"/>
- </PreferenceScreen>
- <PreferenceScreen
- android:key="prefGpodderSettings"
- android:title="@string/gpodnet_main_label">
+ <Preference
+ android:key="prefScreenStorage"
+ android:title="@string/storage_pref"
+ android:icon="?attr/storage" />
- <PreferenceScreen
- android:key="pref_gpodnet_authenticate"
- android:title="@string/pref_gpodnet_authenticate_title"
- android:summary="@string/pref_gpodnet_authenticate_sum">
- <intent android:action=".activity.gpoddernet.GpodnetAuthenticationActivity"/>
- </PreferenceScreen>
- <Preference
- android:key="pref_gpodnet_setlogin_information"
- android:title="@string/pref_gpodnet_setlogin_information_title"
- android:summary="@string/pref_gpodnet_setlogin_information_sum"/>
- <Preference
- android:key="pref_gpodnet_sync"
- android:title="@string/pref_gpodnet_sync_changes_title"
- android:summary="@string/pref_gpodnet_sync_changes_sum"/>
- <Preference
- android:key="pref_gpodnet_force_full_sync"
- android:title="@string/pref_gpodnet_full_sync_title"
- android:summary="@string/pref_gpodnet_full_sync_sum"/>
- <Preference
- android:key="pref_gpodnet_logout"
- android:title="@string/pref_gpodnet_logout_title"/>
- <Preference
- android:key="pref_gpodnet_hostname"
- android:title="@string/pref_gpodnet_sethostname_title"/>
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:key="pref_gpodnet_notifications"
- android:title="@string/pref_gpodnet_notifications_title"
- android:summary="@string/pref_gpodnet_notifications_sum"
- android:defaultValue="true"/>
- </PreferenceScreen>
- </PreferenceCategory>
- <PreferenceCategory android:title="@string/storage_pref">
- <Preference
- android:title="@string/choose_data_directory"
- android:key="prefChooseDataDir"/>
- <ListPreference
- android:entryValues="@array/image_cache_size_values"
- android:entries="@array/image_cache_size_options"
- android:title="@string/pref_image_cache_size_title"
- android:key="prefImageCacheSize"
- android:summary="@string/pref_image_cache_size_sum"
- android:defaultValue="100"/>
- </PreferenceCategory>
- <PreferenceCategory android:title="@string/other_pref">
- <Preference
- android:key="prefOpmlExport"
- android:title="@string/opml_export_label"/>
- <Preference
- android:key="prefHtmlExport"
- android:title="@string/html_export_label"/>
- <Preference
+ <Preference
android:key="statistics"
- android:title="@string/statistics_label"/>
- </PreferenceCategory>
+ android:title="@string/statistics_label"
+ android:icon="?attr/statistics" />
+
<PreferenceCategory android:title="@string/project_pref">
<Preference
android:key="prefFaq"
- android:title="@string/pref_faq"/>
+ android:title="@string/pref_faq"
+ android:icon="?attr/ic_question_answer" />
+
<Preference
android:key="prefKnownIssues"
- android:title="@string/pref_known_issues"/>
+ android:title="@string/pref_known_issues"
+ android:icon="?attr/ic_known_issues" />
<Preference
android:key="prefSendCrashReport"
android:title="@string/crash_report_title"
- android:summary="@string/crash_report_sum"/>
+ android:summary="@string/crash_report_sum"
+ android:icon="?attr/ic_bug" />
<Preference
android:key="prefAbout"
- android:title="@string/about_pref"/>
- </PreferenceCategory>
-
- <PreferenceCategory android:title="@string/experimental_pref">
- <de.danoeh.antennapod.preferences.SwitchCompatPreference
- android:defaultValue="false"
- android:enabled="true"
- android:key="prefCast"
- android:summary="@string/pref_cast_message"
- android:title="@string/pref_cast_title"/>
+ android:title="@string/about_pref"
+ android:icon="?attr/action_about" />
</PreferenceCategory>
-
</PreferenceScreen>
diff --git a/app/src/main/res/xml/preferences_autodownload.xml b/app/src/main/res/xml/preferences_autodownload.xml
new file mode 100644
index 000000000..b5e3182f0
--- /dev/null
+++ b/app/src/main/res/xml/preferences_autodownload.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:search="http://schemas.android.com/apk/com.bytehamster.lib.preferencesearch">
+
+ <de.danoeh.antennapod.preferences.MasterSwitchPreference
+ android:key="prefEnableAutoDl"
+ android:title="@string/pref_automatic_download_title"
+ search:summary="@string/pref_automatic_download_sum"
+ android:defaultValue="false"/>
+ <ListPreference
+ android:defaultValue="25"
+ android:entries="@array/episode_cache_size_entries"
+ android:key="prefEpisodeCacheSize"
+ android:title="@string/pref_episode_cache_title"
+ android:entryValues="@array/episode_cache_size_values"
+ app:useStockLayout="true"/>
+ <ListPreference
+ android:defaultValue="-1"
+ android:entries="@array/episode_cleanup_entries"
+ android:key="prefEpisodeCleanup"
+ android:title="@string/pref_episode_cleanup_title"
+ android:summary="@string/pref_episode_cleanup_summary"
+ android:entryValues="@array/episode_cleanup_values"
+ app:useStockLayout="true"/>
+ <SwitchPreference
+ android:key="prefEnableAutoDownloadOnBattery"
+ android:title="@string/pref_automatic_download_on_battery_title"
+ android:summary="@string/pref_automatic_download_on_battery_sum"
+ android:defaultValue="true"/>
+ <SwitchPreference
+ android:key="prefEnableAutoDownloadOnMobile"
+ android:title="@string/pref_autodl_allow_on_mobile_title"
+ android:summary="@string/pref_autodl_allow_on_mobile_sum"
+ android:defaultValue="false"/>
+ <SwitchPreference
+ android:key="prefEnableAutoDownloadWifiFilter"
+ android:title="@string/pref_autodl_wifi_filter_title"
+ android:summary="@string/pref_autodl_wifi_filter_sum"/>
+</PreferenceScreen>
diff --git a/app/src/main/res/xml/preferences_flattr.xml b/app/src/main/res/xml/preferences_flattr.xml
new file mode 100644
index 000000000..6b4c38a0b
--- /dev/null
+++ b/app/src/main/res/xml/preferences_flattr.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <PreferenceScreen
+ android:key="pref_flattr_authenticate"
+ android:summary="@string/pref_flattr_auth_sum"
+ android:title="@string/pref_flattr_auth_title">
+ <intent android:action=".activities.FlattrAuthActivity"/>
+ </PreferenceScreen>
+
+ <Preference
+ android:key="prefAutoFlattrPrefs"
+ android:summary="@string/pref_auto_flattr_sum"
+ android:title="@string/pref_auto_flattr_title"/>
+ <Preference
+ android:key="prefRevokeAccess"
+ android:summary="@string/pref_revokeAccess_sum"
+ android:title="@string/pref_revokeAccess_title"/>
+
+</PreferenceScreen>
diff --git a/app/src/main/res/xml/preferences_gpodder.xml b/app/src/main/res/xml/preferences_gpodder.xml
new file mode 100644
index 000000000..5789f5f84
--- /dev/null
+++ b/app/src/main/res/xml/preferences_gpodder.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <PreferenceScreen
+ android:key="pref_gpodnet_authenticate"
+ android:title="@string/pref_gpodnet_authenticate_title"
+ android:summary="@string/pref_gpodnet_authenticate_sum">
+ <intent android:action=".activity.gpoddernet.GpodnetAuthenticationActivity"/>
+ </PreferenceScreen>
+ <Preference
+ android:key="pref_gpodnet_setlogin_information"
+ android:title="@string/pref_gpodnet_setlogin_information_title"
+ android:summary="@string/pref_gpodnet_setlogin_information_sum"/>
+ <Preference
+ android:key="pref_gpodnet_sync"
+ android:title="@string/pref_gpodnet_sync_changes_title"
+ android:summary="@string/pref_gpodnet_sync_changes_sum"/>
+ <Preference
+ android:key="pref_gpodnet_force_full_sync"
+ android:title="@string/pref_gpodnet_full_sync_title"
+ android:summary="@string/pref_gpodnet_full_sync_sum"/>
+ <Preference
+ android:key="pref_gpodnet_logout"
+ android:title="@string/pref_gpodnet_logout_title"/>
+ <Preference
+ android:key="pref_gpodnet_hostname"
+ android:title="@string/pref_gpodnet_sethostname_title"/>
+ <SwitchPreference
+ android:key="pref_gpodnet_notifications"
+ android:title="@string/pref_gpodnet_notifications_title"
+ android:summary="@string/pref_gpodnet_notifications_sum"
+ android:defaultValue="true"/>
+
+</PreferenceScreen>
diff --git a/app/src/main/res/xml/preferences_integrations.xml b/app/src/main/res/xml/preferences_integrations.xml
new file mode 100644
index 000000000..c0fd299ec
--- /dev/null
+++ b/app/src/main/res/xml/preferences_integrations.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <Preference
+ android:key="prefFlattrSettings"
+ android:title="@string/flattr_label"
+ android:summary="@string/flattr_summary" />
+
+ <Preference
+ android:key="prefGpodderSettings"
+ android:title="@string/gpodnet_main_label"
+ android:summary="@string/gpodnet_summary" />
+
+</PreferenceScreen>
diff --git a/app/src/main/res/xml/preferences_network.xml b/app/src/main/res/xml/preferences_network.xml
new file mode 100644
index 000000000..c37a99465
--- /dev/null
+++ b/app/src/main/res/xml/preferences_network.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:numberpicker="http://schemas.android.com/apk/de.danoeh.antennapod"
+ xmlns:search="http://schemas.android.com/apk/com.bytehamster.lib.preferencesearch">
+ <PreferenceCategory android:title="@string/automation">
+ <Preference
+ android:key="prefAutoUpdateIntervall"
+ android:summary="@string/pref_autoUpdateIntervallOrTime_sum"
+ android:title="@string/pref_autoUpdateIntervallOrTime_title"/>
+ <Preference
+ android:summary="@string/pref_automatic_download_sum"
+ android:key="prefAutoDownloadSettings"
+ android:title="@string/pref_automatic_download_title"
+ search:ignore="true" />
+ </PreferenceCategory>
+
+ <PreferenceCategory android:title="@string/download_pref_details">
+ <SwitchPreference
+ android:defaultValue="false"
+ android:enabled="true"
+ android:key="prefMobileUpdate"
+ android:summary="@string/pref_mobileUpdate_sum"
+ android:title="@string/pref_mobileUpdate_title"/>
+ <de.danoeh.antennapod.preferences.NumberPickerPreference
+ android:defaultValue="4"
+ numberpicker:minValue="1"
+ numberpicker:maxValue="50"
+ android:key="prefParallelDownloads"
+ android:title="@string/pref_parallel_downloads_title"/>
+ <SwitchPreference
+ android:defaultValue="true"
+ android:enabled="true"
+ android:key="prefShowDownloadReport"
+ android:summary="@string/pref_showDownloadReport_sum"
+ android:title="@string/pref_showDownloadReport_title"/>
+ <Preference
+ android:key="prefProxy"
+ android:summary="@string/pref_proxy_sum"
+ android:title="@string/pref_proxy_title"/>
+ </PreferenceCategory>
+</PreferenceScreen>
diff --git a/app/src/main/res/xml/preferences_playback.xml b/app/src/main/res/xml/preferences_playback.xml
new file mode 100644
index 000000000..9182df600
--- /dev/null
+++ b/app/src/main/res/xml/preferences_playback.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <PreferenceCategory android:title="@string/interruptions">
+ <SwitchPreference
+ android:defaultValue="true"
+ android:enabled="true"
+ android:key="prefPauseOnHeadsetDisconnect"
+ android:summary="@string/pref_pauseOnDisconnect_sum"
+ android:title="@string/pref_pauseOnHeadsetDisconnect_title"/>
+ <SwitchPreference
+ android:defaultValue="true"
+ android:enabled="true"
+ android:dependency="prefPauseOnHeadsetDisconnect"
+ android:key="prefUnpauseOnHeadsetReconnect"
+ android:summary="@string/pref_unpauseOnHeadsetReconnect_sum"
+ android:title="@string/pref_unpauseOnHeadsetReconnect_title"/>
+ <SwitchPreference
+ android:defaultValue="false"
+ android:enabled="true"
+ android:dependency="prefPauseOnHeadsetDisconnect"
+ android:key="prefUnpauseOnBluetoothReconnect"
+ android:summary="@string/pref_unpauseOnBluetoothReconnect_sum"
+ android:title="@string/pref_unpauseOnBluetoothReconnect_title"/>
+ <SwitchPreference
+ android:defaultValue="false"
+ android:enabled="true"
+ android:key="prefPauseForFocusLoss"
+ android:summary="@string/pref_pausePlaybackForFocusLoss_sum"
+ android:title="@string/pref_pausePlaybackForFocusLoss_title"/>
+ <SwitchPreference
+ android:defaultValue="true"
+ android:enabled="true"
+ android:key="prefResumeAfterCall"
+ android:summary="@string/pref_resumeAfterCall_sum"
+ android:title="@string/pref_resumeAfterCall_title"/>
+ <ListPreference
+ android:defaultValue="stop"
+ android:entries="@array/video_background_behavior_options"
+ android:entryValues="@array/video_background_behavior_values"
+ android:key="prefVideoBehavior"
+ android:summary="@string/pref_videoBehavior_sum"
+ android:title="@string/pref_videoBehavior_title"
+ app:useStockLayout="true"/>
+ </PreferenceCategory>
+
+ <PreferenceCategory android:title="@string/buttons">
+ <SwitchPreference
+ android:defaultValue="false"
+ android:enabled="true"
+ android:key="prefHardwareForwardButtonSkips"
+ android:summary="@string/pref_hardwareForwardButtonSkips_sum"
+ android:title="@string/pref_hardwareForwardButtonSkips_title"/>
+ <SwitchPreference
+ android:defaultValue="false"
+ android:enabled="true"
+ android:key="prefHardwarePreviousButtonRestarts"
+ android:summary="@string/pref_hardwarePreviousButtonRestarts_sum"
+ android:title="@string/pref_hardwarePreviousButtonRestarts_title"/>
+ <Preference
+ android:key="prefPlaybackFastForwardDeltaLauncher"
+ android:summary="@string/pref_fast_forward_sum"
+ android:title="@string/pref_fast_forward"/>
+ <Preference
+ android:key="prefPlaybackRewindDeltaLauncher"
+ android:summary="@string/pref_rewind_sum"
+ android:title="@string/pref_rewind"/>
+ <Preference
+ android:key="prefPlaybackSpeedLauncher"
+ android:summary="@string/pref_playback_speed_sum"
+ android:title="@string/pref_playback_speed_title"/>
+ </PreferenceCategory>
+
+ <PreferenceCategory android:title="@string/queue_label">
+ <SwitchPreference
+ android:defaultValue="true"
+ android:enabled="true"
+ android:key="prefEnqueueDownloaded"
+ android:summary="@string/pref_enqueue_downloaded_summary"
+ android:title="@string/pref_enqueue_downloaded_title" />
+ <SwitchPreference
+ android:defaultValue="false"
+ android:enabled="true"
+ android:key="prefQueueAddToFront"
+ android:summary="@string/pref_queueAddToFront_sum"
+ android:title="@string/pref_queueAddToFront_title"/>
+ <SwitchPreference
+ android:defaultValue="true"
+ android:enabled="true"
+ android:key="prefFollowQueue"
+ android:summary="@string/pref_followQueue_sum"
+ android:title="@string/pref_followQueue_title"/>
+ <ListPreference
+ android:defaultValue="30"
+ android:entries="@array/smart_mark_as_played_values"
+ android:entryValues="@array/smart_mark_as_played_values"
+ android:key="prefSmartMarkAsPlayedSecs"
+ android:summary="@string/pref_smart_mark_as_played_sum"
+ android:title="@string/pref_smart_mark_as_played_title"
+ app:useStockLayout="true"/>
+ <SwitchPreference
+ android:defaultValue="true"
+ android:enabled="true"
+ android:key="prefSkipKeepsEpisode"
+ android:summary="@string/pref_skip_keeps_episodes_sum"
+ android:title="@string/pref_skip_keeps_episodes_title"/>
+ </PreferenceCategory>
+
+ <PreferenceCategory android:title="@string/media_player">
+ <ListPreference
+ android:defaultValue="sonic"
+ android:entries="@array/media_player_options"
+ android:key="prefMediaPlayer"
+ android:title="@string/media_player"
+ android:summary="@string/pref_media_player_message"
+ android:entryValues="@array/media_player_values"
+ app:useStockLayout="true"/>
+ </PreferenceCategory>
+
+ <PreferenceCategory android:title="@string/experimental_pref">
+ <SwitchPreference
+ android:defaultValue="false"
+ android:enabled="true"
+ android:key="prefCast"
+ android:summary="@string/pref_cast_message"
+ android:title="@string/pref_cast_title"/>
+ </PreferenceCategory>
+</PreferenceScreen>
diff --git a/app/src/main/res/xml/preferences_storage.xml b/app/src/main/res/xml/preferences_storage.xml
new file mode 100644
index 000000000..fe48cc99c
--- /dev/null
+++ b/app/src/main/res/xml/preferences_storage.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <Preference
+ android:title="@string/choose_data_directory"
+ android:key="prefChooseDataDir"/>
+ <ListPreference
+ android:entryValues="@array/image_cache_size_values"
+ android:entries="@array/image_cache_size_options"
+ android:title="@string/pref_image_cache_size_title"
+ android:key="prefImageCacheSize"
+ android:summary="@string/pref_image_cache_size_sum"
+ android:defaultValue="100"/>
+ <SwitchPreference
+ android:defaultValue="false"
+ android:enabled="true"
+ android:key="prefAutoDelete"
+ android:summary="@string/pref_auto_delete_sum"
+ android:title="@string/pref_auto_delete_title"/>
+ <SwitchPreference
+ android:defaultValue="true"
+ android:enabled="true"
+ android:key="prefFavoriteKeepsEpisode"
+ android:summary="@string/pref_favorite_keeps_episodes_sum"
+ android:title="@string/pref_favorite_keeps_episodes_title"/>
+
+ <PreferenceCategory android:title="@string/import_export_pref">
+ <Preference
+ android:key="prefOpmlExport"
+ android:title="@string/opml_export_label"/>
+ <Preference
+ android:key="prefOpmlImport"
+ android:title="@string/opml_import_label"/>
+ <Preference
+ android:key="prefHtmlExport"
+ android:title="@string/html_export_label"/>
+ <Preference
+ android:key="importExport"
+ android:title="@string/import_export"/>
+ </PreferenceCategory>
+</PreferenceScreen>
diff --git a/app/src/main/res/xml/preferences_user_interface.xml b/app/src/main/res/xml/preferences_user_interface.xml
new file mode 100644
index 000000000..da694b844
--- /dev/null
+++ b/app/src/main/res/xml/preferences_user_interface.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+
+ <PreferenceCategory android:title="@string/appearance">
+ <ListPreference
+ android:entryValues="@array/theme_values"
+ android:entries="@array/theme_options"
+ android:title="@string/pref_set_theme_title"
+ android:key="prefTheme"
+ android:summary="@string/pref_set_theme_sum"
+ android:defaultValue="0"
+ app:useStockLayout="true"/>
+ <Preference
+ android:key="prefHiddenDrawerItems"
+ android:summary="@string/pref_nav_drawer_items_sum"
+ android:title="@string/pref_nav_drawer_items_title"/>
+ <ListPreference
+ android:entryValues="@array/nav_drawer_feed_order_values"
+ android:entries="@array/nav_drawer_feed_order_options"
+ android:title="@string/pref_nav_drawer_feed_order_title"
+ android:key="prefDrawerFeedOrder"
+ android:summary="@string/pref_nav_drawer_feed_order_sum"
+ android:defaultValue="0"
+ app:useStockLayout="true"/>
+ <ListPreference
+ android:entryValues="@array/nav_drawer_feed_counter_values"
+ android:entries="@array/nav_drawer_feed_counter_options"
+ android:title="@string/pref_nav_drawer_feed_counter_title"
+ android:key="prefDrawerFeedIndicator"
+ android:summary="@string/pref_nav_drawer_feed_counter_sum"
+ android:defaultValue="0"
+ app:useStockLayout="true"/>
+ </PreferenceCategory>
+ <PreferenceCategory android:title="@string/external_elements">
+ <SwitchPreference
+ android:defaultValue="false"
+ android:enabled="true"
+ android:key="prefExpandNotify"
+ android:summary="@string/pref_expandNotify_sum"
+ android:title="@string/pref_expandNotify_title"/>
+ <SwitchPreference
+ android:defaultValue="true"
+ android:enabled="true"
+ android:key="prefPersistNotify"
+ android:summary="@string/pref_persistNotify_sum"
+ android:title="@string/pref_persistNotify_title"/>
+ <Preference
+ android:key="prefCompactNotificationButtons"
+ android:summary="@string/pref_compact_notification_buttons_sum"
+ android:title="@string/pref_compact_notification_buttons_title"/>
+ <SwitchPreference
+ android:defaultValue="true"
+ android:enabled="true"
+ android:key="prefLockscreenBackground"
+ android:summary="@string/pref_lockscreen_background_sum"
+ android:title="@string/pref_lockscreen_background_title"/>
+ </PreferenceCategory>
+</PreferenceScreen>
diff --git a/app/src/main/templates/about.html b/app/src/main/templates/about.html
index 400727c46..cc3a24e62 100644
--- a/app/src/main/templates/about.html
+++ b/app/src/main/templates/about.html
@@ -8,30 +8,52 @@
font-family: 'Roboto-Light';
src: url('file:///android_asset/Roboto-Light.ttf');
}
+
+ html, body {
+ background: @background@;
+ margin: 0;
+ padding: 0;
+ }
* {
- color: %s;
+ color: @fontcolor@;
font-family: roboto-Light;
font-size: 12pt;
}
- header {
+ img#logo {
display: block;
margin-left: auto;
margin-right: auto;
- padding-bottom: 500px;
+ max-height: 200px;
+ max-height: 50vh;
+ max-width: 100%;
+ height: auto;
+ width: auto;
}
-
- versiontag {
- color: gray;
+
+ div#logobackground{
+ width: 100%;
+ background: #42a5f5;
+ }
+
+ .card {
+ background: @card_background@;
+ margin: 10px;
+ padding: 10px;
+ border: 1px solid @card_border@;
+ border-top-width: 0;
+ border-bottom-width: 2px;
}
h1 {
font-size: 15pt;
+ margin-left: 20px;
}
h2 {
font-size: 13pt;
+ margin-top: 0px;
}
a {
@@ -44,67 +66,117 @@
<title>About AntennaPod</title>
</head>
<body>
-<div id="header" align="center">
- <img src="file:///android_asset/logo.png" alt="Logo" width="100px" height="100px"/>
-
- <p>AntennaPod, Version @versionname@</p>
- <p>Commit: @commit@</p>
+<div id="logobackground">
+<img id="logo" src="file:///android_asset/logo.png" alt="Logo"/>
+</div>
- <p>Created by Daniel Oeh</p>
+<h1>AntennaPod</h1>
- <p>Copyright &copy; 2012-@year@ AntennaPod Contributors <a href="CONTRIBUTORS.txt">(View)</a></p>
+<div class="card">
+<table>
+<tr><td>Version:</td><td><b>@versionname@</b></td></tr>
+<tr><td>Commit:</td><td><b>@commit@</b></td></tr>
+</table>
+</div>
- <p>Licensed under the MIT License <a href="LICENSE.txt">(View)</a></p>
+<div class="card">
+Created by Daniel Oeh<br />
+Copyright &copy; 2012-@year@<br />
+AntennaPod Contributors <a href="CONTRIBUTORS.txt">(View)</a><br />
+Licensed under the MIT License <a href="LICENSE.txt">(View)</a>
</div>
+
<h1>Used libraries</h1>
+<div class="card">
<h2>Apache Commons <a href="http://commons.apache.org/">(Link)</a></h2>
by The Apache Software Foundation, licensed under the Apache 2.0 license <a href="LICENSE_APACHE-2.0.txt">(View)</a>
+</div>
+<div class="card">
<h2>EventBus <a href="https://github.com/greenrobot/EventBus">(Link)</a></h2>
by greenrobot, licensed under the Apache 2.0 license <a href="LICENSE_APACHE-2.0.txt">(View)</a>
+</div>
+
+<div class="card">
+<h2>ExoPlayer <a href="https://github.com/google/ExoPlayer">(Link)</a></h2>
+by Google, licensed under the Apache 2.0 license <a href="LICENSE_APACHE-2.0.txt">(View)</a>
+</div>
+<div class="card">
<h2>flattr4j <a href="http://www.shredzone.org/projects/flattr4j/wiki">(Link)</a></h2>
licensed under the Apache 2.0 license <a href="LICENSE_APACHE-2.0.txt">(View)</a>
+</div>
+<div class="card">
<h2>Glide <a href="https://github.com/bumptech/glide/">(Link)</a></h2>
licensed under the Simplified BSD license <a href="LICENSE_GLIDE.txt">(View)</a>
+</div>
+<div class="card">
<h2>Iconify <a href="https://github.com/JoanZapata/android-iconify">(Link)</a></h2>
by Joan Zapata, licensed under the Apache 2.0 license <a href="LICENSE_ANDROID_ICONIFY.txt">(View)</a>
+</div>
+<div class="card">
<h2>jsoup <a href="http://jsoup.org/">(Link)</a></h2>
licensed under the MIT license <a href="LICENSE_JSOUP.txt">(View)</a>
+</div>
+<div class="card">
<h2>Material Design Icons <a href="https://github.com/google/material-design-icons">(Link)</a></h2>
by Google, licensed under an Attribution-ShareAlike 4.0 International license <a href="LICENSE_MATERIAL_DESIGN_ICONS.txt">(View)</a>
+</div>
+
+<div class="card">
+<h2>Material Design Icons <a href="https://github.com/Templarian/MaterialDesign">(Link)</a></h2>
+by Templarian, licensed under the SIL Open Font License, Version 1.1 <a href="LICENSE_SIL.txt">(View)</a>
+</div>
+<div class="card">
<h2>Material Dialogs <a href="https://github.com/afollestad/material-dialogs">(Link)</a></h2>
by Aidan Michael Follestad, licensed under the MIT License <a href="LICENSE_MATERIAL_DIALOGS.txt">(View)</a>
+</div>
+<div class="card">
<h2>OkHttp <a href="https://github.com/square/okhttp">(Link)</a></h2>
by Square, licensed under the Apache 2.0 license <a href="LICENSE_OKHTTP.txt">(View)</a>
+</div>
+<div class="card">
<h2>Okio <a href="https://github.com/square/okio">(Link)</a></h2>
by Square, licensed under the Apache 2.0 license <a href="LICENSE_APACHE-2.0.txt">(View)</a>
+</div>
+<div class="card">
<h2>Presto Client <a href="http://www.aocate.com/presto/">(Link)</a></h2>
licensed under the Apache 2.0 license <a href="LICENSE_PRESTO.txt">(View)</a>
+</div>
+<div class="card">
<h2>RecyclerView-FlexibleDivider <a href="https://github.com/yqritc/RecyclerView-FlexibleDivider">(Link)</a></h2>
licensed under the Apache 2.0 license <a href="LICENSE_APACHE-2.0.txt">(View)</a>
+</div>
+<div class="card">
<h2>RxAndroid <a href="https://github.com/ReactiveX/RxAndroid">(Link)</a></h2>
licensed under the Apache 2.0 license <a href="LICENSE_APACHE-2.0.txt">(View)</a>
+</div>
+<div class="card">
<h2>StackBlur <a href="https://github.com/kikoso/android-stackblur">(Link)</a></h2>
by Enrique L&oacute;pez Ma&ntilde;as, licensed under the Apache 2.0 license <a href="LICENSE_APACHE-2.0.txt">(View)</a>
+</div>
+<div class="card">
<h2>Triangle Label View <a href="https://github.com/shts/TriangleLabelView">(Link)</a></h2>
by Shota Saito, licensed under the Apache 2.0 license <a href="LICENSE_TRIANGLE_LABEL_VIEW.txt">(View)</a>
+</div>
+<div class="card">
<h2>AntennaPod-AudioPlayer <a href="https://github.com/AntennaPod/AntennaPod-AudioPlayer/">(Link)</a></h2>
by the AntennaPod team, licensed under the Apache 2.0 license <a href="LICENSE_APACHE-2.0.txt">(View)</a>
+</div>
</body>
</html>
diff --git a/app/src/play/java/de/danoeh/antennapod/dialog/CustomMRControllerDialog.java b/app/src/play/java/de/danoeh/antennapod/dialog/CustomMRControllerDialog.java
index 7b07d3f84..4cde95d6f 100644
--- a/app/src/play/java/de/danoeh/antennapod/dialog/CustomMRControllerDialog.java
+++ b/app/src/play/java/de/danoeh/antennapod/dialog/CustomMRControllerDialog.java
@@ -20,6 +20,7 @@ import android.support.v4.view.accessibility.AccessibilityEventCompat;
import android.support.v7.app.MediaRouteControllerDialog;
import android.support.v7.graphics.Palette;
import android.support.v7.media.MediaRouter;
+import android.support.v7.widget.AppCompatImageView;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
@@ -68,7 +69,7 @@ public class CustomMRControllerDialog extends MediaRouteControllerDialog {
this(context, 0);
}
- public CustomMRControllerDialog(Context context, int theme) {
+ private CustomMRControllerDialog(Context context, int theme) {
super(context, theme);
mediaRouter = MediaRouter.getInstance(getContext());
token = mediaRouter.getMediaSessionToken();
@@ -203,7 +204,7 @@ public class CustomMRControllerDialog extends MediaRouteControllerDialog {
* http://stackoverflow.com/questions/18077325/scale-image-to-fill-imageview-width-and-keep-aspect-ratio
*/
if (landscape) {
- artView = new ImageView(getContext()) {
+ artView = new AppCompatImageView(getContext()) {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int desiredWidth = widthMeasureSpec;
@@ -234,7 +235,7 @@ public class CustomMRControllerDialog extends MediaRouteControllerDialog {
MarginLayoutParamsCompat.setMarginStart(artParams,
getContext().getResources().getDimensionPixelSize(R.dimen.media_router_controller_playback_control_horizontal_spacing));
} else {
- artView = new ImageView(getContext()) {
+ artView = new AppCompatImageView(getContext()) {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int desiredHeight = heightMeasureSpec;