summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/build.gradle12
-rw-r--r--app/proguard.cfg5
-rw-r--r--app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceMediaPlayerTest.java243
-rw-r--r--app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java1
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBCleanupTests.java1
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBNullCleanupAlgorithmTest.java3
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java1
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java30
-rw-r--r--app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java8
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java10
-rw-r--r--app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java24
-rw-r--r--app/src/main/AndroidManifest.xml33
-rw-r--r--app/src/main/assets/LICENSE_TRIANGLE_LABEL_VIEW.txt13
-rw-r--r--app/src/main/assets/Roboto.ttfbin114976 -> 0 bytes
-rw-r--r--app/src/main/java/de/danoeh/antennapod/PodcastApp.java12
-rw-r--r--app/src/main/java/de/danoeh/antennapod/UpdateManager.java97
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java612
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/CastEnabledActivity.java237
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java83
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java39
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java28
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/FlattrAuthActivity.java36
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java104
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java234
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java620
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java44
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java98
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java19
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java3
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java7
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java107
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java3
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java46
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/gpoddernet/GpodnetAuthenticationActivity.java106
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonCallback.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java74
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java58
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java16
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java5
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java24
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java60
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java63
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java8
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java97
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java141
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java1
-rw-r--r--app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java10
-rw-r--r--app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java5
-rw-r--r--app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java11
-rw-r--r--app/src/main/java/de/danoeh/antennapod/config/DBTasksCallbacksImpl.java1
-rw-r--r--app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/AuthenticationDialog.java29
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/AutoFlattrPreferenceDialog.java36
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java12
-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.java320
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java28
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java19
-rw-r--r--app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java36
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java78
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java20
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java10
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java31
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java17
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java164
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java54
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java23
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java42
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java29
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java238
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java16
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SuggestionListFragment.java8
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/TagListFragment.java12
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java25
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java1
-rw-r--r--app/src/main/java/de/danoeh/antennapod/menuhandler/NavDrawerActivity.java2
-rw-r--r--app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java178
-rw-r--r--app/src/main/java/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/receiver/PlayerWidget.java6
-rw-r--r--app/src/main/java/de/danoeh/antennapod/receiver/PowerConnectionReceiver.java4
-rw-r--r--app/src/main/java/de/danoeh/antennapod/receiver/SPAReceiver.java47
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/OnSwipeGesture.java9
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/SquareImageView.java32
-rw-r--r--app/src/main/java/de/danoeh/antennapod/view/SwipeGestureDetector.java44
-rw-r--r--app/src/main/res/layout/downloadlog_item.xml3
-rw-r--r--app/src/main/res/layout/external_player_fragment.xml24
-rw-r--r--app/src/main/res/layout/feeditem_fragment.xml21
-rw-r--r--app/src/main/res/layout/fragment_subscriptions.xml16
-rw-r--r--app/src/main/res/layout/mediaplayerinfo_activity.xml (renamed from app/src/main/res/layout/audioplayer_activity.xml)15
-rw-r--r--app/src/main/res/layout/new_episodes_listitem.xml1
-rw-r--r--app/src/main/res/layout/proxy_settings.xml90
-rw-r--r--app/src/main/res/layout/statistics_activity.xml41
-rw-r--r--app/src/main/res/layout/statistics_listitem.xml57
-rw-r--r--app/src/main/res/layout/subscription_item.xml40
-rw-r--r--app/src/main/res/layout/videoplayer_activity.xml4
-rw-r--r--app/src/main/res/menu/cast_enabled.xml10
-rw-r--r--app/src/main/res/menu/feeditem_options.xml8
-rw-r--r--app/src/main/res/menu/opml_selection_options.xml19
-rw-r--r--app/src/main/res/xml/preferences.xml43
-rw-r--r--app/src/main/templates/about.html3
113 files changed, 3796 insertions, 1717 deletions
diff --git a/app/build.gradle b/app/build.gradle
index 240fd6f9f..cd3fb7aa1 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -9,6 +9,7 @@ repositories {
}
dependencies {
+ compile project(":core")
compile "com.android.support:support-v4:$supportVersion"
compile "com.android.support:appcompat-v7:$supportVersion"
compile "com.android.support:design:$supportVersion"
@@ -19,7 +20,6 @@ dependencies {
compile("org.shredzone.flattr4j:flattr4j-core:$flattr4jVersion") {
exclude group: "org.json", module: "json"
}
-
compile "commons-io:commons-io:$commonsioVersion"
compile "org.jsoup:jsoup:$jsoupVersion"
compile "com.github.bumptech.glide:glide:$glideVersion"
@@ -41,22 +41,22 @@ dependencies {
exclude module: "support-v4"
}
- compile "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion"
+ compile "com.github.shts:TriangleLabelView:$triangleLabelViewVersion"
- compile project(":core")
+ compile "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion"
}
def getMyVersionName() {
def parsedManifestXml = (new XmlSlurper())
.parse("${projectDir}/src/main/AndroidManifest.xml")
- .declareNamespace(android:"http://schemas.android.com/apk/res/android")
+ .declareNamespace(android: "http://schemas.android.com/apk/res/android")
return parsedManifestXml."@android:versionName"
}
def getMyVersionCode() {
def parsedManifestXml = (new XmlSlurper())
.parse("${projectDir}/src/main/AndroidManifest.xml")
- .declareNamespace(android:"http://schemas.android.com/apk/res/android")
+ .declareNamespace(android: "http://schemas.android.com/apk/res/android")
return parsedManifestXml."@android:versionCode".toInteger()
}
@@ -150,7 +150,7 @@ task filterAbout {
from "src/main/templates/about.html"
into "src/main/assets"
filter(ReplaceTokens, tokens: [versionname: android.defaultConfig.versionName,
- commit: "git rev-parse --short HEAD".execute().text])
+ commit : "git rev-parse --short HEAD".execute().text])
}
}
diff --git a/app/proguard.cfg b/app/proguard.cfg
index 19ae36f36..a25664490 100644
--- a/app/proguard.cfg
+++ b/app/proguard.cfg
@@ -64,7 +64,7 @@
-keep class android.support.v4.** { *; }
-keep interface android.support.v4.** { *; }
--keep class android.support.v7.** { *; }
+-keep class !android.support.v7.internal.view.menu.**,android.support.v7.** {*;}
-keep interface android.support.v7.** { *; }
-dontwarn android.support.v4.**
-dontwarn android.support.v7.**
@@ -105,3 +105,6 @@
# for ViewPageIndicator problems (https://github.com/JakeWharton/ViewPagerIndicator/issues/366):
-dontwarn com.viewpagerindicator.LinePageIndicator
+
+# for some reason ProGuard removes this file. Why? Unsure.
+-keep class de.danoeh.antennapod.core.cast.SwitchableMediaRouteActionProvider { *; } \ No newline at end of file
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 7862e986d..6f8dbcb1a 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
@@ -21,13 +21,14 @@ 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.service.playback.PlaybackServiceMediaPlayer;
+import de.danoeh.antennapod.core.service.playback.LocalPSMP;
import de.danoeh.antennapod.core.service.playback.PlayerStatus;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.test.antennapod.util.service.download.HTTPBin;
/**
- * Test class for PlaybackServiceMediaPlayer
+ * Test class for LocalPSMP
*/
public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
private static final String TAG = "PlaybackServiceMediaPlayerTest";
@@ -53,7 +54,10 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
super.setUp();
assertionError = null;
+ final Context context = getInstrumentation().getTargetContext();
+
// create new database
+ PodDBAdapter.init(context);
PodDBAdapter.deleteDatabase();
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
@@ -62,7 +66,6 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
httpServer = new HTTPBin();
httpServer.start();
- final Context context = getInstrumentation().getTargetContext();
File cacheDir = context.getExternalFilesDir("testFiles");
if (cacheDir == null)
cacheDir = context.getExternalFilesDir("testFiles");
@@ -83,7 +86,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
assertEquals(0, httpServer.serveFile(dest));
}
- private void checkPSMPInfo(PlaybackServiceMediaPlayer.PSMPInfo info) {
+ private void checkPSMPInfo(LocalPSMP.PSMPInfo info) {
try {
switch (info.playerStatus) {
case PLAYING:
@@ -109,7 +112,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
public void testInit() {
final Context c = getInstrumentation().getTargetContext();
- PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, defaultCallback);
+ PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, defaultCallback);
psmp.shutdown();
}
@@ -137,7 +140,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
final CountDownLatch countDownLatch = new CountDownLatch(2);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
@Override
- public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
try {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR)
@@ -168,12 +171,22 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
+ public void setSpeedAbilityChanged() {
+
+ }
+
+ @Override
+ public void onMediaChanged(boolean reloadUI) {
+
+ }
+
+ @Override
public void onBufferingUpdate(int percent) {
}
@Override
- public boolean onMediaPlayerInfo(int code) {
+ public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@@ -183,12 +196,12 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
- public boolean endPlayback(boolean playNextEpisode, boolean wasSkipped) {
+ public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
- PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
psmp.playMediaObject(p, true, false, false);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
@@ -206,7 +219,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
final CountDownLatch countDownLatch = new CountDownLatch(2);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
@Override
- public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
try {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR)
@@ -237,12 +250,22 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
+ public void setSpeedAbilityChanged() {
+
+ }
+
+ @Override
+ public void onMediaChanged(boolean reloadUI) {
+
+ }
+
+ @Override
public void onBufferingUpdate(int percent) {
}
@Override
- public boolean onMediaPlayerInfo(int code) {
+ public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@@ -252,11 +275,11 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
- public boolean endPlayback(boolean playNextEpisode, boolean wasSkipped) {
+ public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
- PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
psmp.playMediaObject(p, true, true, false);
@@ -275,7 +298,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
final CountDownLatch countDownLatch = new CountDownLatch(4);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
@Override
- public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
try {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR)
@@ -309,12 +332,22 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
+ public void setSpeedAbilityChanged() {
+
+ }
+
+ @Override
+ public void onMediaChanged(boolean reloadUI) {
+
+ }
+
+ @Override
public void onBufferingUpdate(int percent) {
}
@Override
- public boolean onMediaPlayerInfo(int code) {
+ public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@@ -324,11 +357,11 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
- public boolean endPlayback(boolean playNextEpisode, boolean wasSkipped) {
+ public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
- PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
psmp.playMediaObject(p, true, false, true);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
@@ -345,7 +378,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
final CountDownLatch countDownLatch = new CountDownLatch(5);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
@Override
- public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
try {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR)
@@ -382,12 +415,22 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
+ public void setSpeedAbilityChanged() {
+
+ }
+
+ @Override
+ public void onMediaChanged(boolean reloadUI) {
+
+ }
+
+ @Override
public void onBufferingUpdate(int percent) {
}
@Override
- public boolean onMediaPlayerInfo(int code) {
+ public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@@ -397,12 +440,12 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
- public boolean endPlayback(boolean playNextEpisode, boolean wasSkipped) {
+ public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
- PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, null);
psmp.playMediaObject(p, true, true, true);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
@@ -418,7 +461,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
final CountDownLatch countDownLatch = new CountDownLatch(2);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
@Override
- public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
try {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR)
@@ -449,12 +492,22 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
+ public void setSpeedAbilityChanged() {
+
+ }
+
+ @Override
+ public void onMediaChanged(boolean reloadUI) {
+
+ }
+
+ @Override
public void onBufferingUpdate(int percent) {
}
@Override
- public boolean onMediaPlayerInfo(int code) {
+ public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@@ -464,12 +517,12 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
- public boolean endPlayback(boolean playNextEpisode, boolean wasSkipped) {
+ public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
- PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
psmp.playMediaObject(p, false, false, false);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
@@ -486,7 +539,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
final CountDownLatch countDownLatch = new CountDownLatch(2);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
@Override
- public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
try {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR)
@@ -517,12 +570,22 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
+ public void setSpeedAbilityChanged() {
+
+ }
+
+ @Override
+ public void onMediaChanged(boolean reloadUI) {
+
+ }
+
+ @Override
public void onBufferingUpdate(int percent) {
}
@Override
- public boolean onMediaPlayerInfo(int code) {
+ public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@@ -532,11 +595,11 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
- public boolean endPlayback(boolean playNextEpisode, boolean wasSkipped) {
+ public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
- PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
psmp.playMediaObject(p, false, true, false);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
@@ -553,7 +616,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
final CountDownLatch countDownLatch = new CountDownLatch(4);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
@Override
- public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
try {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR)
@@ -587,12 +650,22 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
+ public void setSpeedAbilityChanged() {
+
+ }
+
+ @Override
+ public void onMediaChanged(boolean reloadUI) {
+
+ }
+
+ @Override
public void onBufferingUpdate(int percent) {
}
@Override
- public boolean onMediaPlayerInfo(int code) {
+ public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@@ -602,11 +675,11 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
- public boolean endPlayback(boolean playNextEpisode, boolean wasSkipped) {
+ public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
- PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
psmp.playMediaObject(p, false, false, true);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
@@ -622,7 +695,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
final CountDownLatch countDownLatch = new CountDownLatch(5);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
@Override
- public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
try {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR)
@@ -660,12 +733,22 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
+ public void setSpeedAbilityChanged() {
+
+ }
+
+ @Override
+ public void onMediaChanged(boolean reloadUI) {
+
+ }
+
+ @Override
public void onBufferingUpdate(int percent) {
}
@Override
- public boolean onMediaPlayerInfo(int code) {
+ public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@@ -675,11 +758,11 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
- public boolean endPlayback(boolean playNextEpisode, boolean wasSkipped) {
+ public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
- PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
psmp.playMediaObject(p, false, true, true);
boolean res = countDownLatch.await(LATCH_TIMEOUT_SECONDS, TimeUnit.SECONDS);
@@ -693,7 +776,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
private final PlaybackServiceMediaPlayer.PSMPCallback defaultCallback = new PlaybackServiceMediaPlayer.PSMPCallback() {
@Override
- public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
checkPSMPInfo(newInfo);
}
@@ -708,12 +791,22 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
+ public void setSpeedAbilityChanged() {
+
+ }
+
+ @Override
+ public void onMediaChanged(boolean reloadUI) {
+
+ }
+
+ @Override
public void onBufferingUpdate(int percent) {
}
@Override
- public boolean onMediaPlayerInfo(int code) { return false; }
+ public boolean onMediaPlayerInfo(int code, int resourceId) { return false; }
@Override
public boolean onMediaPlayerError(Object inObj, int what, int extra) {
@@ -721,7 +814,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
- public boolean endPlayback(boolean playNextEpisode, boolean wasSkipped) {
+ public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
@@ -733,7 +826,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
@Override
- public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR) {
if (assertionError == null)
@@ -776,12 +869,22 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
+ public void setSpeedAbilityChanged() {
+
+ }
+
+ @Override
+ public void onMediaChanged(boolean reloadUI) {
+
+ }
+
+ @Override
public void onBufferingUpdate(int percent) {
}
@Override
- public boolean onMediaPlayerInfo(int code) {
+ public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@@ -793,11 +896,11 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
- public boolean endPlayback(boolean playNextEpisode, boolean wasSkipped) {
+ public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
- PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
if (initialState == PlayerStatus.PLAYING) {
psmp.playMediaObject(p, stream, true, true);
@@ -854,7 +957,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
@Override
- public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR) {
if (assertionError == null)
@@ -881,12 +984,22 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
+ public void setSpeedAbilityChanged() {
+
+ }
+
+ @Override
+ public void onMediaChanged(boolean reloadUI) {
+
+ }
+
+ @Override
public void onBufferingUpdate(int percent) {
}
@Override
- public boolean onMediaPlayerInfo(int code) {
+ public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@@ -899,11 +1012,11 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
- public boolean endPlayback(boolean playNextEpisode, boolean wasSkipped) {
+ public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
- PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
if (initialState == PlayerStatus.PREPARED || initialState == PlayerStatus.PLAYING || initialState == PlayerStatus.PAUSED) {
boolean startWhenPrepared = (initialState != PlayerStatus.PREPARED);
psmp.playMediaObject(writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL), false, startWhenPrepared, true);
@@ -937,7 +1050,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
final CountDownLatch countDownLatch = new CountDownLatch(latchCount);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
@Override
- public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR) {
if (assertionError == null)
@@ -963,12 +1076,22 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
+ public void setSpeedAbilityChanged() {
+
+ }
+
+ @Override
+ public void onMediaChanged(boolean reloadUI) {
+
+ }
+
+ @Override
public void onBufferingUpdate(int percent) {
}
@Override
- public boolean onMediaPlayerInfo(int code) {
+ public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@@ -980,11 +1103,11 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
- public boolean endPlayback(boolean playNextEpisode, boolean wasSkipped) {
+ public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
- PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
if (initialState == PlayerStatus.INITIALIZED
|| initialState == PlayerStatus.PLAYING
@@ -1032,7 +1155,7 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
final CountDownLatch countDownLatch = new CountDownLatch(latchCount);
PlaybackServiceMediaPlayer.PSMPCallback callback = new PlaybackServiceMediaPlayer.PSMPCallback() {
@Override
- public void statusChanged(PlaybackServiceMediaPlayer.PSMPInfo newInfo) {
+ public void statusChanged(LocalPSMP.PSMPInfo newInfo) {
checkPSMPInfo(newInfo);
if (newInfo.playerStatus == PlayerStatus.ERROR) {
if (assertionError == null)
@@ -1057,12 +1180,22 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
+ public void setSpeedAbilityChanged() {
+
+ }
+
+ @Override
+ public void onMediaChanged(boolean reloadUI) {
+
+ }
+
+ @Override
public void onBufferingUpdate(int percent) {
}
@Override
- public boolean onMediaPlayerInfo(int code) {
+ public boolean onMediaPlayerInfo(int code, int resourceId) {
return false;
}
@@ -1074,11 +1207,11 @@ public class PlaybackServiceMediaPlayerTest extends InstrumentationTestCase {
}
@Override
- public boolean endPlayback(boolean playNextEpisode, boolean wasSkipped) {
+ public boolean endPlayback(Playable p, boolean playNextEpisode, boolean wasSkipped, boolean switchingPlayers) {
return false;
}
};
- PlaybackServiceMediaPlayer psmp = new PlaybackServiceMediaPlayer(c, callback);
+ PlaybackServiceMediaPlayer psmp = new LocalPSMP(c, callback);
Playable p = writeTestPlayable(PLAYABLE_FILE_URL, PLAYABLE_LOCAL_URL);
boolean prepareImmediately = initialState != PlayerStatus.INITIALIZED;
boolean startImmediately = initialState != PlayerStatus.PREPARED;
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 5c3d32960..6ab6e5c61 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
@@ -34,6 +34,7 @@ public class PlaybackServiceTaskManagerTest extends InstrumentationTestCase {
super.setUp();
// create new database
+ PodDBAdapter.init(getInstrumentation().getTargetContext());
PodDBAdapter.deleteDatabase();
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
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 7300df395..5e5eb1e8b 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBCleanupTests.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBCleanupTests.java
@@ -70,6 +70,7 @@ public class DBCleanupTests extends InstrumentationTestCase {
assertTrue(destFolder.canWrite());
// create new database
+ PodDBAdapter.init(context);
PodDBAdapter.deleteDatabase();
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBNullCleanupAlgorithmTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBNullCleanupAlgorithmTest.java
index 7205b42c4..7925941ec 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBNullCleanupAlgorithmTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBNullCleanupAlgorithmTest.java
@@ -19,8 +19,6 @@ import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.PodDBAdapter;
-import static de.test.antennapod.storage.DBTestUtils.saveFeedlist;
-
/**
* Tests that the APNullCleanupAlgorithm is working correctly.
*/
@@ -60,6 +58,7 @@ public class DBNullCleanupAlgorithmTest extends InstrumentationTestCase {
assertTrue(destFolder.canWrite());
// create new database
+ PodDBAdapter.init(context);
PodDBAdapter.deleteDatabase();
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
diff --git a/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java b/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java
index 0fc3b1892..9386e3bd6 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBReaderTest.java
@@ -34,6 +34,7 @@ public class DBReaderTest extends InstrumentationTestCase {
super.setUp();
// create new database
+ PodDBAdapter.init(getInstrumentation().getTargetContext());
PodDBAdapter.deleteDatabase();
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
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 5b2393d45..785d32e93 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBTasksTest.java
@@ -5,12 +5,14 @@ import android.test.FlakyTest;
import android.test.InstrumentationTestCase;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
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.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
@@ -28,7 +30,6 @@ public class DBTasksTest extends InstrumentationTestCase {
@Override
protected void tearDown() throws Exception {
super.tearDown();
-
assertTrue(PodDBAdapter.deleteDatabase());
}
@@ -38,6 +39,7 @@ public class DBTasksTest extends InstrumentationTestCase {
context = getInstrumentation().getTargetContext();
// create new database
+ PodDBAdapter.init(context);
PodDBAdapter.deleteDatabase();
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
@@ -120,6 +122,32 @@ public class DBTasksTest extends InstrumentationTestCase {
updatedFeedTest(feedFromDB, feedID, itemIDs, NUM_ITEMS_OLD, NUM_ITEMS_NEW);
}
+ 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));
+
+ PodDBAdapter adapter = PodDBAdapter.getInstance();
+ adapter.open();
+ adapter.setCompleteFeed(feed);
+ adapter.close();
+
+ // ensure that objects have been saved in db, then reset
+ assertTrue(feed.getId() != 0);
+ assertTrue(item.getId() != 0);
+
+ FeedMedia media = new FeedMedia(item, "url", 1024, "mime/type");
+ item.setMedia(media);
+ feed.setItems(Arrays.asList(item));
+
+ final Feed newFeed = DBTasks.updateFeed(context, feed)[0];
+ assertTrue(feed != newFeed);
+
+ final Feed feedFromDB = DBReader.getFeed(newFeed.getId());
+ final FeedItem feedItemFromDB = feedFromDB.getItems().get(0);
+ assertTrue("state: " + feedItemFromDB.getState(), feedItemFromDB.isNew());
+ }
+
private void updatedFeedTest(final Feed newFeed, long feedID, List<Long> itemIDs, final int NUM_ITEMS_OLD, final int NUM_ITEMS_NEW) {
assertTrue(newFeed.getId() == feedID);
assertTrue(newFeed.getItems().size() == NUM_ITEMS_NEW + NUM_ITEMS_OLD);
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 0e1d19f7b..40083e507 100644
--- a/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/storage/DBWriterTest.java
@@ -53,6 +53,7 @@ public class DBWriterTest extends InstrumentationTestCase {
super.setUp();
// create new database
+ PodDBAdapter.init(getInstrumentation().getTargetContext());
PodDBAdapter.deleteDatabase();
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
@@ -194,6 +195,7 @@ public class DBWriterTest extends InstrumentationTestCase {
assertEquals(0, c.getCount());
c.close();
}
+ adapter.close();
}
public void testDeleteFeedNoImage() throws ExecutionException, InterruptedException, IOException, TimeoutException {
@@ -250,6 +252,7 @@ public class DBWriterTest extends InstrumentationTestCase {
assertTrue(c.getCount() == 0);
c.close();
}
+ adapter.close();
}
public void testDeleteFeedNoItems() throws IOException, ExecutionException, InterruptedException, TimeoutException {
@@ -287,6 +290,7 @@ public class DBWriterTest extends InstrumentationTestCase {
c = adapter.getImageCursor(String.valueOf(image.getId()));
assertTrue(c.getCount() == 0);
c.close();
+ adapter.close();
}
public void testDeleteFeedNoFeedMedia() throws IOException, ExecutionException, InterruptedException, TimeoutException {
@@ -339,6 +343,7 @@ public class DBWriterTest extends InstrumentationTestCase {
assertTrue(c.getCount() == 0);
c.close();
}
+ adapter.close();
}
public void testDeleteFeedWithItemImages() throws InterruptedException, ExecutionException, TimeoutException, IOException {
@@ -397,6 +402,7 @@ public class DBWriterTest extends InstrumentationTestCase {
assertEquals(0, c.getCount());
c.close();
}
+ adapter.close();
}
public void testDeleteFeedWithQueueItems() throws ExecutionException, InterruptedException, TimeoutException {
@@ -527,6 +533,7 @@ public class DBWriterTest extends InstrumentationTestCase {
assertTrue(c.getCount() == 0);
c.close();
}
+ adapter.close();
}
private FeedMedia playbackHistorySetup(Date playbackCompletionDate) {
@@ -730,7 +737,6 @@ public class DBWriterTest extends InstrumentationTestCase {
}
assertTrue(idFound);
}
-
queue.close();
adapter.close();
}
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 4e214cf81..9a0e11816 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java
@@ -41,10 +41,12 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv
@Override
protected void setUp() throws Exception {
super.setUp();
- uiTestUtils = new UITestUtils(getInstrumentation().getTargetContext());
+ Context context = getInstrumentation().getTargetContext();
+ uiTestUtils = new UITestUtils(context);
uiTestUtils.setup();
// create new database
+ PodDBAdapter.init(context);
PodDBAdapter.deleteDatabase();
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
@@ -108,6 +110,12 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv
solo.waitForView(android.R.id.list);
assertEquals(solo.getString(R.string.episodes_label), getActionbarTitle());
+ // Subscriptions
+ openNavDrawer();
+ solo.clickOnText(solo.getString(R.string.subscriptions_label));
+ solo.waitForView(R.id.subscriptions_grid);
+ assertEquals(solo.getString(R.string.subscriptions_label), getActionbarTitle());
+
// downloads
openNavDrawer();
solo.clickOnText(solo.getString(R.string.downloads_label));
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 54741502c..040f4150b 100644
--- a/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java
+++ b/app/src/androidTest/java/de/test/antennapod/ui/PreferencesTest.java
@@ -90,6 +90,30 @@ public class PreferencesTest extends ActivityInstrumentationTestCase2<Preference
assertTrue(solo.waitForCondition(() -> persistNotify == UserPreferences.isPersistNotify(), Timeout.getLargeTimeout()));
}
+ public void testSetLockscreenButtons() {
+ 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]);
+ }
+ }
+ // Now try to check all checkboxes
+ solo.clickOnText(buttons[0]);
+ solo.clickOnText(buttons[1]);
+ solo.clickOnText(buttons[2]);
+ // Make sure that the third checkbox is unchecked
+ 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.showSkipOnCompactNotification(), Timeout.getLargeTimeout()));
+ }
+
public void testEnqueueAtFront() {
final boolean enqueueAtFront = UserPreferences.enqueueAtFront();
solo.clickOnText(solo.getString(R.string.pref_queueAddToFront_title));
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index af23c287c..c1b72602a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="de.danoeh.antennapod"
- android:versionCode="1050200"
- android:versionName="1.5.2.0">
+ android:versionCode="1060007"
+ android:versionName="1.6.0.7">
<!--
Version code schema:
"1.2.3-SNAPSHOT" -> 1020300
@@ -41,6 +41,10 @@
android:name="com.google.android.backup.api_key"
android:value="AEdPqrEAAAAI3a05VToCTlqBymJrbFGaKQMvF-bBAuLsOdavBA"/>
+ <meta-data
+ android:name="com.google.android.gms.version"
+ android:value="@integer/google_play_services_version" />
+
<activity
android:name=".activity.MainActivity"
android:configChanges="keyboardHidden|orientation"
@@ -67,6 +71,13 @@
<data android:mimeType="audio/*"/>
</intent-filter>
</activity>
+ <activity
+ android:name=".activity.CastplayerActivity"
+ android:launchMode="singleTop">
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value="de.danoeh.antennapod.activity.MainActivity"/>
+ </activity>
<activity
android:name=".activity.DownloadAuthenticationActivity"
@@ -145,6 +156,13 @@
android:value="de.danoeh.antennapod.activity.PreferenceActivity"/>
</activity>
<activity
+ android:name=".activity.StatisticsActivity"
+ android:label="@string/statistics_label">
+ <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"
android:label="@string/opml_import_label">
@@ -179,7 +197,7 @@
<activity
android:name=".activity.VideoplayerActivity"
android:configChanges="keyboardHidden|orientation"
- android:screenOrientation="landscape">
+ android:screenOrientation="sensorLandscape">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="de.danoeh.antennapod.activity.MainActivity"/>
@@ -201,10 +219,6 @@
android:value="de.danoeh.antennapod.activity.PreferenceActivity"/>
</activity>
- <meta-data
- android:name="android.support.PARENT_ACTIVITY"
- android:value="de.danoeh.antennapod.activity.PreferenceActivity"/>
-
<activity
android:name=".activity.OnlineFeedViewActivity"
android:configChanges="orientation"
@@ -328,11 +342,6 @@
android:scheme="package"/>
</intent-filter>
</receiver>
- <receiver android:name="de.danoeh.antennapod.core.service.playback.MediaButtonIntentReceiver">
- <intent-filter>
- <action android:name="android.intent.action.MEDIA_BUTTON" />
- </intent-filter>
- </receiver>
<meta-data
android:name="de.danoeh.antennapod.core.glide.ApGlideModule"
diff --git a/app/src/main/assets/LICENSE_TRIANGLE_LABEL_VIEW.txt b/app/src/main/assets/LICENSE_TRIANGLE_LABEL_VIEW.txt
new file mode 100644
index 000000000..de9a1f228
--- /dev/null
+++ b/app/src/main/assets/LICENSE_TRIANGLE_LABEL_VIEW.txt
@@ -0,0 +1,13 @@
+Copyright (C) 2016 Shota Saito
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License. \ No newline at end of file
diff --git a/app/src/main/assets/Roboto.ttf b/app/src/main/assets/Roboto.ttf
deleted file mode 100644
index 0ba95c98c..000000000
--- a/app/src/main/assets/Roboto.ttf
+++ /dev/null
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 829a49a15..f6a8db5fb 100644
--- a/app/src/main/java/de/danoeh/antennapod/PodcastApp.java
+++ b/app/src/main/java/de/danoeh/antennapod/PodcastApp.java
@@ -8,11 +8,8 @@ import com.joanzapata.iconify.Iconify;
import com.joanzapata.iconify.fonts.FontAwesomeModule;
import com.joanzapata.iconify.fonts.MaterialModule;
+import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.feed.EventDistributor;
-import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.storage.PodDBAdapter;
-import de.danoeh.antennapod.core.util.NetworkUtils;
import de.danoeh.antennapod.spa.SPAUtil;
/** Main application class. */
@@ -56,11 +53,8 @@ public class PodcastApp extends Application {
singleton = this;
- PodDBAdapter.init(this);
- UserPreferences.init(this);
- UpdateManager.init(this);
- PlaybackPreferences.init(this);
- NetworkUtils.init(this);
+ ClientConfig.initialize(this);
+
EventDistributor.getInstance();
Iconify.with(new FontAwesomeModule());
Iconify.with(new MaterialModule());
diff --git a/app/src/main/java/de/danoeh/antennapod/UpdateManager.java b/app/src/main/java/de/danoeh/antennapod/UpdateManager.java
deleted file mode 100644
index 0b3c43381..000000000
--- a/app/src/main/java/de/danoeh/antennapod/UpdateManager.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package de.danoeh.antennapod;
-
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.util.Log;
-
-import org.antennapod.audio.MediaPlayer;
-
-import java.io.File;
-import java.util.List;
-
-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.preferences.UserPreferences;
-import de.danoeh.antennapod.core.storage.DBReader;
-import de.danoeh.antennapod.core.storage.DBWriter;
-
-/*
- * This class's job is do perform maintenance tasks whenever the app has been updated
- */
-public class UpdateManager {
-
- public static final String TAG = UpdateManager.class.getSimpleName();
-
- private static final String PREF_NAME = "app_version";
- private static final String KEY_VERSION_CODE = "version_code";
-
- private static int currentVersionCode;
-
- private static Context context;
- private static SharedPreferences prefs;
-
- public static void init(Context context) {
- UpdateManager.context = context;
- prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
- PackageManager pm = context.getPackageManager();
- try {
- PackageInfo info = pm.getPackageInfo(context.getPackageName(), 0);
- currentVersionCode = info.versionCode;
- } catch (PackageManager.NameNotFoundException e) {
- Log.e(TAG, "Failed to obtain package info for package name: " + context.getPackageName(), e);
- currentVersionCode = 0;
- return;
- }
- final int oldVersionCode = getStoredVersionCode();
- Log.d(TAG, "old: " + oldVersionCode + ", current: " + currentVersionCode);
- if(oldVersionCode < currentVersionCode) {
- onUpgrade(oldVersionCode, currentVersionCode);
- setCurrentVersionCode();
- }
- }
-
- public static int getStoredVersionCode() {
- return prefs.getInt(KEY_VERSION_CODE, -1);
- }
-
- public static void setCurrentVersionCode() {
- prefs.edit().putInt(KEY_VERSION_CODE, currentVersionCode).apply();
- }
-
- private static void onUpgrade(final int oldVersionCode, final int newVersionCode) {
- if(oldVersionCode < 1030099) {
- // delete the now obsolete image cache
- // from now on, Glide will handle caching images
- new Thread() {
- public void run() {
- List<Feed> feeds = DBReader.getFeedList();
- for (Feed podcast : feeds) {
- List<FeedItem> episodes = DBReader.getFeedItemList(podcast);
- for (FeedItem episode : episodes) {
- FeedImage image = episode.getImage();
- if (image != null && image.isDownloaded() && image.getFile_url() != null) {
- File imageFile = new File(image.getFile_url());
- if (imageFile.exists()) {
- imageFile.delete();
- }
- image.setFile_url(null); // calls setDownloaded(false)
- DBWriter.setFeedImage(image);
- }
- }
- }
- }
- }.start();
- }
- if(oldVersionCode < 1050004) {
- if(MediaPlayer.isPrestoLibraryInstalled(context) && Build.VERSION.SDK_INT >= 16) {
- UserPreferences.enableSonic(true);
- }
- }
- }
-
-}
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 c835f8073..eef2fa4da 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java
@@ -4,7 +4,7 @@ import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
@@ -30,7 +30,7 @@ import rx.schedulers.Schedulers;
/**
* Displays the 'about' screen
*/
-public class AboutActivity extends ActionBarActivity {
+public class AboutActivity extends AppCompatActivity {
private static final String TAG = AboutActivity.class.getSimpleName();
@@ -87,7 +87,7 @@ public class AboutActivity extends ActionBarActivity {
res.recycle();
input = getAssets().open(filename);
String webViewData = IOUtils.toString(input, Charset.defaultCharset());
- if(false == webViewData.startsWith("<!DOCTYPE html>")) {
+ if(!webViewData.startsWith("<!DOCTYPE html>")) {
//webViewData = webViewData.replace("\n\n", "</p><p>");
webViewData = webViewData.replace("%", "&#37;");
webViewData =
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 b4e8d4d71..ca214de9e 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/AudioplayerActivity.java
@@ -1,156 +1,27 @@
package de.danoeh.antennapod.activity;
-import android.app.AlertDialog;
-import android.content.DialogInterface;
import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.res.Configuration;
-import android.os.Build;
-import android.support.annotation.Nullable;
-import android.support.design.widget.AppBarLayout;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentStatePagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.support.v4.widget.DrawerLayout;
-import android.support.v7.app.ActionBarDrawerToggle;
-import android.support.v7.widget.Toolbar;
+import android.support.v4.view.ViewCompat;
import android.text.TextUtils;
import android.util.Log;
-import android.util.TypedValue;
-import android.view.ContextMenu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ListView;
-import com.viewpagerindicator.CirclePageIndicator;
-
-import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.adapter.ChaptersListAdapter;
-import de.danoeh.antennapod.adapter.NavListAdapter;
-import de.danoeh.antennapod.core.asynctask.FeedRemover;
-import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
-import de.danoeh.antennapod.core.feed.EventDistributor;
-import de.danoeh.antennapod.core.feed.Feed;
-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.service.playback.PlayerStatus;
-import de.danoeh.antennapod.core.storage.DBReader;
-import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.util.playback.ExternalMedia;
-import de.danoeh.antennapod.core.util.playback.Playable;
-import de.danoeh.antennapod.core.util.playback.PlaybackController;
-import de.danoeh.antennapod.fragment.AddFeedFragment;
-import de.danoeh.antennapod.fragment.ChaptersFragment;
-import de.danoeh.antennapod.fragment.CoverFragment;
-import de.danoeh.antennapod.fragment.DownloadsFragment;
-import de.danoeh.antennapod.fragment.EpisodesFragment;
-import de.danoeh.antennapod.fragment.ItemDescriptionFragment;
-import de.danoeh.antennapod.fragment.PlaybackHistoryFragment;
-import de.danoeh.antennapod.fragment.QueueFragment;
-import de.danoeh.antennapod.menuhandler.NavDrawerActivity;
-import de.danoeh.antennapod.preferences.PreferenceController;
-import rx.Observable;
-import rx.Subscription;
-import rx.android.schedulers.AndroidSchedulers;
-import rx.schedulers.Schedulers;
+import de.danoeh.antennapod.dialog.VariableSpeedDialog;
/**
* Activity for playing audio files.
*/
-public class AudioplayerActivity extends MediaplayerActivity implements NavDrawerActivity {
-
- 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 = "AudioplayerActivity";
- private static final String PREFS = "AudioPlayerActivityPreferences";
- private static final String PREF_KEY_SELECTED_FRAGMENT_POSITION = "selectedFragmentPosition";
-
- public static final String[] NAV_DRAWER_TAGS = {
- QueueFragment.TAG,
- EpisodesFragment.TAG,
- DownloadsFragment.TAG,
- PlaybackHistoryFragment.TAG,
- AddFeedFragment.TAG
- };
+public class AudioplayerActivity extends MediaplayerInfoActivity {
+ public static final String TAG = "AudioPlayerActivity";
private AtomicBoolean isSetup = new AtomicBoolean(false);
- private DrawerLayout drawerLayout;
- private NavListAdapter navAdapter;
- private ListView navList;
- private View navDrawer;
- private ActionBarDrawerToggle drawerToggle;
- private int mPosition = -1;
-
- private Playable media;
- private ViewPager pager;
- private AudioplayerPagerAdapter pagerAdapter;
-
- private Subscription subscription;
-
- @Override
- protected void onStop() {
- super.onStop();
- Log.d(TAG, "onStop()");
- if(subscription != null) {
- subscription.unsubscribe();
- }
- EventDistributor.getInstance().unregister(contentUpdate);
- saveCurrentFragment();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- // don't risk creating memory leaks
- navAdapter = null;
- drawerToggle = null;
- pager = null;
- pagerAdapter = null;
- }
-
- @Override
- protected void chooseTheme() {
- setTheme(UserPreferences.getNoTitleTheme());
- }
-
- private void saveCurrentFragment() {
- if(pager == null) {
- return;
- }
- Log.d(TAG, "Saving preferences");
- SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
- prefs.edit()
- .putInt(PREF_KEY_SELECTED_FRAGMENT_POSITION, pager.getCurrentItem())
- .commit();
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- if(drawerToggle != null) {
- drawerToggle.onConfigurationChanged(newConfig);
- }
- }
-
- private void loadLastFragment() {
- Log.d(TAG, "Restoring instance state");
- SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
- int lastPosition = prefs.getInt(PREF_KEY_SELECTED_FRAGMENT_POSITION, -1);
- pager.setCurrentItem(lastPosition);
- }
-
@Override
protected void onResume() {
super.onResume();
@@ -167,431 +38,116 @@ public class AudioplayerActivity extends MediaplayerActivity implements NavDrawe
launchIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY,
true);
startService(launchIntent);
- }
- if(pagerAdapter != null && controller != null && controller.getMedia() != media) {
- media = controller.getMedia();
- pagerAdapter.onMediaChanged(media);
- }
-
- EventDistributor.getInstance().register(contentUpdate);
- loadData();
- }
-
- @Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- setIntent(intent);
- }
-
- @Override
- protected void onAwaitingVideoSurface() {
- Log.d(TAG, "onAwaitingVideoSurface was called in audio player -> switching to video player");
- startActivity(new Intent(this, VideoplayerActivity.class));
- }
-
- @Override
- protected void postStatusMsg(int resId) {
- if (resId == R.string.player_preparing_msg
- || resId == R.string.player_seeking_msg
- || resId == R.string.player_buffering_msg) {
- // TODO Show progress bar here
- }
- }
-
- @Override
- protected void clearStatusMsg() {
- // TODO Hide progress bar here
- }
-
-
- @Override
- protected void setupGUI() {
- if(isSetup.getAndSet(true)) {
- return;
- }
- super.setupGUI();
- Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
- setSupportActionBar(toolbar);
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- getSupportActionBar().setTitle("");
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- findViewById(R.id.shadow).setVisibility(View.GONE);
- AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appBar);
- float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, getResources().getDisplayMetrics());
- appBarLayout.setElevation(px);
- }
- drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
- navList = (ListView) findViewById(R.id.nav_list);
- navDrawer = findViewById(R.id.nav_layout);
-
- drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.drawer_open, R.string.drawer_close);
- drawerToggle.setDrawerIndicatorEnabled(false);
- drawerLayout.setDrawerListener(drawerToggle);
-
- navAdapter = new NavListAdapter(itemAccess, this);
- navList.setAdapter(navAdapter);
- navList.setOnItemClickListener((parent, view, position, id) -> {
- int viewType = parent.getAdapter().getItemViewType(position);
- if (viewType != NavListAdapter.VIEW_TYPE_SECTION_DIVIDER) {
- Intent intent = new Intent(AudioplayerActivity.this, MainActivity.class);
- intent.putExtra(MainActivity.EXTRA_NAV_TYPE, viewType);
- intent.putExtra(MainActivity.EXTRA_NAV_INDEX, position);
+ } else if (PlaybackService.isCasting()) {
+ Intent intent = PlaybackService.getPlayerActivityIntent(this);
+ if (!intent.getComponent().getClassName().equals(AudioplayerActivity.class.getName())) {
+ saveCurrentFragment();
+ finish();
startActivity(intent);
}
- drawerLayout.closeDrawer(navDrawer);
- });
- navList.setOnItemLongClickListener((parent, view, position, id) -> {
- if (position < navAdapter.getTags().size()) {
- showDrawerPreferencesDialog();
- return true;
- } else {
- mPosition = position;
- return false;
- }
- });
- registerForContextMenu(navList);
- drawerToggle.syncState();
-
- findViewById(R.id.nav_settings).setOnClickListener(v -> {
- drawerLayout.closeDrawer(navDrawer);
- startActivity(new Intent(AudioplayerActivity.this, PreferenceController.getPreferenceActivity()));
- });
-
- pager = (ViewPager) findViewById(R.id.pager);
- pagerAdapter = new AudioplayerPagerAdapter(getSupportFragmentManager());
- pager.setAdapter(pagerAdapter);
- CirclePageIndicator pageIndicator = (CirclePageIndicator) findViewById(R.id.page_indicator);
- pageIndicator.setViewPager(pager);
- loadLastFragment();
- pager.onSaveInstanceState();
- }
-
- @Override
- protected void onPositionObserverUpdate() {
- super.onPositionObserverUpdate();
- notifyMediaPositionChanged();
- }
-
- @Override
- protected boolean loadMediaInfo() {
- if (!super.loadMediaInfo()) {
- return false;
- }
- if(controller.getMedia() != media) {
- media = controller.getMedia();
- pagerAdapter.onMediaChanged(media);
- }
- return true;
- }
-
- public void notifyMediaPositionChanged() {
- if(pagerAdapter == null) {
- return;
- }
- ChaptersFragment chaptersFragment = pagerAdapter.getChaptersFragment();
- if(chaptersFragment != null) {
- ChaptersListAdapter adapter = (ChaptersListAdapter) chaptersFragment.getListAdapter();
- if (adapter != null) {
- adapter.notifyDataSetChanged();
- }
}
}
@Override
protected void onReloadNotification(int notificationCode) {
- if (notificationCode == PlaybackService.EXTRA_CODE_VIDEO) {
- Log.d(TAG, "ReloadNotification received, switching to Videoplayer now");
+ if (notificationCode == PlaybackService.EXTRA_CODE_CAST) {
+ Log.d(TAG, "ReloadNotification received, switching to Castplayer now");
+ saveCurrentFragment();
finish();
- startActivity(new Intent(this, VideoplayerActivity.class));
+ startActivity(new Intent(this, CastplayerActivity.class));
- }
- }
-
- @Override
- protected void onBufferStart() {
- postStatusMsg(R.string.player_buffering_msg);
- }
-
- @Override
- protected void onBufferEnd() {
- clearStatusMsg();
- }
-
- public PlaybackController getPlaybackController() {
- return controller;
- }
-
- @Override
- public boolean isDrawerOpen() {
- return drawerLayout != null && navDrawer != null && drawerLayout.isDrawerOpen(navDrawer);
- }
-
- @Override
- protected int getContentViewResourceId() {
- return R.layout.audioplayer_activity;
- }
-
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (drawerToggle != null && drawerToggle.onOptionsItemSelected(item)) {
- return true;
} else {
- return super.onOptionsItemSelected(item);
+ super.onReloadNotification(notificationCode);
}
}
@Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
- if(v.getId() != R.id.nav_list) {
+ protected void updatePlaybackSpeedButton() {
+ if(butPlaybackSpeed == null) {
return;
}
- AdapterView.AdapterContextMenuInfo adapterInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
- int position = adapterInfo.position;
- if(position < navAdapter.getSubscriptionOffset()) {
+ if (controller == null) {
+ butPlaybackSpeed.setVisibility(View.GONE);
return;
}
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.nav_feed_context, menu);
- Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
- menu.setHeaderTitle(feed.getTitle());
- // episodes are not loaded, so we cannot check if the podcast has new or unplayed ones!
- }
-
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- final int position = mPosition;
- mPosition = -1; // reset
- if(position < 0) {
- return false;
- }
- Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
- switch(item.getItemId()) {
- case R.id.mark_all_seen_item:
- DBWriter.markFeedSeen(feed.getId());
- return true;
- case R.id.mark_all_read_item:
- DBWriter.markFeedRead(feed.getId());
- return true;
- case R.id.remove_item:
- final FeedRemover remover = new FeedRemover(this, feed) {
- @Override
- protected void onPostExecute(Void result) {
- super.onPostExecute(result);
- }
- };
- ConfirmationDialog conDialog = new ConfirmationDialog(this,
- R.string.remove_feed_label,
- R.string.feed_delete_confirmation_msg) {
- @Override
- public void onConfirmButtonPressed(
- DialogInterface dialog) {
- dialog.dismiss();
- if (controller != null) {
- Playable playable = controller.getMedia();
- if (playable != null && playable instanceof FeedMedia) {
- FeedMedia media = (FeedMedia) playable;
- if (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));
- }
- }
- }
- }
- remover.executeAsync();
- }
- };
- conDialog.createNewDialog().show();
- return true;
- default:
- return super.onContextItemSelected(item);
- }
+ updatePlaybackSpeedButtonText();
+ ViewCompat.setAlpha(butPlaybackSpeed, controller.canSetPlaybackSpeed() ? 1.0f : 0.5f);
+ butPlaybackSpeed.setVisibility(View.VISIBLE);
}
@Override
- public void onBackPressed() {
- if(isDrawerOpen()) {
- drawerLayout.closeDrawer(navDrawer);
- } else if (pager == null || pager.getCurrentItem() == 0) {
- // If the user is currently looking at the first step, allow the system to handle the
- // Back button. This calls finish() on this activity and pops the back stack.
- super.onBackPressed();
- } else {
- // Otherwise, select the previous step.
- pager.setCurrentItem(pager.getCurrentItem() - 1);
- }
- }
-
- public 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];
- for (int i = 0; i < NAV_DRAWER_TAGS.length; i++) {
- String tag = NAV_DRAWER_TAGS[i];
- navLabels[i] = navAdapter.getLabel(tag);
- if (!hiddenDrawerItems.contains(tag)) {
- checked[i] = true;
- }
- }
-
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle(R.string.drawer_preferences);
- builder.setMultiChoiceItems(navLabels, checked, (dialog, which, isChecked) -> {
- if (isChecked) {
- hiddenDrawerItems.remove(NAV_DRAWER_TAGS[which]);
- } else {
- hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]);
- }
- });
- builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
- UserPreferences.setHiddenDrawerItems(hiddenDrawerItems);
- });
- builder.setNegativeButton(R.string.cancel_label, null);
- builder.create().show();
- }
-
- private DBReader.NavDrawerData navDrawerData;
-
- private void loadData() {
- subscription = Observable.fromCallable(() -> DBReader.getNavDrawerData())
- .subscribeOn(Schedulers.newThread())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(result -> {
- navDrawerData = result;
- if (navAdapter != null) {
- navAdapter.notifyDataSetChanged();
- }
- }, error -> {
- Log.e(TAG, Log.getStackTraceString(error));
- });
- }
-
-
-
- private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
-
- @Override
- public void update(EventDistributor eventDistributor, Integer arg) {
- if ((EventDistributor.FEED_LIST_UPDATE & arg) != 0) {
- Log.d(TAG, "Received contentUpdate Intent.");
- loadData();
- }
+ protected void updatePlaybackSpeedButtonText() {
+ if(butPlaybackSpeed == null) {
+ return;
}
- };
-
- private final NavListAdapter.ItemAccess itemAccess = new NavListAdapter.ItemAccess() {
- @Override
- public int getCount() {
- if (navDrawerData != null) {
- return navDrawerData.feeds.size();
- } else {
- return 0;
- }
+ if (controller == null) {
+ butPlaybackSpeed.setVisibility(View.GONE);
+ return;
}
-
- @Override
- public Feed getItem(int position) {
- if (navDrawerData != null && 0 <= position && position < navDrawerData.feeds.size()) {
- return navDrawerData.feeds.get(position);
- } else {
- return null;
+ float speed = 1.0f;
+ if(controller.canSetPlaybackSpeed()) {
+ try {
+ // we can only retrieve the playback speed from the controller/playback service
+ // once mediaplayer has been initialized
+ speed = Float.parseFloat(UserPreferences.getPlaybackSpeed());
+ } catch (NumberFormatException e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ UserPreferences.setPlaybackSpeed(String.valueOf(speed));
}
}
-
- @Override
- public int getSelectedItemIndex() {
- return -1;
- }
-
- @Override
- public int getQueueSize() {
- return (navDrawerData != null) ? navDrawerData.queueSize : 0;
- }
-
- @Override
- public int getNumberOfNewItems() {
- return (navDrawerData != null) ? navDrawerData.numNewItems : 0;
- }
-
- @Override
- public int getNumberOfDownloadedItems() {
- return (navDrawerData != null) ? navDrawerData.numDownloadedItems : 0;
- }
-
- @Override
- public int getReclaimableItems() {
- return (navDrawerData != null) ? navDrawerData.reclaimableSpace : 0;
- }
-
- @Override
- public int getFeedCounter(long feedId) {
- return navDrawerData != null ? navDrawerData.feedCounters.get(feedId) : 0;
- }
- };
-
- public interface AudioplayerContentFragment {
- void onMediaChanged(Playable media);
+ String speedStr = String.format("%.2fx", speed);
+ butPlaybackSpeed.setText(speedStr);
}
- private class AudioplayerPagerAdapter extends FragmentStatePagerAdapter {
-
- public AudioplayerPagerAdapter(FragmentManager fm) {
- super(fm);
- }
-
- private CoverFragment coverFragment;
- private ItemDescriptionFragment itemDescriptionFragment;
- private ChaptersFragment chaptersFragment;
-
- public void onMediaChanged(Playable media) {
- if(coverFragment != null) {
- coverFragment.onMediaChanged(media);
- }
- if(itemDescriptionFragment != null) {
- itemDescriptionFragment.onMediaChanged(media);
- }
- if(chaptersFragment != null) {
- chaptersFragment.onMediaChanged(media);
- }
- }
-
- @Nullable
- public ChaptersFragment getChaptersFragment() {
- return chaptersFragment;
+ @Override
+ protected void setupGUI() {
+ if(isSetup.getAndSet(true)) {
+ return;
}
-
- @Override
- public Fragment getItem(int position) {
- Log.d(TAG, "getItem(" + position + ")");
- switch (position) {
- case POS_COVER:
- if(coverFragment == null) {
- coverFragment = CoverFragment.newInstance(media);
- }
- return coverFragment;
- case POS_DESCR:
- if(itemDescriptionFragment == null) {
- itemDescriptionFragment = ItemDescriptionFragment.newInstance(media, true, true);
- }
- return itemDescriptionFragment;
- case POS_CHAPTERS:
- if(chaptersFragment == null) {
- chaptersFragment = ChaptersFragment.newInstance(media, controller);
+ super.setupGUI();
+ if(butCastDisconnect != null) {
+ butCastDisconnect.setVisibility(View.GONE);
+ }
+ if(butPlaybackSpeed != null) {
+ butPlaybackSpeed.setOnClickListener(v -> {
+ if (controller == null) {
+ return;
+ }
+ if (controller.canSetPlaybackSpeed()) {
+ String[] availableSpeeds = UserPreferences.getPlaybackSpeedArray();
+ String currentSpeed = UserPreferences.getPlaybackSpeed();
+
+ // Provide initial value in case the speed list has changed
+ // out from under us
+ // and our current speed isn't in the new list
+ String newSpeed;
+ if (availableSpeeds.length > 0) {
+ newSpeed = availableSpeeds[0];
+ } else {
+ newSpeed = "1.00";
}
- return chaptersFragment;
- default:
- return null;
- }
- }
- @Override
- public int getCount() {
- return NUM_CONTENT_FRAGMENTS;
+ for (int i = 0; i < availableSpeeds.length; i++) {
+ if (availableSpeeds[i].equals(currentSpeed)) {
+ if (i == availableSpeeds.length - 1) {
+ newSpeed = availableSpeeds[0];
+ } else {
+ newSpeed = availableSpeeds[i + 1];
+ }
+ break;
+ }
+ }
+ UserPreferences.setPlaybackSpeed(newSpeed);
+ controller.setPlaybackSpeed(Float.parseFloat(newSpeed));
+ } else {
+ VariableSpeedDialog.showGetPluginDialog(this);
+ }
+ });
+ butPlaybackSpeed.setOnLongClickListener(v -> {
+ VariableSpeedDialog.showDialog(this);
+ return true;
+ });
+ butPlaybackSpeed.setVisibility(View.VISIBLE);
}
}
-
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/CastEnabledActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/CastEnabledActivity.java
new file mode 100644
index 000000000..b8856c295
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/activity/CastEnabledActivity.java
@@ -0,0 +1,237 @@
+package de.danoeh.antennapod.activity;
+
+import android.content.SharedPreferences;
+import android.media.AudioManager;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.support.annotation.CallSuper;
+import android.support.v4.view.MenuItemCompat;
+import android.support.v7.app.AppCompatActivity;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.google.android.gms.cast.ApplicationMetadata;
+
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.cast.CastConsumer;
+import de.danoeh.antennapod.core.cast.CastManager;
+import de.danoeh.antennapod.core.cast.DefaultCastConsumer;
+import de.danoeh.antennapod.core.cast.SwitchableMediaRouteActionProvider;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.service.playback.PlaybackService;
+
+/**
+ * Activity that allows for showing the MediaRouter button whenever there's a cast device in the
+ * network.
+ */
+public abstract class CastEnabledActivity extends AppCompatActivity
+ implements SharedPreferences.OnSharedPreferenceChangeListener {
+ public static final String TAG = "CastEnabledActivity";
+
+ protected CastManager castManager;
+ protected SwitchableMediaRouteActionProvider mediaRouteActionProvider;
+ private final CastButtonVisibilityManager castButtonVisibilityManager = new CastButtonVisibilityManager();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).
+ registerOnSharedPreferenceChangeListener(this);
+
+ castManager = CastManager.getInstance();
+ castManager.addCastConsumer(castConsumer);
+ castButtonVisibilityManager.setPrefEnabled(UserPreferences.isCastEnabled());
+ onCastConnectionChanged(castManager.isConnected());
+ }
+
+ @Override
+ protected void onDestroy() {
+ PreferenceManager.getDefaultSharedPreferences(getApplicationContext())
+ .unregisterOnSharedPreferenceChangeListener(this);
+ castManager.removeCastConsumer(castConsumer);
+ super.onDestroy();
+ }
+
+ @Override
+ @CallSuper
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ getMenuInflater().inflate(R.menu.cast_enabled, menu);
+ castButtonVisibilityManager.setMenu(menu);
+ return true;
+ }
+
+ @Override
+ @CallSuper
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ mediaRouteActionProvider = castManager
+ .addMediaRouterButton(menu.findItem(R.id.media_route_menu_item));
+ mediaRouteActionProvider.setEnabled(castButtonVisibilityManager.shouldEnable());
+ return true;
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ castButtonVisibilityManager.setResumed(true);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ castButtonVisibilityManager.setResumed(false);
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ if (UserPreferences.PREF_CAST_ENABLED.equals(key)) {
+ boolean newValue = UserPreferences.isCastEnabled();
+ Log.d(TAG, "onSharedPreferenceChanged(), isCastEnabled set to " + newValue);
+ castButtonVisibilityManager.setPrefEnabled(newValue);
+ // PlaybackService has its own listener, so if it's active we don't have to take action here.
+ if (!newValue && !PlaybackService.isRunning) {
+ CastManager.getInstance().disconnect();
+ }
+ }
+ }
+
+ CastConsumer castConsumer = new DefaultCastConsumer() {
+ @Override
+ public void onApplicationConnected(ApplicationMetadata appMetadata, String sessionId, boolean wasLaunched) {
+ onCastConnectionChanged(true);
+ }
+
+ @Override
+ public void onDisconnected() {
+ onCastConnectionChanged(false);
+ }
+ };
+
+ private void onCastConnectionChanged(boolean connected) {
+ if (connected) {
+ castButtonVisibilityManager.onConnected();
+ setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE);
+ } else {
+ castButtonVisibilityManager.onDisconnected();
+ setVolumeControlStream(AudioManager.STREAM_MUSIC);
+ }
+ }
+
+ /**
+ * Should be called by any activity or fragment for which the cast button should be shown.
+ *
+ * @param showAsAction refer to {@link MenuItem#setShowAsAction(int)}
+ */
+ public final void requestCastButton(int showAsAction) {
+ castButtonVisibilityManager.requestCastButton(showAsAction);
+ }
+
+ private class CastButtonVisibilityManager {
+ private volatile boolean prefEnabled = false;
+ private volatile boolean viewRequested = false;
+ private volatile boolean resumed = false;
+ private volatile boolean connected = false;
+ private volatile int showAsAction = MenuItem.SHOW_AS_ACTION_IF_ROOM;
+ private Menu menu;
+
+ public synchronized void setPrefEnabled(boolean newValue) {
+ if (prefEnabled != newValue && resumed && (viewRequested || connected)) {
+ if (newValue) {
+ castManager.incrementUiCounter();
+ } else {
+ castManager.decrementUiCounter();
+ }
+ }
+ prefEnabled = newValue;
+ if (mediaRouteActionProvider != null) {
+ mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
+ }
+ }
+
+ public synchronized void setResumed(boolean newValue) {
+ if (resumed == newValue) {
+ Log.e(TAG, "resumed should never change to the same value");
+ return;
+ }
+ resumed = newValue;
+ if (prefEnabled && (viewRequested || connected)) {
+ if (resumed) {
+ castManager.incrementUiCounter();
+ } else {
+ castManager.decrementUiCounter();
+ }
+ }
+ }
+
+ public synchronized void setViewRequested(boolean newValue) {
+ if (viewRequested != newValue && resumed && prefEnabled && !connected) {
+ if (newValue) {
+ castManager.incrementUiCounter();
+ } else {
+ castManager.decrementUiCounter();
+ }
+ }
+ viewRequested = newValue;
+ if (mediaRouteActionProvider != null) {
+ mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
+ }
+ }
+
+ public synchronized void setConnected(boolean newValue) {
+ if (connected != newValue && resumed && prefEnabled && !prefEnabled) {
+ if (newValue) {
+ castManager.incrementUiCounter();
+ } else {
+ castManager.decrementUiCounter();
+ }
+ }
+ connected = newValue;
+ if (mediaRouteActionProvider != null) {
+ mediaRouteActionProvider.setEnabled(prefEnabled && (viewRequested || connected));
+ }
+ }
+
+ public synchronized boolean shouldEnable() {
+ return prefEnabled && viewRequested;
+ }
+
+ public void setMenu(Menu menu) {
+ setViewRequested(false);
+ showAsAction = MenuItem.SHOW_AS_ACTION_IF_ROOM;
+ this.menu = menu;
+ setShowAsAction();
+ }
+
+ public void requestCastButton(int showAsAction) {
+ setViewRequested(true);
+ this.showAsAction = showAsAction;
+ setShowAsAction();
+ }
+
+ public void onConnected() {
+ setConnected(true);
+ setShowAsAction();
+ }
+
+ public void onDisconnected() {
+ setConnected(false);
+ setShowAsAction();
+ }
+
+ private void setShowAsAction() {
+ if (menu == null) {
+ Log.d(TAG, "setShowAsAction() without a menu");
+ return;
+ }
+ MenuItem item = menu.findItem(R.id.media_route_menu_item);
+ if (item == null) {
+ Log.e(TAG, "setShowAsAction(), but cast button not inflated");
+ return;
+ }
+ MenuItemCompat.setShowAsAction(item, connected? MenuItem.SHOW_AS_ACTION_ALWAYS : showAsAction);
+ }
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java
new file mode 100644
index 000000000..1ca4d095f
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/activity/CastplayerActivity.java
@@ -0,0 +1,83 @@
+package de.danoeh.antennapod.activity;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+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 AtomicBoolean isSetup = new AtomicBoolean(false);
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (!PlaybackService.isCasting()) {
+ Intent intent = PlaybackService.getPlayerActivityIntent(this);
+ if (!intent.getComponent().getClassName().equals(CastplayerActivity.class.getName())) {
+ finish();
+ startActivity(intent);
+ }
+ }
+ }
+
+ @Override
+ protected void onReloadNotification(int notificationCode) {
+ if (notificationCode == PlaybackService.EXTRA_CODE_AUDIO) {
+ Log.d(TAG, "ReloadNotification received, switching to Audioplayer now");
+ saveCurrentFragment();
+ finish();
+ startActivity(new Intent(this, AudioplayerActivity.class));
+ } else {
+ super.onReloadNotification(notificationCode);
+ }
+ }
+
+ @Override
+ protected void setupGUI() {
+ if(isSetup.getAndSet(true)) {
+ return;
+ }
+ super.setupGUI();
+ if (butPlaybackSpeed != null) {
+ butPlaybackSpeed.setVisibility(View.GONE);
+ }
+ if (butCastDisconnect != null) {
+ butCastDisconnect.setOnClickListener(v -> castManager.disconnect());
+ butCastDisconnect.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ if (!PlaybackService.isCasting()) {
+ Intent intent = PlaybackService.getPlayerActivityIntent(this);
+ if (!intent.getComponent().getClassName().equals(CastplayerActivity.class.getName())) {
+ saveCurrentFragment();
+ finish();
+ startActivity(intent);
+ }
+ }
+ super.onResume();
+ }
+
+ @Override
+ protected void onBufferStart() {
+ //sbPosition.setIndeterminate(true);
+ sbPosition.setEnabled(false);
+ }
+
+ @Override
+ protected void onBufferEnd() {
+ //sbPosition.setIndeterminate(false);
+ sbPosition.setEnabled(true);
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java
index 62e85120d..5fd69ef6a 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/DirectoryChooserActivity.java
@@ -243,7 +243,7 @@ public class DirectoryChooserActivity extends AppCompatActivity {
@Override
public void onEvent(int event, String path) {
Log.d(TAG, "FileObserver received event " + event);
- runOnUiThread(() -> refreshDirectory());
+ runOnUiThread(DirectoryChooserActivity.this::refreshDirectory);
}
};
}
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 365c4216d..41b2debdc 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/DownloadAuthenticationActivity.java
@@ -5,7 +5,6 @@ import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
-import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
@@ -73,31 +72,25 @@ public class DownloadAuthenticationActivity extends ActionBarActivity {
txtvDescription.setText(txtvDescription.getText() + ":\n\n" + request.getTitle());
- butCancel.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- setResult(Activity.RESULT_CANCELED);
- finish();
- }
+ butCancel.setOnClickListener(v -> {
+ setResult(Activity.RESULT_CANCELED);
+ finish();
});
- butConfirm.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- String username = etxtUsername.getText().toString();
- String password = etxtPassword.getText().toString();
- request.setUsername(username);
- request.setPassword(password);
- Intent result = new Intent();
- result.putExtra(RESULT_REQUEST, request);
- setResult(Activity.RESULT_OK, result);
-
- if (sendToDownloadRequester) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Sending request to DownloadRequester");
- DownloadRequester.getInstance().download(DownloadAuthenticationActivity.this, request);
- }
- finish();
+ butConfirm.setOnClickListener(v -> {
+ String username = etxtUsername.getText().toString();
+ String password = etxtPassword.getText().toString();
+ request.setUsername(username);
+ request.setPassword(password);
+ Intent result = new Intent();
+ result.putExtra(RESULT_REQUEST, request);
+ setResult(Activity.RESULT_OK, result);
+
+ if (sendToDownloadRequester) {
+ if (BuildConfig.DEBUG) Log.d(TAG, "Sending request to DownloadRequester");
+ DownloadRequester.getInstance().download(DownloadAuthenticationActivity.this, request);
}
+ finish();
});
}
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 9116decb0..d4356719e 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java
@@ -139,20 +139,14 @@ public class FeedInfoActivity extends ActionBarActivity {
Log.d(TAG, "Author is " + feed.getAuthor());
Log.d(TAG, "URL is " + feed.getDownload_url());
FeedPreferences prefs = feed.getPreferences();
- imgvCover.post(new Runnable() {
-
- @Override
- public void run() {
- Glide.with(FeedInfoActivity.this)
- .load(feed.getImageUri())
- .placeholder(R.color.light_gray)
- .error(R.color.light_gray)
- .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
- .fitCenter()
- .dontAnimate()
- .into(imgvCover);
- }
- });
+ imgvCover.post(() -> Glide.with(FeedInfoActivity.this)
+ .load(feed.getImageUri())
+ .placeholder(R.color.light_gray)
+ .error(R.color.light_gray)
+ .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
+ .fitCenter()
+ .dontAnimate()
+ .into(imgvCover));
txtvTitle.setText(feed.getTitle());
String description = feed.getDescription();
@@ -245,7 +239,11 @@ public class FeedInfoActivity extends ActionBarActivity {
}
}
};
- loadTask.execute(feedId);
+ if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
+ loadTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, feedId);
+ } else {
+ loadTask.execute(feedId);
+ }
}
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 3b10ba4c3..be1c9f9e6 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/FlattrAuthActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/FlattrAuthActivity.java
@@ -9,17 +9,17 @@ import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
+
+import org.shredzone.flattr4j.exception.FlattrException;
+
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;
-import org.shredzone.flattr4j.exception.FlattrException;
-
/** Guides the user through the authentication process */
public class FlattrAuthActivity extends ActionBarActivity {
@@ -46,25 +46,19 @@ public class FlattrAuthActivity extends ActionBarActivity {
butAuthenticate = (Button) findViewById(R.id.but_authenticate);
butReturn = (Button) findViewById(R.id.but_return_home);
- butReturn.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(FlattrAuthActivity.this, MainActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- }
- });
+ butReturn.setOnClickListener(v -> {
+ Intent intent = new Intent(FlattrAuthActivity.this, MainActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(intent);
+ });
- butAuthenticate.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- try {
- FlattrUtils.startAuthProcess(FlattrAuthActivity.this);
- } catch (FlattrException e) {
- e.printStackTrace();
- }
- }
- });
+ butAuthenticate.setOnClickListener(v -> {
+ try {
+ FlattrUtils.startAuthProcess(FlattrAuthActivity.this);
+ } catch (FlattrException e) {
+ e.printStackTrace();
+ }
+ });
}
public static FlattrAuthActivity getInstance() {
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 bd7da7c03..b7c7d86c7 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java
@@ -7,7 +7,6 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.database.DataSetObserver;
-import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -17,11 +16,11 @@ import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AlertDialog;
-import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.util.TypedValue;
import android.view.ContextMenu;
+import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
@@ -43,15 +42,13 @@ import de.danoeh.antennapod.core.event.ProgressEvent;
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.FeedMedia;
+import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
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.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
+import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.core.util.StorageUtils;
-import de.danoeh.antennapod.core.util.playback.Playable;
-import de.danoeh.antennapod.core.util.playback.PlaybackController;
import de.danoeh.antennapod.dialog.RatingDialog;
import de.danoeh.antennapod.fragment.AddFeedFragment;
import de.danoeh.antennapod.fragment.DownloadsFragment;
@@ -60,6 +57,7 @@ import de.danoeh.antennapod.fragment.ExternalPlayerFragment;
import de.danoeh.antennapod.fragment.ItemlistFragment;
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;
@@ -71,7 +69,7 @@ import rx.schedulers.Schedulers;
/**
* The activity that is shown when the user launches the app.
*/
-public class MainActivity extends AppCompatActivity implements NavDrawerActivity {
+public class MainActivity extends CastEnabledActivity implements NavDrawerActivity {
private static final String TAG = "MainActivity";
@@ -86,6 +84,7 @@ public class MainActivity extends AppCompatActivity implements NavDrawerActivity
public static final String EXTRA_NAV_INDEX = "nav_index";
public static final String EXTRA_FRAGMENT_TAG = "fragment_tag";
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";
@@ -93,9 +92,11 @@ public class MainActivity extends AppCompatActivity implements NavDrawerActivity
public static final String[] NAV_DRAWER_TAGS = {
QueueFragment.TAG,
EpisodesFragment.TAG,
+ SubscriptionFragment.TAG,
DownloadsFragment.TAG,
PlaybackHistoryFragment.TAG,
- AddFeedFragment.TAG
+ AddFeedFragment.TAG,
+ NavListAdapter.SUBSCRIPTION_LIST_TAG
};
private Toolbar toolbar;
@@ -121,7 +122,6 @@ public class MainActivity extends AppCompatActivity implements NavDrawerActivity
super.onCreate(savedInstanceState);
StorageUtils.checkStorageAvailability(this);
setContentView(R.layout.main);
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
@@ -184,7 +184,7 @@ public class MainActivity extends AppCompatActivity implements NavDrawerActivity
loadFragment(lastFragment, null);
} else {
try {
- loadFeedFragmentById(Integer.valueOf(lastFragment), null);
+ loadFeedFragmentById(Integer.parseInt(lastFragment), null);
} catch (NumberFormatException e) {
// it's not a number, this happens if we removed
// a label from the NAV_DRAWER_TAGS
@@ -270,7 +270,7 @@ public class MainActivity extends AppCompatActivity implements NavDrawerActivity
}
public void loadFragment(int index, Bundle args) {
- Log.d(TAG, "loadFragment(index: " + index + ", args: " + args +")");
+ Log.d(TAG, "loadFragment(index: " + index + ", args: " + args + ")");
if (index < navAdapter.getSubscriptionOffset()) {
String tag = navAdapter.getTags().get(index);
loadFragment(tag, args);
@@ -299,6 +299,10 @@ public class MainActivity extends AppCompatActivity implements NavDrawerActivity
case AddFeedFragment.TAG:
fragment = new AddFeedFragment();
break;
+ case SubscriptionFragment.TAG:
+ SubscriptionFragment subscriptionFragment = new SubscriptionFragment();
+ fragment = subscriptionFragment;
+ break;
default:
// default to the queue
tag = QueueFragment.TAG;
@@ -464,8 +468,9 @@ public class MainActivity extends AppCompatActivity implements NavDrawerActivity
StorageUtils.checkStorageAvailability(this);
Intent intent = getIntent();
- if (navDrawerData != null && intent.hasExtra(EXTRA_NAV_TYPE) &&
- (intent.hasExtra(EXTRA_NAV_INDEX) || intent.hasExtra(EXTRA_FRAGMENT_TAG))) {
+ if (intent.hasExtra(EXTRA_FEED_ID) ||
+ (navDrawerData != null && intent.hasExtra(EXTRA_NAV_TYPE) &&
+ (intent.hasExtra(EXTRA_NAV_INDEX) || intent.hasExtra(EXTRA_FRAGMENT_TAG)))) {
handleNavIntent();
}
loadData();
@@ -500,6 +505,26 @@ public class MainActivity extends AppCompatActivity implements NavDrawerActivity
}
@Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ boolean retVal = super.onCreateOptionsMenu(menu);
+ switch (getLastNavFragment()) {
+ case QueueFragment.TAG:
+ case EpisodesFragment.TAG:
+ requestCastButton(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ return retVal;
+ case DownloadsFragment.TAG:
+ case PlaybackHistoryFragment.TAG:
+ case AddFeedFragment.TAG:
+ case SubscriptionFragment.TAG:
+ return retVal;
+ default:
+ requestCastButton(MenuItem.SHOW_AS_ACTION_NEVER);
+ return retVal;
+ }
+
+ }
+
+ @Override
public boolean onOptionsItemSelected(MenuItem item) {
if (drawerToggle.onOptionsItemSelected(item)) {
return true;
@@ -565,21 +590,15 @@ public class MainActivity extends AppCompatActivity implements NavDrawerActivity
public void onConfirmButtonPressed(
DialogInterface dialog) {
dialog.dismiss();
- if (externalPlayerFragment != null) {
- PlaybackController controller = externalPlayerFragment.getPlaybackControllerTestingOnly();
- if (controller != null) {
- Playable playable = controller.getMedia();
- if (playable != null && playable instanceof FeedMedia) {
- FeedMedia media = (FeedMedia) playable;
- if (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));
- }
- }
- }
+ long mediaId = PlaybackPreferences.getCurrentlyPlayingFeedMediaId();
+ if (mediaId > 0 &&
+ FeedItemUtil.indexOfItemWithMediaId(feed.getItems(), mediaId) >= 0) {
+ Log.d(TAG, "Currently playing episode is about to be deleted, skipping");
+ remover.skipOnCompletion = true;
+ int playerStatus = PlaybackPreferences.getCurrentPlayerStatus();
+ if(playerStatus == PlaybackPreferences.PLAYER_STATUS_PLAYING) {
+ sendBroadcast(new Intent(
+ PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE));
}
}
remover.executeAsync();
@@ -652,10 +671,23 @@ public class MainActivity extends AppCompatActivity implements NavDrawerActivity
public int getFeedCounter(long feedId) {
return navDrawerData != null ? navDrawerData.feedCounters.get(feedId) : 0;
}
+
+ @Override
+ public int getFeedCounterSum() {
+ if(navDrawerData == null) {
+ return 0;
+ }
+ int sum = 0;
+ for(int counter : navDrawerData.feedCounters.values()) {
+ sum += counter;
+ }
+ return sum;
+ }
+
};
private void loadData() {
- subscription = Observable.fromCallable(() -> DBReader.getNavDrawerData())
+ subscription = Observable.fromCallable(DBReader::getNavDrawerData)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
@@ -674,6 +706,12 @@ public class MainActivity extends AppCompatActivity implements NavDrawerActivity
public void onEvent(QueueEvent event) {
Log.d(TAG, "onEvent(" + event + ")");
+ // we are only interested in the number of queue items, not download status or position
+ if(event.action == QueueEvent.Action.DELETED_MEDIA ||
+ event.action == QueueEvent.Action.SORTED ||
+ event.action == QueueEvent.Action.MOVED) {
+ return;
+ }
loadData();
}
@@ -709,15 +747,19 @@ public class MainActivity extends AppCompatActivity implements NavDrawerActivity
private void handleNavIntent() {
Log.d(TAG, "handleNavIntent()");
Intent intent = getIntent();
- if (intent.hasExtra(EXTRA_NAV_TYPE) &&
- intent.hasExtra(EXTRA_NAV_INDEX) || intent.hasExtra(EXTRA_FRAGMENT_TAG)) {
+ if (intent.hasExtra(EXTRA_FEED_ID) ||
+ (intent.hasExtra(EXTRA_NAV_TYPE) &&
+ (intent.hasExtra(EXTRA_NAV_INDEX) || intent.hasExtra(EXTRA_FRAGMENT_TAG)))) {
int index = intent.getIntExtra(EXTRA_NAV_INDEX, -1);
String tag = intent.getStringExtra(EXTRA_FRAGMENT_TAG);
Bundle args = intent.getBundleExtra(EXTRA_FRAGMENT_ARGS);
+ long feedId = intent.getLongExtra(EXTRA_FEED_ID, 0);
if (index >= 0) {
loadFragment(index, args);
} else if (tag != null) {
loadFragment(tag, args);
+ } else if(feedId > 0) {
+ loadFeedFragmentById(feedId, args);
}
}
setIntent(new Intent(MainActivity.this, MainActivity.class)); // to avoid handling the intent twice when the configuration changes
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 61815757f..71d288725 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
@@ -6,13 +6,10 @@ import android.content.SharedPreferences;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PixelFormat;
-import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
-import android.support.v4.view.ViewCompat;
import android.support.v7.app.AlertDialog;
-import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
@@ -58,7 +55,7 @@ import rx.schedulers.Schedulers;
* Provides general features which are both needed for playing audio and video
* files.
*/
-public abstract class MediaplayerActivity extends AppCompatActivity implements OnSeekBarChangeListener {
+public abstract class MediaplayerActivity extends CastEnabledActivity implements OnSeekBarChangeListener {
private static final String TAG = "MediaplayerActivity";
private static final String PREFS = "MediaPlayerActivityPreferences";
private static final String PREF_SHOW_TIME_LEFT = "showTimeLeft";
@@ -68,7 +65,6 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
protected TextView txtvPosition;
protected TextView txtvLength;
protected SeekBar sbPosition;
- protected Button butPlaybackSpeed;
protected ImageButton butRev;
protected TextView txtvRev;
protected ImageButton butPlay;
@@ -129,8 +125,8 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
}
@Override
- public void postStatusMsg(int msg) {
- MediaplayerActivity.this.postStatusMsg(msg);
+ public void postStatusMsg(int msg, boolean showToast) {
+ MediaplayerActivity.this.postStatusMsg(msg, showToast);
}
@Override
@@ -173,12 +169,21 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
super.setScreenOn(enable);
MediaplayerActivity.this.setScreenOn(enable);
}
+
+ @Override
+ public void onSetSpeedAbilityChanged() {
+ MediaplayerActivity.this.onSetSpeedAbilityChanged();
+ }
};
+ }
+ protected void onSetSpeedAbilityChanged() {
+ Log.d(TAG, "onSetSpeedAbilityChanged()");
+ updatePlaybackSpeedButton();
}
protected void onPlaybackSpeedChange() {
- updateButPlaybackSpeed();
+ updatePlaybackSpeedButtonText();
}
protected void onServiceQueried() {
@@ -199,7 +204,6 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
Log.d(TAG, "onCreate()");
StorageUtils.checkStorageAvailability(this);
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
orientation = getResources().getConfiguration().orientation;
getWindow().setFormat(PixelFormat.TRANSPARENT);
@@ -207,11 +211,11 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
@Override
protected void onPause() {
- super.onPause();
if(controller != null) {
controller.reinitServiceIfPaused();
controller.pause();
}
+ super.onPause();
}
/**
@@ -249,18 +253,16 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
controller.release();
}
controller = newPlaybackController();
- if(butPlay != null) {
- butPlay.setOnClickListener(controller.newOnPlayButtonClickListener());
- }
}
@Override
protected void onStop() {
- super.onStop();
Log.d(TAG, "onStop()");
if (controller != null) {
controller.release();
+ controller = null; // prevent leak
}
+ super.onStop();
}
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@@ -279,6 +281,7 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
+ requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.mediaplayer, menu);
return true;
@@ -389,18 +392,11 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
.getSleepTimerTimeLeft()));
stDialog.positiveText(R.string.disable_sleeptimer_label);
stDialog.negativeText(R.string.cancel_label);
- stDialog.callback(new MaterialDialog.ButtonCallback() {
- @Override
- public void onPositive(MaterialDialog dialog) {
- dialog.dismiss();
- controller.disableSleepTimer();
- }
-
- @Override
- public void onNegative(MaterialDialog dialog) {
- dialog.dismiss();
- }
+ stDialog.onPositive((dialog, which) -> {
+ dialog.dismiss();
+ controller.disableSleepTimer();
});
+ stDialog.onNegative((dialog, which) -> dialog.dismiss());
stDialog.build().show();
}
break;
@@ -466,9 +462,7 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
txtvPlaybackSpeed.setText(speedStr);
} else if(fromUser) {
float speed = Float.valueOf(UserPreferences.getPlaybackSpeed());
- barPlaybackSpeed.post(() -> {
- barPlaybackSpeed.setProgress((int) (20 * speed) - 10);
- });
+ barPlaybackSpeed.post(() -> barPlaybackSpeed.setProgress((int) (20 * speed) - 10));
}
}
@@ -486,9 +480,9 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
barPlaybackSpeed.setProgress((int) (20 * currentSpeed) - 10);
final SeekBar barLeftVolume = (SeekBar) dialog.findViewById(R.id.volume_left);
- barLeftVolume.setProgress(100);
+ barLeftVolume.setProgress(UserPreferences.getLeftVolumePercentage());
final SeekBar barRightVolume = (SeekBar) dialog.findViewById(R.id.volume_right);
- barRightVolume.setProgress(100);
+ barRightVolume.setProgress(UserPreferences.getRightVolumePercentage());
final CheckBox stereoToMono = (CheckBox) dialog.findViewById(R.id.stereo_to_mono);
stereoToMono.setChecked(UserPreferences.stereoToMono());
if (controller != null && !controller.canDownmix()) {
@@ -500,14 +494,9 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
barLeftVolume.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- float leftVolume = 1.0f, rightVolume = 1.0f;
- if (progress < 100) {
- leftVolume = progress / 100.0f;
- }
- if (barRightVolume.getProgress() < 100) {
- rightVolume = barRightVolume.getProgress() / 100.0f;
- }
- controller.setVolume(leftVolume, rightVolume);
+ controller.setVolume(
+ Converter.getVolumeFromPercentage(progress),
+ Converter.getVolumeFromPercentage(barRightVolume.getProgress()));
}
@Override
@@ -521,14 +510,9 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
barRightVolume.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- float leftVolume = 1.0f, rightVolume = 1.0f;
- if (progress < 100) {
- rightVolume = progress / 100.0f;
- }
- if (barLeftVolume.getProgress() < 100) {
- leftVolume = barLeftVolume.getProgress() / 100.0f;
- }
- controller.setVolume(leftVolume, rightVolume);
+ controller.setVolume(
+ Converter.getVolumeFromPercentage(barLeftVolume.getProgress()),
+ Converter.getVolumeFromPercentage(progress));
}
@Override
@@ -601,7 +585,7 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
*/
protected abstract void onAwaitingVideoSurface();
- protected abstract void postStatusMsg(int resId);
+ protected abstract void postStatusMsg(int resId, boolean showToast);
protected abstract void clearStatusMsg();
@@ -649,25 +633,22 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
if (media != null) {
onPositionObserverUpdate();
checkFavorite();
- if(butPlaybackSpeed != null) {
- if (controller == null) {
- butPlaybackSpeed.setVisibility(View.GONE);
- } else {
- butPlaybackSpeed.setVisibility(View.VISIBLE);
- if (controller.canSetPlaybackSpeed()) {
- ViewCompat.setAlpha(butPlaybackSpeed, 1.0f);
- } else {
- ViewCompat.setAlpha(butPlaybackSpeed, 0.5f);
- }
- }
- updateButPlaybackSpeed();
- }
+ updatePlaybackSpeedButton();
return true;
} else {
return false;
}
}
+ protected void updatePlaybackSpeedButton() {
+ // Only meaningful on AudioplayerActivity, where it is overridden.
+ }
+
+ protected void updatePlaybackSpeedButtonText() {
+ // Only meaningful on AudioplayerActivity, where it is overridden.
+ }
+
+
protected void setupGUI() {
setContentView(getContentViewResourceId());
sbPosition = (SeekBar) findViewById(R.id.sbPosition);
@@ -677,28 +658,29 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
showTimeLeft = prefs.getBoolean(PREF_SHOW_TIME_LEFT, false);
Log.d("timeleft", showTimeLeft ? "true" : "false");
txtvLength = (TextView) findViewById(R.id.txtvLength);
- txtvLength.setOnClickListener(v -> {
- showTimeLeft = !showTimeLeft;
- Playable media = controller.getMedia();
- if (media == null) {
- return;
- }
+ if (txtvLength != null) {
+ txtvLength.setOnClickListener(v -> {
+ showTimeLeft = !showTimeLeft;
+ Playable media = controller.getMedia();
+ if (media == null) {
+ return;
+ }
- String length;
- if (showTimeLeft) {
- length = "-" + Converter.getDurationStringLong(media.getDuration() - media.getPosition());
- } else {
- length = Converter.getDurationStringLong(media.getDuration());
- }
- txtvLength.setText(length);
+ String length;
+ if (showTimeLeft) {
+ length = "-" + Converter.getDurationStringLong(media.getDuration() - media.getPosition());
+ } else {
+ length = Converter.getDurationStringLong(media.getDuration());
+ }
+ txtvLength.setText(length);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putBoolean(PREF_SHOW_TIME_LEFT, showTimeLeft);
- editor.apply();
- Log.d("timeleft on click", showTimeLeft ? "true" : "false");
- });
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putBoolean(PREF_SHOW_TIME_LEFT, showTimeLeft);
+ editor.apply();
+ Log.d("timeleft on click", showTimeLeft ? "true" : "false");
+ });
+ }
- butPlaybackSpeed = (Button) findViewById(R.id.butPlaybackSpeed);
butRev = (ImageButton) findViewById(R.id.butRev);
txtvRev = (TextView) findViewById(R.id.txtvRev);
if (txtvRev != null) {
@@ -718,52 +700,8 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
// BUTTON SETUP
- if(butPlaybackSpeed != null) {
- butPlaybackSpeed.setOnClickListener(v -> {
- if (controller == null) {
- return;
- }
- if (controller.canSetPlaybackSpeed()) {
- String[] availableSpeeds = UserPreferences.getPlaybackSpeedArray();
- String currentSpeed = UserPreferences.getPlaybackSpeed();
-
- // Provide initial value in case the speed list has changed
- // out from under us
- // and our current speed isn't in the new list
- String newSpeed;
- if (availableSpeeds.length > 0) {
- newSpeed = availableSpeeds[0];
- } else {
- newSpeed = "1.00";
- }
-
- for (int i = 0; i < availableSpeeds.length; i++) {
- if (availableSpeeds[i].equals(currentSpeed)) {
- if (i == availableSpeeds.length - 1) {
- newSpeed = availableSpeeds[0];
- } else {
- newSpeed = availableSpeeds[i + 1];
- }
- break;
- }
- }
- UserPreferences.setPlaybackSpeed(newSpeed);
- controller.setPlaybackSpeed(Float.parseFloat(newSpeed));
- } else {
- VariableSpeedDialog.showGetPluginDialog(this);
- }
- });
- butPlaybackSpeed.setOnLongClickListener(v -> {
- VariableSpeedDialog.showDialog(this);
- return true;
- });
- }
-
if (butRev != null) {
- butRev.setOnClickListener(v -> {
- int curr = controller.getPosition();
- controller.seekTo(curr - UserPreferences.getRewindSecs() * 1000);
- });
+ butRev.setOnClickListener(v -> onRewind());
butRev.setOnLongClickListener(new View.OnLongClickListener() {
int choice;
@@ -800,13 +738,10 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
});
}
- butPlay.setOnClickListener(controller.newOnPlayButtonClickListener());
+ butPlay.setOnClickListener(v -> onPlayPause());
if (butFF != null) {
- butFF.setOnClickListener(v -> {
- int curr = controller.getPosition();
- controller.seekTo(curr + UserPreferences.getFastFowardSecs() * 1000);
- });
+ butFF.setOnClickListener(v -> onFastForward());
butFF.setOnLongClickListener(new View.OnLongClickListener() {
int choice;
@@ -844,12 +779,33 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
}
if (butSkip != null) {
- butSkip.setOnClickListener(v -> {
- sendBroadcast(new Intent(PlaybackService.ACTION_SKIP_CURRENT_EPISODE));
- });
+ butSkip.setOnClickListener(v -> sendBroadcast(new Intent(PlaybackService.ACTION_SKIP_CURRENT_EPISODE)));
}
}
+ protected void onRewind() {
+ if (controller == null) {
+ return;
+ }
+ int curr = controller.getPosition();
+ controller.seekTo(curr - UserPreferences.getRewindSecs() * 1000);
+ }
+
+ protected void onPlayPause() {
+ if(controller == null) {
+ return;
+ }
+ controller.playPause();
+ }
+
+ protected void onFastForward() {
+ if (controller == null) {
+ return;
+ }
+ int curr = controller.getPosition();
+ controller.seekTo(curr + UserPreferences.getFastFowardSecs() * 1000);
+ }
+
protected abstract int getContentViewResourceId();
void handleError(int errorCode) {
@@ -880,20 +836,6 @@ public abstract class MediaplayerActivity extends AppCompatActivity implements O
}
}
- private void updateButPlaybackSpeed() {
- if (controller != null && butPlaybackSpeed != null) {
- float speed = 1.0f;
- try {
- speed = Float.parseFloat(UserPreferences.getPlaybackSpeed());
- } catch(NumberFormatException e) {
- Log.e(TAG, Log.getStackTraceString(e));
- UserPreferences.setPlaybackSpeed(String.valueOf(speed));
- }
- String speedStr = String.format("%.2fx", speed);
- butPlaybackSpeed.setText(speedStr);
- }
- }
-
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
if (controller != null) {
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java
new file mode 100644
index 000000000..647745e39
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java
@@ -0,0 +1,620 @@
+package de.danoeh.antennapod.activity;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.Configuration;
+import android.os.Build;
+import android.support.annotation.Nullable;
+import android.support.design.widget.AppBarLayout;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentStatePagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v7.app.ActionBarDrawerToggle;
+import android.support.v7.widget.Toolbar;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.ContextMenu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.Button;
+import android.widget.ImageButton;
+import android.widget.ListView;
+import android.widget.Toast;
+
+import com.viewpagerindicator.CirclePageIndicator;
+
+import java.util.List;
+
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.adapter.ChaptersListAdapter;
+import de.danoeh.antennapod.adapter.NavListAdapter;
+import de.danoeh.antennapod.core.asynctask.FeedRemover;
+import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
+import de.danoeh.antennapod.core.feed.EventDistributor;
+import de.danoeh.antennapod.core.feed.Feed;
+import de.danoeh.antennapod.core.feed.FeedMedia;
+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.storage.DBReader;
+import de.danoeh.antennapod.core.storage.DBWriter;
+import de.danoeh.antennapod.core.util.playback.Playable;
+import de.danoeh.antennapod.core.util.playback.PlaybackController;
+import de.danoeh.antennapod.fragment.AddFeedFragment;
+import de.danoeh.antennapod.fragment.ChaptersFragment;
+import de.danoeh.antennapod.fragment.CoverFragment;
+import de.danoeh.antennapod.fragment.DownloadsFragment;
+import de.danoeh.antennapod.fragment.EpisodesFragment;
+import de.danoeh.antennapod.fragment.ItemDescriptionFragment;
+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 rx.Observable;
+import rx.Subscription;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.schedulers.Schedulers;
+
+/**
+ * Activity for playing files that do not require a video surface.
+ */
+public abstract class MediaplayerInfoActivity extends MediaplayerActivity implements NavDrawerActivity {
+
+ 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 = {
+ QueueFragment.TAG,
+ EpisodesFragment.TAG,
+ SubscriptionFragment.TAG,
+ DownloadsFragment.TAG,
+ PlaybackHistoryFragment.TAG,
+ AddFeedFragment.TAG,
+ NavListAdapter.SUBSCRIPTION_LIST_TAG
+ };
+
+ protected Button butPlaybackSpeed;
+ protected ImageButton butCastDisconnect;
+ private DrawerLayout drawerLayout;
+ private NavListAdapter navAdapter;
+ private ListView navList;
+ private View navDrawer;
+ private ActionBarDrawerToggle drawerToggle;
+ private int mPosition = -1;
+
+ private Playable media;
+ private ViewPager pager;
+ private MediaplayerInfoPagerAdapter pagerAdapter;
+
+ private Subscription subscription;
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ Log.d(TAG, "onStop()");
+ if(pagerAdapter != null) {
+ pagerAdapter.setController(null);
+ }
+ if(subscription != null) {
+ subscription.unsubscribe();
+ }
+ EventDistributor.getInstance().unregister(contentUpdate);
+ saveCurrentFragment();
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.d(TAG, "onDestroy()");
+ super.onDestroy();
+ // don't risk creating memory leaks
+ drawerLayout = null;
+ navAdapter = null;
+ navList = null;
+ navDrawer = null;
+ drawerToggle = null;
+ pager = null;
+ pagerAdapter = null;
+ }
+
+ @Override
+ protected void chooseTheme() {
+ setTheme(UserPreferences.getNoTitleTheme());
+ }
+
+ protected void saveCurrentFragment() {
+ if(pager == null) {
+ return;
+ }
+ Log.d(TAG, "Saving preferences");
+ SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
+ prefs.edit()
+ .putInt(PREF_KEY_SELECTED_FRAGMENT_POSITION, pager.getCurrentItem())
+ .commit();
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ if(drawerToggle != null) {
+ drawerToggle.onConfigurationChanged(newConfig);
+ }
+ }
+
+ private void loadLastFragment() {
+ Log.d(TAG, "Restoring instance state");
+ SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
+ int lastPosition = prefs.getInt(PREF_KEY_SELECTED_FRAGMENT_POSITION, -1);
+ pager.setCurrentItem(lastPosition);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if(pagerAdapter != null && controller != null && controller.getMedia() != media) {
+ media = controller.getMedia();
+ pagerAdapter.onMediaChanged(media);
+ pagerAdapter.setController(controller);
+ }
+
+ EventDistributor.getInstance().register(contentUpdate);
+ loadData();
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ setIntent(intent);
+ }
+
+ @Override
+ protected void onAwaitingVideoSurface() {
+ Log.d(TAG, "onAwaitingVideoSurface was called in audio player -> switching to video player");
+ startActivity(new Intent(this, VideoplayerActivity.class));
+ }
+
+ @Override
+ protected void postStatusMsg(int resId, boolean showToast) {
+ if (resId == R.string.player_preparing_msg
+ || resId == R.string.player_seeking_msg
+ || resId == R.string.player_buffering_msg) {
+ // TODO Show progress bar here
+ }
+ if (showToast) {
+ Toast.makeText(this, resId, Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ @Override
+ protected void clearStatusMsg() {
+ // TODO Hide progress bar here
+ }
+
+
+ @Override
+ protected void setupGUI() {
+ super.setupGUI();
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setTitle("");
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ findViewById(R.id.shadow).setVisibility(View.GONE);
+ AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appBar);
+ float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4, getResources().getDisplayMetrics());
+ appBarLayout.setElevation(px);
+ }
+ drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
+ navList = (ListView) findViewById(R.id.nav_list);
+ navDrawer = findViewById(R.id.nav_layout);
+
+ drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.drawer_open, R.string.drawer_close);
+ drawerToggle.setDrawerIndicatorEnabled(false);
+ drawerLayout.setDrawerListener(drawerToggle);
+
+ navAdapter = new NavListAdapter(itemAccess, this);
+ navList.setAdapter(navAdapter);
+ navList.setOnItemClickListener((parent, view, position, id) -> {
+ int viewType = parent.getAdapter().getItemViewType(position);
+ if (viewType != NavListAdapter.VIEW_TYPE_SECTION_DIVIDER) {
+ Intent intent = new Intent(MediaplayerInfoActivity.this, MainActivity.class);
+ intent.putExtra(MainActivity.EXTRA_NAV_TYPE, viewType);
+ intent.putExtra(MainActivity.EXTRA_NAV_INDEX, position);
+ startActivity(intent);
+ }
+ drawerLayout.closeDrawer(navDrawer);
+ });
+ navList.setOnItemLongClickListener((parent, view, position, id) -> {
+ if (position < navAdapter.getTags().size()) {
+ showDrawerPreferencesDialog();
+ return true;
+ } else {
+ mPosition = position;
+ return false;
+ }
+ });
+ registerForContextMenu(navList);
+ drawerToggle.syncState();
+
+ findViewById(R.id.nav_settings).setOnClickListener(v -> {
+ drawerLayout.closeDrawer(navDrawer);
+ startActivity(new Intent(MediaplayerInfoActivity.this, PreferenceController.getPreferenceActivity()));
+ });
+
+ butPlaybackSpeed = (Button) findViewById(R.id.butPlaybackSpeed);
+ butCastDisconnect = (ImageButton) findViewById(R.id.butCastDisconnect);
+
+ pager = (ViewPager) findViewById(R.id.pager);
+ pagerAdapter = new MediaplayerInfoPagerAdapter(getSupportFragmentManager(), media);
+ pagerAdapter.setController(controller);
+ pager.setAdapter(pagerAdapter);
+ CirclePageIndicator pageIndicator = (CirclePageIndicator) findViewById(R.id.page_indicator);
+ pageIndicator.setViewPager(pager);
+ loadLastFragment();
+ pager.onSaveInstanceState();
+ }
+
+ @Override
+ protected void onPositionObserverUpdate() {
+ super.onPositionObserverUpdate();
+ notifyMediaPositionChanged();
+ }
+
+ @Override
+ protected boolean loadMediaInfo() {
+ if (!super.loadMediaInfo()) {
+ return false;
+ }
+ if(controller.getMedia() != media) {
+ media = controller.getMedia();
+ pagerAdapter.onMediaChanged(media);
+ }
+ return true;
+ }
+
+ public void notifyMediaPositionChanged() {
+ if(pagerAdapter == null) {
+ return;
+ }
+ ChaptersFragment chaptersFragment = pagerAdapter.getChaptersFragment();
+ if(chaptersFragment != null) {
+ ChaptersListAdapter adapter = (ChaptersListAdapter) chaptersFragment.getListAdapter();
+ if (adapter != null) {
+ adapter.notifyDataSetChanged();
+ }
+ }
+ }
+
+ @Override
+ protected void onReloadNotification(int notificationCode) {
+ if (notificationCode == PlaybackService.EXTRA_CODE_VIDEO) {
+ Log.d(TAG, "ReloadNotification received, switching to Videoplayer now");
+ finish();
+ startActivity(new Intent(this, VideoplayerActivity.class));
+
+ }
+ }
+
+ @Override
+ protected void onBufferStart() {
+ postStatusMsg(R.string.player_buffering_msg, false);
+ }
+
+ @Override
+ protected void onBufferEnd() {
+ clearStatusMsg();
+ }
+
+ public PlaybackController getPlaybackController() {
+ return controller;
+ }
+
+ @Override
+ public boolean isDrawerOpen() {
+ return drawerLayout != null && navDrawer != null && drawerLayout.isDrawerOpen(navDrawer);
+ }
+
+ @Override
+ protected int getContentViewResourceId() {
+ return R.layout.mediaplayerinfo_activity;
+ }
+
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ return drawerToggle != null && drawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, v, menuInfo);
+ if(v.getId() != R.id.nav_list) {
+ return;
+ }
+ AdapterView.AdapterContextMenuInfo adapterInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
+ int position = adapterInfo.position;
+ if(position < navAdapter.getSubscriptionOffset()) {
+ return;
+ }
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.nav_feed_context, menu);
+ Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
+ menu.setHeaderTitle(feed.getTitle());
+ // episodes are not loaded, so we cannot check if the podcast has new or unplayed ones!
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+ final int position = mPosition;
+ mPosition = -1; // reset
+ if(position < 0) {
+ return false;
+ }
+ Feed feed = navDrawerData.feeds.get(position - navAdapter.getSubscriptionOffset());
+ switch(item.getItemId()) {
+ case R.id.mark_all_seen_item:
+ DBWriter.markFeedSeen(feed.getId());
+ return true;
+ case R.id.mark_all_read_item:
+ DBWriter.markFeedRead(feed.getId());
+ return true;
+ case R.id.remove_item:
+ final FeedRemover remover = new FeedRemover(this, feed) {
+ @Override
+ protected void onPostExecute(Void result) {
+ super.onPostExecute(result);
+ }
+ };
+ ConfirmationDialog conDialog = new ConfirmationDialog(this,
+ R.string.remove_feed_label,
+ R.string.feed_delete_confirmation_msg) {
+ @Override
+ public void onConfirmButtonPressed(
+ DialogInterface dialog) {
+ dialog.dismiss();
+ if (controller != null) {
+ Playable playable = controller.getMedia();
+ if (playable != null && playable instanceof FeedMedia) {
+ FeedMedia media = (FeedMedia) playable;
+ if (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));
+ }
+ }
+ }
+ }
+ remover.executeAsync();
+ }
+ };
+ conDialog.createNewDialog().show();
+ return true;
+ default:
+ return super.onContextItemSelected(item);
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ if(isDrawerOpen()) {
+ drawerLayout.closeDrawer(navDrawer);
+ } else if (pager == null || pager.getCurrentItem() == 0) {
+ // If the user is currently looking at the first step, allow the system to handle the
+ // Back button. This calls finish() on this activity and pops the back stack.
+ super.onBackPressed();
+ } else {
+ // Otherwise, select the previous step.
+ pager.setCurrentItem(pager.getCurrentItem() - 1);
+ }
+ }
+
+ public 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];
+ for (int i = 0; i < NAV_DRAWER_TAGS.length; i++) {
+ String tag = NAV_DRAWER_TAGS[i];
+ navLabels[i] = navAdapter.getLabel(tag);
+ if (!hiddenDrawerItems.contains(tag)) {
+ checked[i] = true;
+ }
+ }
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.drawer_preferences);
+ builder.setMultiChoiceItems(navLabels, checked, (dialog, which, isChecked) -> {
+ if (isChecked) {
+ hiddenDrawerItems.remove(NAV_DRAWER_TAGS[which]);
+ } else {
+ hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]);
+ }
+ });
+ builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
+ UserPreferences.setHiddenDrawerItems(hiddenDrawerItems);
+ });
+ builder.setNegativeButton(R.string.cancel_label, null);
+ builder.create().show();
+ }
+
+ private DBReader.NavDrawerData navDrawerData;
+
+ private void loadData() {
+ subscription = Observable.fromCallable(DBReader::getNavDrawerData)
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(result -> {
+ navDrawerData = result;
+ if (navAdapter != null) {
+ navAdapter.notifyDataSetChanged();
+ }
+ }, error -> {
+ Log.e(TAG, Log.getStackTraceString(error));
+ });
+ }
+
+
+
+ private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
+
+ @Override
+ public void update(EventDistributor eventDistributor, Integer arg) {
+ if ((EventDistributor.FEED_LIST_UPDATE & arg) != 0) {
+ Log.d(TAG, "Received contentUpdate Intent.");
+ loadData();
+ }
+ }
+ };
+
+ private final NavListAdapter.ItemAccess itemAccess = new NavListAdapter.ItemAccess() {
+ @Override
+ public int getCount() {
+ if (navDrawerData != null) {
+ return navDrawerData.feeds.size();
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public Feed getItem(int position) {
+ if (navDrawerData != null && 0 <= position && position < navDrawerData.feeds.size()) {
+ return navDrawerData.feeds.get(position);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public int getSelectedItemIndex() {
+ return -1;
+ }
+
+ @Override
+ public int getQueueSize() {
+ return (navDrawerData != null) ? navDrawerData.queueSize : 0;
+ }
+
+ @Override
+ public int getNumberOfNewItems() {
+ return (navDrawerData != null) ? navDrawerData.numNewItems : 0;
+ }
+
+ @Override
+ public int getNumberOfDownloadedItems() {
+ return (navDrawerData != null) ? navDrawerData.numDownloadedItems : 0;
+ }
+
+ @Override
+ public int getReclaimableItems() {
+ return (navDrawerData != null) ? navDrawerData.reclaimableSpace : 0;
+ }
+
+ @Override
+ public int getFeedCounter(long feedId) {
+ return navDrawerData != null ? navDrawerData.feedCounters.get(feedId) : 0;
+ }
+
+ @Override
+ public int getFeedCounterSum() {
+ if(navDrawerData == null) {
+ return 0;
+ }
+ int sum = 0;
+ for(int counter : navDrawerData.feedCounters.values()) {
+ sum += counter;
+ }
+ return sum;
+ }
+ };
+
+ public interface MediaplayerInfoContentFragment {
+ void onMediaChanged(Playable media);
+ }
+
+ private static class MediaplayerInfoPagerAdapter extends FragmentStatePagerAdapter {
+
+ private static final String TAG = "MPInfoPagerAdapter";
+
+ private Playable media;
+ private PlaybackController controller;
+
+ public MediaplayerInfoPagerAdapter(FragmentManager fm, Playable media) {
+ super(fm);
+ this.media = media;
+ }
+
+ private CoverFragment coverFragment;
+ private ItemDescriptionFragment itemDescriptionFragment;
+ private ChaptersFragment chaptersFragment;
+
+ public void onMediaChanged(Playable media) {
+ Log.d(TAG, "media changing to " + ((media != null) ? media.getEpisodeTitle() : "null"));
+ this.media = media;
+ if(coverFragment != null) {
+ coverFragment.onMediaChanged(media);
+ }
+ if(itemDescriptionFragment != null) {
+ itemDescriptionFragment.onMediaChanged(media);
+ }
+ if(chaptersFragment != null) {
+ chaptersFragment.onMediaChanged(media);
+ }
+ }
+
+ public void setController(PlaybackController controller) {
+ this.controller = controller;
+ if(chaptersFragment != null) {
+ chaptersFragment.setController(controller);
+ }
+ }
+
+ @Nullable
+ public ChaptersFragment getChaptersFragment() {
+ return chaptersFragment;
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ Log.d(TAG, "getItem(" + position + ")");
+ switch (position) {
+ case POS_COVER:
+ if(coverFragment == null) {
+ coverFragment = CoverFragment.newInstance(media);
+ }
+ return coverFragment;
+ case POS_DESCR:
+ if(itemDescriptionFragment == null) {
+ itemDescriptionFragment = ItemDescriptionFragment.newInstance(media, true, true);
+ }
+ return itemDescriptionFragment;
+ case POS_CHAPTERS:
+ if(chaptersFragment == null) {
+ chaptersFragment = ChaptersFragment.newInstance(media);
+ chaptersFragment.setController(controller);
+ }
+ return chaptersFragment;
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ public int getCount() {
+ return NUM_CONTENT_FRAGMENTS;
+ }
+ }
+}
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 c7426c006..a53f9bdb8 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java
@@ -7,8 +7,8 @@ import android.content.Intent;
import android.os.Bundle;
import android.os.Looper;
import android.support.v4.app.NavUtils;
-import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
@@ -79,7 +79,7 @@ import rx.schedulers.Schedulers;
* If the feed cannot be downloaded or parsed, an error dialog will be displayed
* and the activity will finish as soon as the error dialog is closed.
*/
-public class OnlineFeedViewActivity extends ActionBarActivity {
+public class OnlineFeedViewActivity extends AppCompatActivity {
private static final String TAG = "OnlineFeedViewActivity";
@@ -328,6 +328,7 @@ public class OnlineFeedViewActivity extends ActionBarActivity {
subscriber.onError(e);
}
} catch (Exception e) {
+ Log.e(TAG, Log.getStackTraceString(e));
subscriber.onError(e);
} finally {
boolean rc = new File(feed.getFile_url()).delete();
@@ -408,18 +409,25 @@ public class OnlineFeedViewActivity extends ActionBarActivity {
description.setText(feed.getDescription());
subscribeButton.setOnClickListener(v -> {
- try {
+ if(feed != null && 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
+ intent.putExtra(MainActivity.EXTRA_FEED_ID, getFeedId(feed));
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(intent);
+ } else {
Feed f = new Feed(selectedDownloadUrl, null, feed.getTitle());
f.setPreferences(feed.getPreferences());
this.feed = f;
-
- DownloadRequester.getInstance().downloadFeed(this, f);
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- DownloadRequestErrorDialogCreator.newRequestErrorDialog(OnlineFeedViewActivity.this,
- e.getMessage());
+ try {
+ DownloadRequester.getInstance().downloadFeed(this, f);
+ } catch (DownloadRequestException e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ DownloadRequestErrorDialogCreator.newRequestErrorDialog(this, e.getMessage());
+ }
+ setSubscribeButtonState(feed);
}
- setSubscribeButtonState(feed);
});
if (alternateFeedUrls.isEmpty()) {
@@ -462,8 +470,8 @@ public class OnlineFeedViewActivity extends ActionBarActivity {
subscribeButton.setEnabled(false);
subscribeButton.setText(R.string.downloading_label);
} else if (feedInFeedlist(feed)) {
- subscribeButton.setEnabled(false);
- subscribeButton.setText(R.string.subscribed_label);
+ subscribeButton.setEnabled(true);
+ subscribeButton.setText(R.string.open_podcast);
} else {
subscribeButton.setEnabled(true);
subscribeButton.setText(R.string.subscribe_label);
@@ -483,6 +491,18 @@ public class OnlineFeedViewActivity extends ActionBarActivity {
return false;
}
+ private long getFeedId(Feed feed) {
+ if (feeds == null || feed == null) {
+ return 0;
+ }
+ for (Feed f : feeds) {
+ if (f.getIdentifyingValue().equals(feed.getIdentifyingValue())) {
+ return f.getId();
+ }
+ }
+ return 0;
+ }
+
private void showErrorDialog(String errorMsg) {
assert(Looper.myLooper() == Looper.getMainLooper()); // run on UI thread
if (!isFinishing() && !isPaused) {
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java
index 8a9ec58d3..bc1a40b11 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java
@@ -2,28 +2,27 @@ package de.danoeh.antennapod.activity;
import android.content.Intent;
import android.os.Bundle;
-import android.support.v4.view.MenuItemCompat;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
import android.util.SparseBooleanArray;
import android.view.Menu;
+import android.view.MenuInflater;
import android.view.MenuItem;
-import android.view.View;
-import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
-import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.core.opml.OpmlElement;
-import de.danoeh.antennapod.core.preferences.UserPreferences;
import java.util.ArrayList;
import java.util.List;
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.opml.OpmlElement;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+
/**
* Displays the feeds that the OPML-Importer has read and lets the user choose
* which feeds he wants to import.
*/
-public class OpmlFeedChooserActivity extends ActionBarActivity {
+public class OpmlFeedChooserActivity extends AppCompatActivity {
private static final String TAG = "OpmlFeedChooserActivity";
public static final String EXTRA_SELECTED_ITEMS = "de.danoeh.antennapod.selectedItems";
@@ -33,6 +32,9 @@ public class OpmlFeedChooserActivity extends ActionBarActivity {
private ListView feedlist;
private ArrayAdapter<String> listAdapter;
+ private MenuItem selectAll;
+ private MenuItem deselectAll;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
setTheme(UserPreferences.getTheme());
@@ -44,45 +46,54 @@ public class OpmlFeedChooserActivity extends ActionBarActivity {
feedlist = (ListView) findViewById(R.id.feedlist);
feedlist.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
- listAdapter = new ArrayAdapter<String>(this,
+ listAdapter = new ArrayAdapter<>(this,
android.R.layout.simple_list_item_multiple_choice,
getTitleList());
feedlist.setAdapter(listAdapter);
-
- butCancel.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- setResult(RESULT_CANCELED);
- finish();
+ feedlist.setOnItemClickListener((parent, view, position, id) -> {
+ SparseBooleanArray checked = feedlist.getCheckedItemPositions();
+ int checkedCount = 0;
+ for (int i = 0; i < checked.size(); i++) {
+ if (checked.valueAt(i)) {
+ checkedCount++;
+ }
+ }
+ if(checkedCount == listAdapter.getCount()) {
+ selectAll.setVisible(false);
+ deselectAll.setVisible(true);
+ } else {
+ deselectAll.setVisible(false);
+ selectAll.setVisible(true);
}
});
- butConfirm.setOnClickListener(new OnClickListener() {
+ butCancel.setOnClickListener(v -> {
+ setResult(RESULT_CANCELED);
+ finish();
+ });
- @Override
- public void onClick(View v) {
- Intent intent = new Intent();
- SparseBooleanArray checked = feedlist.getCheckedItemPositions();
+ butConfirm.setOnClickListener(v -> {
+ Intent intent = new Intent();
+ SparseBooleanArray checked = feedlist.getCheckedItemPositions();
- int checkedCount = 0;
- // Get number of checked items
- for (int i = 0; i < checked.size(); i++) {
- if (checked.valueAt(i)) {
- checkedCount++;
- }
+ int checkedCount = 0;
+ // Get number of checked items
+ for (int i = 0; i < checked.size(); i++) {
+ if (checked.valueAt(i)) {
+ checkedCount++;
}
- int[] selection = new int[checkedCount];
- for (int i = 0, collected = 0; collected < checkedCount; i++) {
- if (checked.valueAt(i)) {
- selection[collected] = checked.keyAt(i);
- collected++;
- }
+ }
+ int[] selection = new int[checkedCount];
+ for (int i = 0, collected = 0; collected < checkedCount; i++) {
+ if (checked.valueAt(i)) {
+ selection[collected] = checked.keyAt(i);
+ collected++;
}
- intent.putExtra(EXTRA_SELECTED_ITEMS, selection);
- setResult(RESULT_OK, intent);
- finish();
}
+ intent.putExtra(EXTRA_SELECTED_ITEMS, selection);
+ setResult(RESULT_OK, intent);
+ finish();
});
}
@@ -93,7 +104,6 @@ public class OpmlFeedChooserActivity extends ActionBarActivity {
for (OpmlElement element : OpmlImportHolder.getReadElements()) {
result.add(element.getText());
}
-
}
return result;
}
@@ -101,13 +111,11 @@ public class OpmlFeedChooserActivity extends ActionBarActivity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
- MenuItemCompat.setShowAsAction(menu.add(Menu.NONE, R.id.select_all_item, Menu.NONE,
- R.string.select_all_label),
- MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
-
- MenuItemCompat.setShowAsAction(menu.add(Menu.NONE, R.id.deselect_all_item, Menu.NONE,
- R.string.deselect_all_label),
- MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.opml_selection_options, menu);
+ selectAll = menu.findItem(R.id.select_all_item);
+ deselectAll = menu.findItem(R.id.deselect_all_item);
+ deselectAll.setVisible(false);
return true;
}
@@ -115,10 +123,14 @@ public class OpmlFeedChooserActivity extends ActionBarActivity {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.select_all_item:
+ selectAll.setVisible(false);
selectAllItems(true);
+ deselectAll.setVisible(true);
return true;
case R.id.deselect_all_item:
+ deselectAll.setVisible(false);
selectAllItems(false);
+ selectAll.setVisible(true);
return true;
default:
return false;
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 46dabec12..8726af281 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java
@@ -4,8 +4,9 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Environment;
+import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import com.afollestad.materialdialogs.MaterialDialog;
@@ -25,13 +26,13 @@ import de.danoeh.antennapod.core.util.LangUtils;
/**
* Base activity for Opml Import - e.g. with code what to do afterwards
* */
-public class OpmlImportBaseActivity extends ActionBarActivity {
+public class OpmlImportBaseActivity extends AppCompatActivity {
private static final String TAG = "OpmlImportBaseActivity";
private OpmlImportWorker importWorker;
private static final int PERMISSION_REQUEST_READ_EXTERNAL_STORAGE = 5;
- private Uri uri;
+ @Nullable private Uri uri;
/**
* Handles the choices made by the user in the OpmlFeedChooserActivity and
@@ -67,7 +68,14 @@ public class OpmlImportBaseActivity extends ActionBarActivity {
}
}
- protected void importUri(Uri uri) {
+ protected void importUri(@Nullable Uri uri) {
+ if(uri == null) {
+ new MaterialDialog.Builder(this)
+ .content(R.string.opml_import_error_no_file)
+ .positiveText(android.R.string.ok)
+ .show();
+ return;
+ }
this.uri = uri;
if(uri.toString().contains(Environment.getExternalStorageDirectory().toString())) {
int permission = ActivityCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE);
@@ -127,8 +135,9 @@ public class OpmlImportBaseActivity extends ActionBarActivity {
importWorker.executeAsync();
} catch (Exception e) {
Log.d(TAG, Log.getStackTraceString(e));
+ String message = getString(R.string.opml_reader_error);
new MaterialDialog.Builder(this)
- .content("Cannot open OPML file: " + e.getMessage())
+ .content(message + " " + e.getMessage())
.positiveText(android.R.string.ok)
.show();
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java
index ab4b0d0ee..02e16a7b5 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromIntentActivity.java
@@ -18,6 +18,9 @@ public class OpmlImportFromIntentActivity extends OpmlImportBaseActivity {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Uri uri = getIntent().getData();
+ if(uri.toString().startsWith("/")) {
+ uri = Uri.parse("file://" + uri.toString());
+ }
importUri(uri);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java
index 15d97cc2c..b2dab7f68 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportFromPathActivity.java
@@ -53,7 +53,7 @@ public class OpmlImportFromPathActivity extends OpmlImportBaseActivity {
intentPickAction = new Intent(Intent.ACTION_PICK);
intentPickAction.setData(Uri.parse("file://"));
- if(false == IntentUtils.isCallable(getApplicationContext(), intentPickAction)) {
+ if(!IntentUtils.isCallable(getApplicationContext(), intentPickAction)) {
intentPickAction.setData(null);
if(false == IntentUtils.isCallable(getApplicationContext(), intentPickAction)) {
txtvHeaderExplanation1.setVisibility(View.GONE);
@@ -70,7 +70,7 @@ public class OpmlImportFromPathActivity extends OpmlImportBaseActivity {
intentGetContentAction = new Intent(Intent.ACTION_GET_CONTENT);
intentGetContentAction.addCategory(Intent.CATEGORY_OPENABLE);
intentGetContentAction.setType("*/*");
- if(false == IntentUtils.isCallable(getApplicationContext(), intentGetContentAction)) {
+ if(!IntentUtils.isCallable(getApplicationContext(), intentGetContentAction)) {
txtvHeaderExplanation2.setVisibility(View.GONE);
txtvExplanation2.setVisibility(View.GONE);
findViewById(R.id.divider2).setVisibility(View.GONE);
@@ -135,6 +135,9 @@ public class OpmlImportFromPathActivity extends OpmlImportBaseActivity {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && requestCode == CHOOSE_OPML_FILE) {
Uri uri = data.getData();
+ if(uri.toString().startsWith("/")) {
+ uri = Uri.parse("file://" + uri.toString());
+ }
importUri(uri);
}
}
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 80ccb7c99..ba22a42b4 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java
@@ -8,7 +8,7 @@ import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.support.v7.app.ActionBar;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewGroup;
@@ -24,7 +24,7 @@ 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 ActionBarActivity {
+public class PreferenceActivity extends AppCompatActivity {
private PreferenceController preferenceController;
private MainFragment prefFragment;
@@ -49,7 +49,7 @@ public class PreferenceActivity extends ActionBarActivity {
protected void onCreate(Bundle savedInstanceState) {
// This must be the FIRST thing we do, otherwise other code may not have the
// reference it needs
- instance = new WeakReference<PreferenceActivity>(this);
+ instance = new WeakReference<>(this);
setTheme(UserPreferences.getTheme());
super.onCreate(savedInstanceState);
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java
new file mode 100644
index 000000000..0254617e4
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/activity/StatisticsActivity.java
@@ -0,0 +1,107 @@
+package de.danoeh.antennapod.activity;
+
+import android.os.Bundle;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
+import android.util.Log;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.adapter.StatisticsListAdapter;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.core.util.Converter;
+import rx.Observable;
+import rx.Subscription;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.schedulers.Schedulers;
+
+/**
+ * Displays the 'statistics' screen
+ */
+public class StatisticsActivity extends AppCompatActivity
+ implements AdapterView.OnItemClickListener {
+
+ private static final String TAG = StatisticsActivity.class.getSimpleName();
+
+ private Subscription subscription;
+ private TextView totalTimeTextView;
+ private ListView feedStatisticsList;
+ private ProgressBar progressBar;
+ private StatisticsListAdapter listAdapter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ setTheme(UserPreferences.getTheme());
+ super.onCreate(savedInstanceState);
+ getSupportActionBar().setDisplayShowHomeEnabled(true);
+ setContentView(R.layout.statistics_activity);
+
+ totalTimeTextView = (TextView) findViewById(R.id.total_time);
+ feedStatisticsList = (ListView) findViewById(R.id.statistics_list);
+ progressBar = (ProgressBar) findViewById(R.id.progressBar);
+ listAdapter = new StatisticsListAdapter(this);
+ feedStatisticsList.setAdapter(listAdapter);
+ feedStatisticsList.setOnItemClickListener(this);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ progressBar.setVisibility(View.VISIBLE);
+ totalTimeTextView.setVisibility(View.GONE);
+ feedStatisticsList.setVisibility(View.GONE);
+ loadStats();
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ finish();
+ return true;
+ } else {
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ private void loadStats() {
+ if(subscription != null) {
+ subscription.unsubscribe();
+ }
+ subscription = Observable.fromCallable(() -> DBReader.getStatistics())
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(result -> {
+ if (result != null) {
+ totalTimeTextView.setText(Converter
+ .shortLocalizedDuration(this, result.totalTime));
+ listAdapter.update(result.feedTime);
+ progressBar.setVisibility(View.GONE);
+ totalTimeTextView.setVisibility(View.VISIBLE);
+ feedStatisticsList.setVisibility(View.VISIBLE);
+ }
+ }, error -> {
+ Log.e(TAG, Log.getStackTraceString(error));
+ });
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ DBReader.StatisticsItem stats = listAdapter.getItem(position);
+
+ AlertDialog.Builder dialog = new AlertDialog.Builder(this);
+ dialog.setTitle(stats.feed.getTitle());
+ dialog.setMessage(getString(R.string.statistics_details_dialog,
+ stats.episodesStarted,
+ stats.episodes,
+ Converter.shortLocalizedDuration(this, stats.timePlayed),
+ Converter.shortLocalizedDuration(this, stats.time)));
+ dialog.setPositiveButton(android.R.string.ok, null);
+ dialog.show();
+ }
+}
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 e980764ec..f22507f4c 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/StorageErrorActivity.java
@@ -132,7 +132,8 @@ public class StorageErrorActivity extends AppCompatActivity {
List<String> folders = new ArrayList<>(mediaDirs.length);
List<CharSequence> choices = new ArrayList<>(mediaDirs.length);
for(int i=0; i < mediaDirs.length; i++) {
- if(mediaDirs[i] == null) {
+ File dir = mediaDirs[i];
+ if(dir == null || !dir.exists() || !dir.canRead() || !dir.canWrite()) {
continue;
}
String path = mediaDirs[i].getAbsolutePath();
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 ee459dbc6..a4ffebae2 100644
--- a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java
@@ -41,6 +41,7 @@ public class VideoplayerActivity extends MediaplayerActivity {
*/
private boolean videoControlsShowing = true;
private boolean videoSurfaceCreated = false;
+ private boolean destroyingDueToReload = false;
private VideoControlsHider videoControlsHider = new VideoControlsHider(this);
@@ -83,23 +84,30 @@ public class VideoplayerActivity extends MediaplayerActivity {
launchIntent.putExtra(PlaybackService.EXTRA_PREPARE_IMMEDIATELY,
true);
startService(launchIntent);
+ } else if (PlaybackService.isCasting()) {
+ Intent intent = PlaybackService.getPlayerActivityIntent(this);
+ if (!intent.getComponent().getClassName().equals(VideoplayerActivity.class.getName())) {
+ destroyingDueToReload = true;
+ finish();
+ startActivity(intent);
+ }
}
}
@Override
protected void onPause() {
- super.onPause();
videoControlsHider.stop();
if (controller != null && controller.getStatus() == PlayerStatus.PLAYING) {
controller.pause();
}
+ super.onPause();
}
@Override
protected void onDestroy() {
- super.onDestroy();
videoControlsHider.stop();
videoControlsHider = null;
+ super.onDestroy();
}
@Override
@@ -159,7 +167,7 @@ public class VideoplayerActivity extends MediaplayerActivity {
}
@Override
- protected void postStatusMsg(int resId) {
+ protected void postStatusMsg(int resId, boolean showToast) {
if (resId == R.string.player_preparing_msg) {
progressIndicator.setVisibility(View.VISIBLE);
} else {
@@ -202,6 +210,24 @@ public class VideoplayerActivity extends MediaplayerActivity {
videoControlsShowing = !videoControlsShowing;
}
+ @Override
+ protected void onRewind() {
+ super.onRewind();
+ setupVideoControlsToggler();
+ }
+
+ @Override
+ protected void onPlayPause() {
+ super.onPlayPause();
+ setupVideoControlsToggler();
+ }
+
+ @Override
+ protected void onFastForward() {
+ super.onFastForward();
+ setupVideoControlsToggler();
+ }
+
private final SurfaceHolder.Callback surfaceHolderCallback = new SurfaceHolder.Callback() {
@Override
@@ -218,7 +244,7 @@ public class VideoplayerActivity extends MediaplayerActivity {
if (controller.serviceAvailable()) {
controller.setVideoSurface(holder);
} else {
- Log.e(TAG, "Could'nt attach surface to mediaplayer - reference to service was null");
+ Log.e(TAG, "Couldn't attach surface to mediaplayer - reference to service was null");
}
}
@@ -228,7 +254,9 @@ public class VideoplayerActivity extends MediaplayerActivity {
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "Videosurface was destroyed");
videoSurfaceCreated = false;
- controller.notifyVideoSurfaceAbandoned();
+ if (!destroyingDueToReload) {
+ controller.notifyVideoSurfaceAbandoned();
+ }
}
};
@@ -237,8 +265,14 @@ public class VideoplayerActivity extends MediaplayerActivity {
protected void onReloadNotification(int notificationCode) {
if (notificationCode == PlaybackService.EXTRA_CODE_AUDIO) {
Log.d(TAG, "ReloadNotification received, switching to Audioplayer now");
+ destroyingDueToReload = true;
finish();
startActivity(new Intent(this, AudioplayerActivity.class));
+ } else if (notificationCode == PlaybackService.EXTRA_CODE_CAST) {
+ Log.d(TAG, "ReloadNotification received, switching to Castplayer now");
+ destroyingDueToReload = true;
+ finish();
+ startActivity(new Intent(this, CastplayerActivity.class));
}
}
@@ -312,7 +346,7 @@ public class VideoplayerActivity extends MediaplayerActivity {
private static class VideoControlsHider extends Handler {
- private static final int DELAY = 5000;
+ private static final int DELAY = 2500;
private WeakReference<VideoplayerActivity> activity;
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 28c2b7206..d46a3d6c2 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
@@ -4,8 +4,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.Bundle;
-import android.support.v4.app.NavUtils;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.LayoutInflater;
@@ -20,7 +20,6 @@ import android.widget.Spinner;
import android.widget.TextView;
import android.widget.ViewFlipper;
-import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
@@ -42,7 +41,7 @@ import de.danoeh.antennapod.core.service.GpodnetSyncService;
* Step 3: Choose from a list of actions
*/
public class GpodnetAuthenticationActivity extends ActionBarActivity {
- private static final String TAG = "GpodnetAuthenticationActivity";
+ private static final String TAG = "GpodnetAuthActivity";
private static final String CURRENT_STEP = "current_step";
@@ -122,7 +121,7 @@ public class GpodnetAuthenticationActivity extends ActionBarActivity {
final String passwordStr = password.getText().toString();
if (BuildConfig.DEBUG) Log.d(TAG, "Checking login credentials");
- new AsyncTask<GpodnetService, Void, Void>() {
+ AsyncTask<GpodnetService, Void, Void> authTask = new AsyncTask<GpodnetService, Void, Void>() {
volatile Exception exception;
@@ -144,7 +143,7 @@ public class GpodnetAuthenticationActivity extends ActionBarActivity {
if (exception == null) {
advance();
} else {
- txtvError.setText(exception.getMessage());
+ txtvError.setText(exception.getCause().getMessage());
txtvError.setVisibility(View.VISIBLE);
}
}
@@ -161,7 +160,12 @@ public class GpodnetAuthenticationActivity extends ActionBarActivity {
}
return null;
}
- }.execute(service);
+ };
+ if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) {
+ authTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, service);
+ } else {
+ authTask.execute();
+ }
}
});
}
@@ -177,7 +181,7 @@ public class GpodnetAuthenticationActivity extends ActionBarActivity {
// load device list
- final AtomicReference<List<GpodnetDevice>> devices = new AtomicReference<List<GpodnetDevice>>();
+ final AtomicReference<List<GpodnetDevice>> devices = new AtomicReference<>();
new AsyncTask<GpodnetService, Void, List<GpodnetDevice>>() {
private volatile Exception exception;
@@ -194,17 +198,18 @@ public class GpodnetAuthenticationActivity extends ActionBarActivity {
protected void onPostExecute(List<GpodnetDevice> gpodnetDevices) {
super.onPostExecute(gpodnetDevices);
if (gpodnetDevices != null) {
- List<String> deviceNames = new ArrayList<String>();
+ List<String> deviceNames = new ArrayList<>();
for (GpodnetDevice device : gpodnetDevices) {
deviceNames.add(device.getCaption());
}
- spinnerDevices.setAdapter(new ArrayAdapter<String>(GpodnetAuthenticationActivity.this,
+ spinnerDevices.setAdapter(new ArrayAdapter<>(GpodnetAuthenticationActivity.this,
android.R.layout.simple_spinner_dropdown_item, deviceNames));
spinnerDevices.setEnabled(true);
if (!deviceNames.isEmpty()) {
chooseDevice.setEnabled(true);
}
devices.set(gpodnetDevices);
+ deviceID.setText(generateDeviceID(gpodnetDevices));
createNewDevice.setEnabled(true);
}
}
@@ -225,7 +230,7 @@ public class GpodnetAuthenticationActivity extends ActionBarActivity {
createNewDevice.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- if (checkDeviceIDText(deviceID, txtvError, devices.get())) {
+ if (checkDeviceIDText(deviceID, caption, txtvError, devices.get())) {
final String deviceStr = deviceID.getText().toString();
final String captionStr = caption.getText().toString();
@@ -273,45 +278,60 @@ public class GpodnetAuthenticationActivity extends ActionBarActivity {
}
});
- deviceID.setText(generateDeviceID());
- chooseDevice.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- final int position = spinnerDevices.getSelectedItemPosition();
- if (position != AdapterView.INVALID_POSITION) {
- selectedDevice = devices.get().get(position);
- advance();
- }
+ chooseDevice.setOnClickListener(v -> {
+ final int position = spinnerDevices.getSelectedItemPosition();
+ if (position != AdapterView.INVALID_POSITION) {
+ selectedDevice = devices.get().get(position);
+ advance();
}
});
}
- private String generateDeviceID() {
- final int DEVICE_ID_LENGTH = 10;
- StringBuilder buffer = new StringBuilder(DEVICE_ID_LENGTH);
- SecureRandom random = new SecureRandom();
- for (int i = 0; i < DEVICE_ID_LENGTH; i++) {
- buffer.append(random.nextInt(10));
+ private String generateDeviceID(List<GpodnetDevice> gpodnetDevices) {
+ // devices names must be of a certain form:
+ // https://gpoddernet.readthedocs.org/en/latest/api/reference/general.html#devices
+ // This is more restrictive than needed, but I think it makes for more readable names.
+ String baseId = Build.MODEL.replaceAll("\\W", "");
+ String id = baseId;
+ int num = 0;
+
+ while (isDeviceWithIdInList(id, gpodnetDevices)) {
+ id = baseId + "_" + num;
+ num++;
+ }
+
+ return id;
+ }
+ private boolean isDeviceWithIdInList(String id, List<GpodnetDevice> gpodnetDevices) {
+ if (gpodnetDevices == null) {
+ return false;
+ }
+ for (GpodnetDevice device : gpodnetDevices) {
+ if (device.getId().equals(id)) {
+ return true;
+ }
}
- return buffer.toString();
+ return false;
}
- private boolean checkDeviceIDText(EditText deviceID, TextView txtvError, List<GpodnetDevice> devices) {
+ private boolean checkDeviceIDText(EditText deviceID, EditText caption, TextView txtvError, List<GpodnetDevice> devices) {
String text = deviceID.getText().toString();
if (text.length() == 0) {
txtvError.setText(R.string.gpodnetauth_device_errorEmpty);
txtvError.setVisibility(View.VISIBLE);
return false;
+ } else if (caption.length() == 0) {
+ txtvError.setText(R.string.gpodnetauth_device_caption_errorEmpty);
+ txtvError.setVisibility(View.VISIBLE);
+ return false;
} else {
if (devices != null) {
- for (GpodnetDevice device : devices) {
- if (device.getId().equals(text)) {
- txtvError.setText(R.string.gpodnetauth_device_errorAlreadyUsed);
- txtvError.setVisibility(View.VISIBLE);
- return false;
- }
+ if (isDeviceWithIdInList(text, devices)) {
+ txtvError.setText(R.string.gpodnetauth_device_errorAlreadyUsed);
+ txtvError.setVisibility(View.VISIBLE);
+ return false;
}
txtvError.setVisibility(View.GONE);
return true;
@@ -325,20 +345,14 @@ public class GpodnetAuthenticationActivity extends ActionBarActivity {
final Button sync = (Button) view.findViewById(R.id.butSyncNow);
final Button back = (Button) view.findViewById(R.id.butGoMainscreen);
- sync.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- GpodnetSyncService.sendSyncIntent(GpodnetAuthenticationActivity.this);
- finish();
- }
+ sync.setOnClickListener(v -> {
+ GpodnetSyncService.sendSyncIntent(GpodnetAuthenticationActivity.this);
+ finish();
});
- back.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(GpodnetAuthenticationActivity.this, MainActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- }
+ back.setOnClickListener(v -> {
+ Intent intent = new Intent(GpodnetAuthenticationActivity.this, MainActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(intent);
});
}
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 a75789815..66e6f9a00 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonCallback.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonCallback.java
@@ -4,5 +4,5 @@ import de.danoeh.antennapod.core.feed.FeedItem;
public interface ActionButtonCallback {
/** Is called when the action button of a list item has been pressed. */
- abstract void onActionButtonPressed(FeedItem item);
+ void onActionButtonPressed(FeedItem item);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java b/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java
index 935a0dcd4..8aaf0055a 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java
@@ -50,7 +50,7 @@ public class AdapterUtils {
Log.d(TAG, "size: " + media.getSize());
if (media.getSize() > 0) {
txtvPos.setText(Converter.byteToString(media.getSize()));
- } else if(NetworkUtils.isDownloadAllowed() && false == media.checkedOnSizeButUnknown()) {
+ } else if(NetworkUtils.isDownloadAllowed() && !media.checkedOnSizeButUnknown()) {
txtvPos.setText("{fa-spinner}");
Iconify.addIcons(txtvPos);
NetworkUtils.getFeedMediaSizeObservable(media)
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 07f895468..43a00f7c5 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/AllEpisodesRecycleAdapter.java
@@ -1,10 +1,10 @@
package de.danoeh.antennapod.adapter;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
+import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
+import android.text.Layout;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
@@ -15,13 +15,11 @@ import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.bumptech.glide.Glide;
-import com.bumptech.glide.load.resource.drawable.GlideDrawable;
-import com.bumptech.glide.request.animation.GlideAnimation;
-import com.bumptech.glide.request.target.GlideDrawableImageViewTarget;
import com.joanzapata.iconify.Iconify;
import com.nineoldandroids.view.ViewHelper;
@@ -84,8 +82,12 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
.inflate(R.layout.new_episodes_listitem, parent, false);
Holder holder = new Holder(view);
holder.container = (FrameLayout) view.findViewById(R.id.container);
+ holder.content = (LinearLayout) view.findViewById(R.id.content);
holder.placeholder = (TextView) view.findViewById(R.id.txtvPlaceholder);
holder.title = (TextView) view.findViewById(R.id.txtvTitle);
+ if(Build.VERSION.SDK_INT >= 23) {
+ holder.title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
+ }
holder.pubDate = (TextView) view
.findViewById(R.id.txtvPublished);
holder.statusUnread = view.findViewById(R.id.statusUnread);
@@ -121,11 +123,16 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
holder.title.setText(item.getTitle());
String pubDateStr = DateUtils.formatAbbrev(mainActivityRef.get(), item.getPubDate());
holder.pubDate.setText(pubDateStr);
- if (showOnlyNewEpisodes || false == item.isNew()) {
+ if (showOnlyNewEpisodes || !item.isNew()) {
holder.statusUnread.setVisibility(View.INVISIBLE);
} else {
holder.statusUnread.setVisibility(View.VISIBLE);
}
+ if(item.isPlayed()) {
+ ViewHelper.setAlpha(holder.content, 0.5f);
+ } else {
+ ViewHelper.setAlpha(holder.content, 1.0f);
+ }
FeedMedia media = item.getMedia();
if (media != null) {
@@ -135,7 +142,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
holder.txtvDuration.setText(Converter.getDurationStringLong(media.getDuration()));
} else if (media.getSize() > 0) {
holder.txtvDuration.setText(Converter.byteToString(media.getSize()));
- } else if(NetworkUtils.isDownloadAllowed() && false == media.checkedOnSizeButUnknown()) {
+ } else if(NetworkUtils.isDownloadAllowed() && !media.checkedOnSizeButUnknown()) {
holder.txtvDuration.setText("{fa-spinner}");
Iconify.addIcons(holder.txtvDuration);
NetworkUtils.getFeedMediaSizeObservable(media)
@@ -197,7 +204,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
.fitCenter()
.dontAnimate()
- .into(new CoverTarget(item.getFeed().getImageUri(), holder.placeholder, holder.cover));
+ .into(new CoverTarget(item.getFeed().getImageUri(), holder.placeholder, holder.cover, mainActivityRef.get()));
}
@Override
@@ -221,44 +228,6 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
return pos;
}
- private class CoverTarget extends GlideDrawableImageViewTarget {
-
- private final WeakReference<Uri> fallback;
- private final WeakReference<TextView> placeholder;
- private final WeakReference<ImageView> cover;
-
- public CoverTarget(Uri fallbackUri, TextView txtvPlaceholder, ImageView imgvCover) {
- super(imgvCover);
- fallback = new WeakReference<>(fallbackUri);
- placeholder = new WeakReference<>(txtvPlaceholder);
- cover = new WeakReference<>(imgvCover);
- }
-
- @Override
- public void onLoadFailed(Exception e, Drawable errorDrawable) {
- Uri fallbackUri = fallback.get();
- TextView txtvPlaceholder = placeholder.get();
- ImageView imgvCover = cover.get();
- if(fallbackUri != null && txtvPlaceholder != null && imgvCover != null) {
- Glide.with(mainActivityRef.get())
- .load(fallbackUri)
- .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
- .fitCenter()
- .dontAnimate()
- .into(new CoverTarget(null, txtvPlaceholder, imgvCover));
- }
- }
-
- @Override
- public void onResourceReady(GlideDrawable drawable, GlideAnimation anim) {
- super.onResourceReady(drawable, anim);
- TextView txtvPlaceholder = placeholder.get();
- if(txtvPlaceholder != null) {
- txtvPlaceholder.setVisibility(View.INVISIBLE);
- }
- }
- }
-
private View.OnClickListener secondaryActionListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -271,6 +240,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
implements View.OnClickListener,
View.OnCreateContextMenuListener,
ItemTouchHelperViewHolder {
+ LinearLayout content;
FrameLayout container;
TextView placeholder;
TextView title;
@@ -295,7 +265,8 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
public void onClick(View v) {
MainActivity mainActivity = mainActivityRef.get();
if (mainActivity != null) {
- mainActivity.loadChildFragment(ItemFragment.newInstance(item.getId()));
+ long[] ids = itemAccess.getItemsIds().toArray();
+ mainActivity.loadChildFragment(ItemFragment.newInstance(ids, position));
}
}
@@ -331,8 +302,7 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
item1.setVisible(visible);
}
};
- FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, true,
- itemAccess.getQueueIds(), itemAccess.getFavoritesIds());
+ FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, true, null);
}
}
@@ -343,14 +313,12 @@ public class AllEpisodesRecycleAdapter extends RecyclerView.Adapter<AllEpisodesR
FeedItem getItem(int position);
+ LongList getItemsIds();
+
int getItemDownloadProgressPercent(FeedItem item);
boolean isInQueue(FeedItem item);
- LongList getQueueIds();
-
- LongList getFavoritesIds();
-
}
/**
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 8bde1097b..37e00ab74 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/ChaptersListAdapter.java
@@ -109,7 +109,7 @@ public class ChaptersListAdapter extends ArrayAdapter<Chapter> {
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(widget);
- } else if (action == MotionEvent.ACTION_DOWN) {
+ } else if (action == MotionEvent.ACTION_DOWN){
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java b/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java
new file mode 100644
index 000000000..ed0c08086
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/CoverTarget.java
@@ -0,0 +1,58 @@
+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;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.load.resource.drawable.GlideDrawable;
+import com.bumptech.glide.request.animation.GlideAnimation;
+import com.bumptech.glide.request.target.GlideDrawableImageViewTarget;
+
+import java.lang.ref.WeakReference;
+
+import de.danoeh.antennapod.activity.MainActivity;
+import de.danoeh.antennapod.core.glide.ApGlideSettings;
+
+class CoverTarget extends GlideDrawableImageViewTarget {
+
+ private final WeakReference<Uri> fallback;
+ private final WeakReference<TextView> placeholder;
+ private final WeakReference<ImageView> cover;
+ private final WeakReference<MainActivity> mainActivity;
+
+ public CoverTarget(Uri fallbackUri, TextView txtvPlaceholder, ImageView imgvCover, MainActivity activity) {
+ super(imgvCover);
+ fallback = new WeakReference<>(fallbackUri);
+ placeholder = new WeakReference<>(txtvPlaceholder);
+ cover = new WeakReference<>(imgvCover);
+ mainActivity = new WeakReference<>(activity);
+ }
+
+ @Override
+ public void onLoadFailed(Exception e, Drawable errorDrawable) {
+ Uri fallbackUri = fallback.get();
+ TextView txtvPlaceholder = placeholder.get();
+ ImageView imgvCover = cover.get();
+ if (fallbackUri != null && txtvPlaceholder != null && imgvCover != null) {
+ MainActivity activity = mainActivity.get();
+ Glide.with(activity)
+ .load(fallbackUri)
+ .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
+ .fitCenter()
+ .dontAnimate()
+ .into(new CoverTarget(null, txtvPlaceholder, imgvCover, activity));
+ }
+ }
+
+ @Override
+ public void onResourceReady(GlideDrawable drawable, GlideAnimation anim) {
+ super.onResourceReady(drawable, anim);
+ TextView txtvPlaceholder = placeholder.get();
+ if (txtvPlaceholder != null) {
+ txtvPlaceholder.setVisibility(View.INVISIBLE);
+ }
+ }
+}
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 469a807e1..00ab96f6c 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DefaultActionButtonCallback.java
@@ -1,9 +1,7 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
-import android.support.v7.app.AlertDialog;
import android.widget.Toast;
import com.afollestad.materialdialogs.MaterialDialog;
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 9ff80424c..e271b5eed 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadLogAdapter.java
@@ -1,7 +1,9 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
+import android.os.Build;
import android.support.v4.content.ContextCompat;
+import android.text.Layout;
import android.text.format.DateUtils;
import android.util.Log;
import android.view.LayoutInflater;
@@ -11,8 +13,8 @@ import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Toast;
-import com.joanzapata.iconify.Iconify;
import com.joanzapata.iconify.widget.IconButton;
+import com.joanzapata.iconify.widget.IconTextView;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
@@ -48,13 +50,15 @@ public class DownloadLogAdapter extends BaseAdapter {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.downloadlog_item, parent, false);
- holder.icon = (TextView) convertView.findViewById(R.id.txtvIcon);
+ holder.icon = (IconTextView) convertView.findViewById(R.id.txtvIcon);
holder.retry = (IconButton) convertView.findViewById(R.id.btnRetry);
holder.date = (TextView) convertView.findViewById(R.id.txtvDate);
holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
+ if(Build.VERSION.SDK_INT >= 23) {
+ holder.title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
+ }
holder.type = (TextView) convertView.findViewById(R.id.txtvType);
- holder.reason = (TextView) convertView
- .findViewById(R.id.txtvReason);
+ holder.reason = (TextView) convertView.findViewById(R.id.txtvReason);
convertView.setTag(holder);
} else {
holder = (Holder) convertView.getTag();
@@ -78,14 +82,12 @@ public class DownloadLogAdapter extends BaseAdapter {
holder.icon.setTextColor(ContextCompat.getColor(convertView.getContext(),
R.color.download_success_green));
holder.icon.setText("{fa-check-circle}");
- Iconify.addIcons(holder.icon);
holder.retry.setVisibility(View.GONE);
holder.reason.setVisibility(View.GONE);
} else {
holder.icon.setTextColor(ContextCompat.getColor(convertView.getContext(),
R.color.download_failed_red));
holder.icon.setText("{fa-times-circle}");
- Iconify.addIcons(holder.icon);
String reasonText = status.getReason().getErrorString(context);
if (status.getReasonDetailed() != null) {
reasonText += ": " + status.getReasonDetailed();
@@ -160,7 +162,7 @@ public class DownloadLogAdapter extends BaseAdapter {
}
static class Holder {
- TextView icon;
+ IconTextView icon;
IconButton retry;
TextView title;
TextView type;
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 53dedd496..6d0beff9e 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadedEpisodesListAdapter.java
@@ -1,6 +1,8 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
+import android.os.Build;
+import android.text.Layout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -60,6 +62,9 @@ public class DownloadedEpisodesListAdapter extends BaseAdapter {
parent, false);
holder.imageView = (ImageView) convertView.findViewById(R.id.imgvImage);
holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
+ if(Build.VERSION.SDK_INT >= 23) {
+ holder.title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
+ }
holder.txtvSize = (TextView) convertView.findViewById(R.id.txtvSize);
holder.queueStatus = (ImageView) convertView.findViewById(R.id.imgvInPlaylist);
holder.pubDate = (TextView) convertView
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 4a0ff1f12..e1efdaa7b 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadlistAdapter.java
@@ -131,11 +131,11 @@ public class DownloadlistAdapter extends BaseAdapter {
}
public interface ItemAccess {
- public int getCount();
+ int getCount();
- public Downloader getItem(int position);
+ Downloader getItem(int position);
- public void onSecondaryActionClick(Downloader downloader);
+ void onSecondaryActionClick(Downloader downloader);
}
}
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 7ca8d6a31..4e9c5d71b 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java
@@ -2,7 +2,9 @@ package de.danoeh.antennapod.adapter;
import android.content.Context;
import android.content.res.TypedArray;
+import android.os.Build;
import android.support.v4.content.ContextCompat;
+import android.text.Layout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -95,8 +97,10 @@ public class FeedItemlistAdapter extends BaseAdapter {
convertView = inflater.inflate(R.layout.feeditemlist_item, parent, false);
holder.container = (LinearLayout) convertView
.findViewById(R.id.container);
- holder.title = (TextView) convertView
- .findViewById(R.id.txtvItemname);
+ holder.title = (TextView) convertView.findViewById(R.id.txtvItemname);
+ if(Build.VERSION.SDK_INT >= 23) {
+ holder.title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
+ }
holder.lenSize = (TextView) convertView
.findViewById(R.id.txtvLenSize);
holder.butAction = (ImageButton) convertView
@@ -147,6 +151,8 @@ public class FeedItemlistAdapter extends BaseAdapter {
String pubDateStr = DateUtils.formatAbbrev(context, item.getPubDate());
holder.published.setText(pubDateStr);
+ boolean isInQueue = item.isTagged(FeedItem.TAG_QUEUE);
+
FeedMedia media = item.getMedia();
if (media == null) {
holder.episodeProgress.setVisibility(View.GONE);
@@ -157,7 +163,7 @@ public class FeedItemlistAdapter extends BaseAdapter {
AdapterUtils.updateEpisodePlaybackProgress(item, holder.lenSize, holder.episodeProgress);
- if (itemAccess.isInQueue(item)) {
+ if (isInQueue) {
holder.inPlaylist.setVisibility(View.VISIBLE);
} else {
holder.inPlaylist.setVisibility(View.INVISIBLE);
@@ -189,17 +195,15 @@ public class FeedItemlistAdapter extends BaseAdapter {
holder.type.setImageBitmap(null);
holder.type.setVisibility(View.GONE);
}
+ typeDrawables.recycle();
if(media.isCurrentlyPlaying()) {
- if(media.isCurrentlyPlaying()) {
- holder.container.setBackgroundColor(playingBackGroundColor);
- } else {
- holder.container.setBackgroundColor(normalBackGroundColor);
- }
+ holder.container.setBackgroundColor(playingBackGroundColor);
+ } else {
+ holder.container.setBackgroundColor(normalBackGroundColor);
}
}
- boolean isInQueue = itemAccess.isInQueue(item);
actionButtonUtils.configureActionButton(holder.butAction, item, isInQueue);
holder.butAction.setFocusable(false);
holder.butAction.setTag(item);
@@ -233,8 +237,6 @@ public class FeedItemlistAdapter extends BaseAdapter {
public interface ItemAccess {
- boolean isInQueue(FeedItem item);
-
int getItemDownloadProgressPercent(FeedItem item);
int getCount();
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 6d7e6dcac..75c858ec6 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/NavListAdapter.java
@@ -38,6 +38,7 @@ import de.danoeh.antennapod.fragment.EpisodesFragment;
import de.danoeh.antennapod.fragment.NewEpisodesFragment;
import de.danoeh.antennapod.fragment.PlaybackHistoryFragment;
import de.danoeh.antennapod.fragment.QueueFragment;
+import de.danoeh.antennapod.fragment.SubscriptionFragment;
/**
* BaseAdapter for the navigation drawer
@@ -49,11 +50,18 @@ public class NavListAdapter extends BaseAdapter
public static final int VIEW_TYPE_SECTION_DIVIDER = 1;
public static final int VIEW_TYPE_SUBSCRIPTION = 2;
+ /**
+ * a tag used as a placeholder to indicate if the subscription list should be displayed or not
+ * This tag doesn't correspond to any specific activity.
+ */
+ public static final String SUBSCRIPTION_LIST_TAG = "SubscriptionList";
+
private static List<String> tags;
private static String[] titles;
private ItemAccess itemAccess;
private Context context;
+ private boolean showSubscriptionList = true;
public NavListAdapter(ItemAccess itemAccess, Context context) {
this.itemAccess = itemAccess;
@@ -73,11 +81,23 @@ public class NavListAdapter extends BaseAdapter
}
private void loadItems() {
- List<String> newTags = new ArrayList<String>(Arrays.asList(MainActivity.NAV_DRAWER_TAGS));
+ List<String> newTags = new ArrayList<>(Arrays.asList(MainActivity.NAV_DRAWER_TAGS));
List<String> hiddenFragments = UserPreferences.getHiddenDrawerItems();
for(String hidden : hiddenFragments) {
newTags.remove(hidden);
}
+
+ if (newTags.contains(SUBSCRIPTION_LIST_TAG)) {
+ // we never want SUBSCRIPTION_LIST_TAG to be in 'tags'
+ // since it doesn't actually correspond to a position in the list, but is
+ // a placeholder that indicates if we should show the subscription list in the
+ // nav drawer at all.
+ showSubscriptionList = true;
+ newTags.remove(SUBSCRIPTION_LIST_TAG);
+ } else {
+ showSubscriptionList = false;
+ }
+
tags = newTags;
notifyDataSetChanged();
}
@@ -108,6 +128,9 @@ public class NavListAdapter extends BaseAdapter
case PlaybackHistoryFragment.TAG:
icon = R.attr.ic_history;
break;
+ case SubscriptionFragment.TAG:
+ icon = R.attr.ic_folder;
+ break;
case AddFeedFragment.TAG:
icon = R.attr.content_new;
break;
@@ -127,7 +150,11 @@ public class NavListAdapter extends BaseAdapter
@Override
public int getCount() {
- return getSubscriptionOffset() + itemAccess.getCount();
+ int baseCount = getSubscriptionOffset();
+ if (showSubscriptionList) {
+ baseCount += itemAccess.getCount();
+ }
+ return baseCount;
}
@Override
@@ -177,7 +204,7 @@ public class NavListAdapter extends BaseAdapter
} else if (viewType == VIEW_TYPE_SECTION_DIVIDER) {
v = getSectionDividerView(convertView, parent);
} else {
- v = getFeedView(position - getSubscriptionOffset(), convertView, parent);
+ v = getFeedView(position, convertView, parent);
}
if (v != null && viewType != VIEW_TYPE_SECTION_DIVIDER) {
TextView txtvTitle = (TextView) v.findViewById(R.id.txtvTitle);
@@ -226,6 +253,14 @@ public class NavListAdapter extends BaseAdapter
} else {
holder.count.setVisibility(View.GONE);
}
+ } else if (tag.equals(SubscriptionFragment.TAG)) {
+ int sum = itemAccess.getFeedCounterSum();
+ if (sum > 0) {
+ holder.count.setVisibility(View.VISIBLE);
+ holder.count.setText(String.valueOf(sum));
+ } else {
+ holder.count.setVisibility(View.GONE);
+ }
} else if(tag.equals(DownloadsFragment.TAG) && UserPreferences.isEnableAutodownload()) {
int epCacheSize = UserPreferences.getEpisodeCacheSize();
// don't count episodes that can be reclaimed
@@ -236,13 +271,13 @@ public class NavListAdapter extends BaseAdapter
holder.count.setText("{md-disc-full 150%}");
Iconify.addIcons(holder.count);
holder.count.setVisibility(View.VISIBLE);
- holder.count.setOnClickListener(v -> {
+ holder.count.setOnClickListener(v ->
new AlertDialog.Builder(context)
.setTitle(R.string.episode_cache_full_title)
.setMessage(R.string.episode_cache_full_message)
.setPositiveButton(android.R.string.ok, (dialog, which) -> {})
- .show();
- });
+ .show()
+ );
} else {
holder.count.setVisibility(View.GONE);
}
@@ -267,10 +302,11 @@ public class NavListAdapter extends BaseAdapter
return convertView;
}
- private View getFeedView(int feedPos, View convertView, ViewGroup parent) {
- FeedHolder holder;
+ private View getFeedView(int position, View convertView, ViewGroup parent) {
+ int feedPos = position - getSubscriptionOffset();
Feed feed = itemAccess.getItem(feedPos);
+ FeedHolder holder;
if (convertView == null) {
holder = new FeedHolder();
LayoutInflater inflater = (LayoutInflater) context
@@ -298,7 +334,6 @@ public class NavListAdapter extends BaseAdapter
holder.title.setText(feed.getTitle());
-
if(feed.hasLastUpdateFailed()) {
RelativeLayout.LayoutParams p = (RelativeLayout.LayoutParams) holder.title.getLayoutParams();
p.addRule(RelativeLayout.LEFT_OF, R.id.itxtvFailure);
@@ -312,7 +347,11 @@ public class NavListAdapter extends BaseAdapter
if(counter > 0) {
holder.count.setVisibility(View.VISIBLE);
holder.count.setText(String.valueOf(counter));
- holder.count.setTypeface(holder.title.getTypeface());
+ if (itemAccess.getSelectedItemIndex() == position) {
+ holder.count.setTypeface(null, Typeface.BOLD);
+ } else {
+ holder.count.setTypeface(null, Typeface.NORMAL);
+ }
} else {
holder.count.setVisibility(View.GONE);
}
@@ -341,6 +380,7 @@ public class NavListAdapter extends BaseAdapter
int getNumberOfDownloadedItems();
int getReclaimableItems();
int getFeedCounter(long feedId);
+ int getFeedCounterSum();
}
}
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 6cf61f90b..796ac4184 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/QueueRecyclerAdapter.java
@@ -1,12 +1,12 @@
package de.danoeh.antennapod.adapter;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
+import android.os.Build;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.MotionEventCompat;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
+import android.text.Layout;
import android.text.TextUtils;
import android.util.Log;
import android.view.ContextMenu;
@@ -23,12 +23,11 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import com.bumptech.glide.Glide;
-import com.bumptech.glide.load.resource.drawable.GlideDrawable;
-import com.bumptech.glide.request.animation.GlideAnimation;
-import com.bumptech.glide.request.target.GlideDrawableImageViewTarget;
import com.joanzapata.iconify.Iconify;
import com.nineoldandroids.view.ViewHelper;
+import org.apache.commons.lang3.ArrayUtils;
+
import java.lang.ref.WeakReference;
import de.danoeh.antennapod.R;
@@ -144,6 +143,9 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
placeholder = (TextView) v.findViewById(R.id.txtvPlaceholder);
cover = (ImageView) v.findViewById(R.id.imgvCover);
title = (TextView) v.findViewById(R.id.txtvTitle);
+ if(Build.VERSION.SDK_INT >= 23) {
+ title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
+ }
pubDate = (TextView) v.findViewById(R.id.txtvPubDate);
progressLeft = (TextView) v.findViewById(R.id.txtvProgressLeft);
progressRight = (TextView) v.findViewById(R.id.txtvProgressRight);
@@ -165,7 +167,9 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
public void onClick(View v) {
MainActivity activity = mainActivity.get();
if (activity != null) {
- activity.loadChildFragment(ItemFragment.newInstance(item.getId()));
+ long[] ids = itemAccess.getQueueIds().toArray();
+ int position = ArrayUtils.indexOf(ids, item.getId());
+ activity.loadChildFragment(ItemFragment.newInstance(ids, position));
}
}
@@ -189,8 +193,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
item1.setVisible(visible);
}
};
- FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, true,
- itemAccess.getQueueIds(), itemAccess.getFavoritesIds());
+ FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, true, itemAccess.getQueueIds());
}
@Override
@@ -258,7 +261,7 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
} else {
if(media.getSize() > 0) {
progressLeft.setText(Converter.byteToString(media.getSize()));
- } else if(NetworkUtils.isDownloadAllowed() && false == media.checkedOnSizeButUnknown()) {
+ } else if(NetworkUtils.isDownloadAllowed() && !media.checkedOnSizeButUnknown()) {
progressLeft.setText("{fa-spinner}");
Iconify.addIcons(progressLeft);
NetworkUtils.getFeedMediaSizeObservable(media)
@@ -297,48 +300,9 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
.diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
.fitCenter()
.dontAnimate()
- .into(new CoverTarget(item.getFeed().getImageUri(), placeholder, cover));
- }
-
- }
-
-
- private class CoverTarget extends GlideDrawableImageViewTarget {
-
- private final WeakReference<Uri> fallback;
- private final WeakReference<TextView> placeholder;
- private final WeakReference<ImageView> cover;
-
- public CoverTarget(Uri fallbackUri, TextView txtvPlaceholder, ImageView imgvCover) {
- super(imgvCover);
- fallback = new WeakReference<>(fallbackUri);
- placeholder = new WeakReference<>(txtvPlaceholder);
- cover = new WeakReference<>(imgvCover);
+ .into(new CoverTarget(item.getFeed().getImageUri(), placeholder, cover, mainActivity.get()));
}
- @Override
- public void onLoadFailed(Exception e, Drawable errorDrawable) {
- Uri fallbackUri = fallback.get();
- TextView txtvPlaceholder = placeholder.get();
- ImageView imgvCover = cover.get();
- if(fallbackUri != null && txtvPlaceholder != null && imgvCover != null) {
- Glide.with(mainActivity.get())
- .load(fallbackUri)
- .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
- .fitCenter()
- .dontAnimate()
- .into(new CoverTarget(null, txtvPlaceholder, imgvCover));
- }
- }
-
- @Override
- public void onResourceReady(GlideDrawable drawable, GlideAnimation anim) {
- super.onResourceReady(drawable, anim);
- TextView txtvPlaceholder = placeholder.get();
- if(txtvPlaceholder != null) {
- txtvPlaceholder.setVisibility(View.INVISIBLE);
- }
- }
}
private View.OnClickListener secondaryActionListener = new View.OnClickListener() {
@@ -357,7 +321,6 @@ public class QueueRecyclerAdapter extends RecyclerView.Adapter<QueueRecyclerAdap
long getItemDownloadSize(FeedItem item);
int getItemDownloadProgressPercent(FeedItem item);
LongList getQueueIds();
- LongList getFavoritesIds();
}
/**
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 83f5dcb4d..a68ef01d9 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/SearchlistAdapter.java
@@ -1,6 +1,8 @@
package de.danoeh.antennapod.adapter;
import android.content.Context;
+import android.os.Build;
+import android.text.Layout;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -9,7 +11,6 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
-import com.bumptech.glide.load.engine.DiskCacheStrategy;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.core.feed.Feed;
@@ -61,6 +62,9 @@ public class SearchlistAdapter extends BaseAdapter {
convertView = inflater.inflate(R.layout.searchlist_item, parent, false);
holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
+ if(Build.VERSION.SDK_INT >= 23) {
+ holder.title.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
+ }
holder.cover = (ImageView) convertView
.findViewById(R.id.imgvFeedimage);
holder.subtitle = (TextView) convertView
@@ -112,7 +116,7 @@ public class SearchlistAdapter extends BaseAdapter {
TextView subtitle;
}
- public static interface ItemAccess {
+ public interface ItemAccess {
int getCount();
SearchResult getItem(int position);
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java
new file mode 100644
index 000000000..7fb1472ad
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java
@@ -0,0 +1,97 @@
+package de.danoeh.antennapod.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.bumptech.glide.Glide;
+import com.joanzapata.iconify.widget.IconTextView;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.feed.Feed;
+import de.danoeh.antennapod.core.glide.ApGlideSettings;
+import de.danoeh.antennapod.core.storage.DBReader;
+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<>();
+
+ public StatisticsListAdapter(Context context) {
+ this.context = context;
+ }
+
+
+ @Override
+ public int getCount() {
+ return feedTime.size();
+ }
+
+ @Override
+ public DBReader.StatisticsItem getItem(int position) {
+ return feedTime.get(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return feedTime.get(position).feed.getId();
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ StatisticsHolder holder;
+ Feed feed = feedTime.get(position).feed;
+
+ if (convertView == null) {
+ holder = new StatisticsHolder();
+ LayoutInflater inflater = (LayoutInflater) context
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ convertView = inflater.inflate(R.layout.statistics_listitem, parent, false);
+
+ holder.image = (ImageView) convertView.findViewById(R.id.imgvCover);
+ holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
+ holder.time = (TextView) convertView.findViewById(R.id.txtvTime);
+ convertView.setTag(holder);
+ } else {
+ holder = (StatisticsHolder) convertView.getTag();
+ }
+
+ Glide.with(context)
+ .load(feed.getImageUri())
+ .placeholder(R.color.light_gray)
+ .error(R.color.light_gray)
+ .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
+ .fitCenter()
+ .dontAnimate()
+ .into(holder.image);
+
+ holder.title.setText(feed.getTitle());
+ holder.time.setText(Converter.shortLocalizedDuration(context,
+ feedTime.get(position).timePlayed));
+ return convertView;
+ }
+
+ public void update(List<DBReader.StatisticsItem> feedTime) {
+ this.feedTime = feedTime;
+ notifyDataSetChanged();
+ }
+
+ static class StatisticsHolder {
+ ImageView image;
+ TextView title;
+ TextView time;
+ }
+
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java
new file mode 100644
index 000000000..e2561804e
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/SubscriptionsAdapter.java
@@ -0,0 +1,141 @@
+package de.danoeh.antennapod.adapter;
+
+import android.content.Context;
+import android.net.Uri;
+import android.support.v4.app.Fragment;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.bumptech.glide.Glide;
+
+import java.lang.ref.WeakReference;
+
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.activity.MainActivity;
+import de.danoeh.antennapod.core.feed.Feed;
+import de.danoeh.antennapod.core.glide.ApGlideSettings;
+import de.danoeh.antennapod.fragment.AddFeedFragment;
+import de.danoeh.antennapod.fragment.ItemlistFragment;
+import jp.shts.android.library.TriangleLabelView;
+
+/**
+ * Adapter for subscriptions
+ */
+public class SubscriptionsAdapter extends BaseAdapter implements AdapterView.OnItemClickListener {
+
+ /** placeholder object that indicates item should be added */
+ public static final Object ADD_ITEM_OBJ = new Object();
+
+ /** the position in the view that holds the add item */
+ private static final int ADD_POSITION = 0;
+ private static final String TAG = "SubscriptionsAdapter";
+
+ private final WeakReference<MainActivity> mainActivityRef;
+ private final ItemAccess itemAccess;
+
+ public SubscriptionsAdapter(MainActivity mainActivity, ItemAccess itemAccess) {
+ this.mainActivityRef = new WeakReference<>(mainActivity);
+ this.itemAccess = itemAccess;
+ }
+
+ private int getAdjustedPosition(int origPosition) {
+ return origPosition - 1;
+ }
+
+ @Override
+ public int getCount() {
+ return 1 + itemAccess.getCount();
+ }
+
+ @Override
+ public Object getItem(int position) {
+ if (position == ADD_POSITION) {
+ return ADD_ITEM_OBJ;
+ }
+ return itemAccess.getItem(getAdjustedPosition(position));
+ }
+
+ @Override
+ public long getItemId(int position) {
+ if (position == ADD_POSITION) {
+ return 0;
+ }
+ return itemAccess.getItem(getAdjustedPosition(position)).getId();
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ Holder holder;
+
+ if (convertView == null) {
+ holder = new Holder();
+
+ LayoutInflater layoutInflater =
+ (LayoutInflater) mainActivityRef.get().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ convertView = layoutInflater.inflate(R.layout.subscription_item, parent, false);
+ holder.feedTitle = (TextView) convertView.findViewById(R.id.txtvTitle);
+ holder.imageView = (ImageView) convertView.findViewById(R.id.imgvCover);
+ holder.count = (TriangleLabelView) convertView.findViewById(R.id.triangleCountView);
+
+
+ convertView.setTag(holder);
+ } else {
+ holder = (Holder) convertView.getTag();
+ }
+
+ if (position == ADD_POSITION) {
+ holder.feedTitle.setText("{md-add 500%}\n\n" + mainActivityRef.get().getString(R.string.add_feed_label));
+ holder.feedTitle.setVisibility(View.VISIBLE);
+ // prevent any accidental re-use of old values (not sure how that would happen...)
+ holder.count.setPrimaryText("");
+ // make it go away, we don't need it for add feed
+ holder.count.setVisibility(View.INVISIBLE);
+ return convertView;
+ }
+
+ final Feed feed = (Feed) getItem(position);
+ if (feed == null) return null;
+
+ holder.feedTitle.setText(feed.getTitle());
+ holder.feedTitle.setVisibility(View.VISIBLE);
+ holder.count.setPrimaryText(String.valueOf(itemAccess.getFeedCounter(feed.getId())));
+ holder.count.setVisibility(View.VISIBLE);
+ Glide.with(mainActivityRef.get())
+ .load(feed.getImageUri())
+ .error(R.color.light_gray)
+ .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY)
+ .fitCenter()
+ .dontAnimate()
+ .into(new CoverTarget(null, holder.feedTitle, holder.imageView, mainActivityRef.get()));
+
+ return convertView;
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ if (position == ADD_POSITION) {
+ mainActivityRef.get().loadChildFragment(new AddFeedFragment());
+ } else {
+ Fragment fragment = ItemlistFragment.newInstance(getItemId(position));
+ mainActivityRef.get().loadChildFragment(fragment);
+ }
+ }
+
+ static class Holder {
+ public TextView feedTitle;
+ public ImageView imageView;
+ public TriangleLabelView count;
+ }
+
+ public interface ItemAccess {
+ int getCount();
+ Feed getItem(int position);
+ int getFeedCounter(long feedId);
+ }
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java
index 743f9fc86..aea3d583f 100644
--- a/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java
+++ b/app/src/main/java/de/danoeh/antennapod/adapter/gpodnet/PodcastListAdapter.java
@@ -9,7 +9,6 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
-import com.bumptech.glide.load.engine.DiskCacheStrategy;
import org.apache.commons.lang3.StringUtils;
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 47ac4c757..e9756b467 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
@@ -167,7 +167,7 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> {
for(int i=0; imageUrl == null && i < images.length(); i++) {
JSONObject image = images.getJSONObject(i);
String height = image.getJSONObject("attributes").getString("height");
- if(Integer.valueOf(height) >= 100) {
+ if(Integer.parseInt(height) >= 100) {
imageUrl = image.getString("label");
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java
index 5c24c2822..13abb26ea 100644
--- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java
+++ b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java
@@ -3,7 +3,6 @@ package de.danoeh.antennapod.asynctask;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
@@ -80,14 +79,7 @@ public class OpmlExportWorker extends AsyncTask<Void, Void, Void> {
progDialog.dismiss();
AlertDialog.Builder alert = new AlertDialog.Builder(context)
.setNeutralButton(android.R.string.ok,
- new DialogInterface.OnClickListener() {
-
- @Override
- public void onClick(DialogInterface dialog,
- int which) {
- dialog.dismiss();
- }
- });
+ (dialog, which) -> dialog.dismiss());
if (exception != null) {
alert.setTitle(R.string.export_error_label);
alert.setMessage(exception.getMessage());
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 cc27b6c9d..1cb653f01 100644
--- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java
+++ b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java
@@ -43,9 +43,8 @@ public class OpmlFeedQueuer extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
DownloadRequester requester = DownloadRequester.getInstance();
- for (int idx = 0; idx < selection.length; idx++) {
- OpmlElement element = OpmlImportHolder.getReadElements().get(
- selection[idx]);
+ for (int selected : selection) {
+ OpmlElement element = OpmlImportHolder.getReadElements().get(selected);
Feed feed = new Feed(element.getXmlUrl(), null,
element.getText());
try {
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 86636485d..45ec6c5fa 100644
--- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java
+++ b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java
@@ -3,21 +3,20 @@ package de.danoeh.antennapod.asynctask;
import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
import android.os.AsyncTask;
import android.support.v7.app.AlertDialog;
import android.util.Log;
-import de.danoeh.antennapod.core.BuildConfig;
-import de.danoeh.antennapod.core.R;
-import de.danoeh.antennapod.core.opml.OpmlElement;
-import de.danoeh.antennapod.core.opml.OpmlReader;
+
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
+import de.danoeh.antennapod.core.R;
+import de.danoeh.antennapod.core.opml.OpmlElement;
+import de.danoeh.antennapod.core.opml.OpmlReader;
+
public class OpmlImportWorker extends
AsyncTask<Void, Void, ArrayList<OpmlElement>> {
private static final String TAG = "OpmlImportWorker";
diff --git a/app/src/main/java/de/danoeh/antennapod/config/DBTasksCallbacksImpl.java b/app/src/main/java/de/danoeh/antennapod/config/DBTasksCallbacksImpl.java
index 9f8af1142..c3f7ae9c8 100644
--- a/app/src/main/java/de/danoeh/antennapod/config/DBTasksCallbacksImpl.java
+++ b/app/src/main/java/de/danoeh/antennapod/config/DBTasksCallbacksImpl.java
@@ -2,7 +2,6 @@ package de.danoeh.antennapod.config;
import de.danoeh.antennapod.core.DBTasksCallbacks;
import de.danoeh.antennapod.core.preferences.UserPreferences;
-import de.danoeh.antennapod.core.storage.APCleanupAlgorithm;
import de.danoeh.antennapod.core.storage.APDownloadAlgorithm;
import de.danoeh.antennapod.core.storage.AutomaticDownloadAlgorithm;
import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithm;
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 997befe99..1ab60ef61 100644
--- a/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java
+++ b/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java
@@ -5,6 +5,7 @@ import android.content.Intent;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.AudioplayerActivity;
+import de.danoeh.antennapod.activity.CastplayerActivity;
import de.danoeh.antennapod.activity.VideoplayerActivity;
import de.danoeh.antennapod.core.PlaybackServiceCallbacks;
import de.danoeh.antennapod.core.feed.MediaType;
@@ -12,7 +13,10 @@ import de.danoeh.antennapod.core.feed.MediaType;
public class PlaybackServiceCallbacksImpl implements PlaybackServiceCallbacks {
@Override
- public Intent getPlayerActivityIntent(Context context, MediaType mediaType) {
+ public Intent getPlayerActivityIntent(Context context, MediaType mediaType, boolean remotePlayback) {
+ if (remotePlayback) {
+ return new Intent(context, CastplayerActivity.class);
+ }
if (mediaType == MediaType.VIDEO) {
return new Intent(context, VideoplayerActivity.class);
} else {
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/AuthenticationDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/AuthenticationDialog.java
index bdb2d68ba..6f9e221ec 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/AuthenticationDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/AuthenticationDialog.java
@@ -2,13 +2,13 @@ package de.danoeh.antennapod.dialog;
import android.app.Dialog;
import android.content.Context;
-import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
+
import de.danoeh.antennapod.R;
/**
@@ -58,26 +58,13 @@ public abstract class AuthenticationDialog extends Dialog {
if (passwordInitialValue != null) {
etxtPassword.setText(passwordInitialValue);
}
- setOnCancelListener(new OnCancelListener() {
- @Override
- public void onCancel(DialogInterface dialog) {
- onCancelled();
- }
- });
- butCancel.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- cancel();
- }
- });
- butConfirm.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- onConfirmed(etxtUsername.getText().toString(),
- etxtPassword.getText().toString(),
- showSaveCredentialsCheckbox && saveUsernamePassword.isChecked());
- dismiss();
- }
+ setOnCancelListener(dialog -> onCancelled());
+ butCancel.setOnClickListener(v -> cancel());
+ butConfirm.setOnClickListener(v -> {
+ onConfirmed(etxtUsername.getText().toString(),
+ etxtPassword.getText().toString(),
+ showSaveCredentialsCheckbox && saveUsernamePassword.isChecked());
+ dismiss();
});
}
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/AutoFlattrPreferenceDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/AutoFlattrPreferenceDialog.java
index 75b1bc8d2..93425949c 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/AutoFlattrPreferenceDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/AutoFlattrPreferenceDialog.java
@@ -3,7 +3,6 @@ package de.danoeh.antennapod.dialog;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
-import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.widget.CheckBox;
@@ -42,12 +41,9 @@ public class AutoFlattrPreferenceDialog {
setStatusMsgText(activity, txtvStatus, initialValue);
skbPercent.setProgress(initialValue);
- chkAutoFlattr.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- skbPercent.setEnabled(chkAutoFlattr.isChecked());
- txtvStatus.setEnabled(chkAutoFlattr.isChecked());
- }
+ chkAutoFlattr.setOnClickListener(v -> {
+ skbPercent.setEnabled(chkAutoFlattr.isChecked());
+ txtvStatus.setEnabled(chkAutoFlattr.isChecked());
});
skbPercent.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@@ -69,20 +65,14 @@ public class AutoFlattrPreferenceDialog {
builder.setTitle(R.string.pref_auto_flattr_title)
.setView(view)
- .setPositiveButton(R.string.confirm_label, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- float progDouble = ((float) skbPercent.getProgress()) / 100.0f;
- callback.onConfirmed(chkAutoFlattr.isChecked(), progDouble);
- dialog.dismiss();
- }
+ .setPositiveButton(R.string.confirm_label, (dialog, which) -> {
+ float progDouble = ((float) skbPercent.getProgress()) / 100.0f;
+ callback.onConfirmed(chkAutoFlattr.isChecked(), progDouble);
+ dialog.dismiss();
})
- .setNegativeButton(R.string.cancel_label, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- callback.onCancelled();
- dialog.dismiss();
- }
+ .setNegativeButton(R.string.cancel_label, (dialog, which) -> {
+ callback.onCancelled();
+ dialog.dismiss();
})
.setCancelable(false).show();
}
@@ -97,10 +87,10 @@ public class AutoFlattrPreferenceDialog {
}
}
- public static interface AutoFlattrPreferenceDialogInterface {
- public void onCancelled();
+ public interface AutoFlattrPreferenceDialogInterface {
+ void onCancelled();
- public void onConfirmed(boolean autoFlattrEnabled, float autoFlattrValue);
+ void onConfirmed(boolean autoFlattrEnabled, float autoFlattrValue);
}
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 ac7a9efee..577a3ecbe 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java
@@ -54,7 +54,7 @@ public class EpisodesApplyActionFragment extends Fragment {
private final Map<Long,FeedItem> idMap = new ArrayMap<>();
private final List<FeedItem> episodes = new ArrayList<>();
private int actions;
- private final List<String> titles = new ArrayList();
+ private final List<String> titles = new ArrayList<>();
private final LongList checkedIds = new LongList();
private MenuItem mSelectToggle;
@@ -285,9 +285,9 @@ public class EpisodesApplyActionFragment extends Fragment {
private void sortByDuration(final boolean reverse) {
Collections.sort(episodes, (lhs, rhs) -> {
int ordering;
- if (false == lhs.hasMedia()) {
+ if (!lhs.hasMedia()) {
ordering = 1;
- } else if (false == rhs.hasMedia()) {
+ } else if (!rhs.hasMedia()) {
ordering = -1;
} else {
ordering = lhs.getMedia().getDuration() - rhs.getMedia().getDuration();
@@ -304,7 +304,7 @@ public class EpisodesApplyActionFragment extends Fragment {
private void checkAll() {
for (FeedItem episode : episodes) {
- if(false == checkedIds.contains(episode.getId())) {
+ if(!checkedIds.contains(episode.getId())) {
checkedIds.add(episode.getId());
}
}
@@ -391,14 +391,14 @@ public class EpisodesApplyActionFragment extends Fragment {
private void downloadChecked() {
// download the check episodes in the same order as they are currently displayed
- List<FeedItem> toDownload = new ArrayList<FeedItem>(checkedIds.size());
+ List<FeedItem> toDownload = new ArrayList<>(checkedIds.size());
for(FeedItem episode : episodes) {
if(checkedIds.contains(episode.getId())) {
toDownload.add(episode);
}
}
try {
- DBTasks.downloadFeedItems(getActivity(), toDownload.toArray(new FeedItem[0]));
+ DBTasks.downloadFeedItems(getActivity(), toDownload.toArray(new FeedItem[toDownload.size()]));
} catch (DownloadRequestException e) {
e.printStackTrace();
DownloadRequestErrorDialogCreator.newRequestErrorDialog(getActivity(), e.getMessage());
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 5f531e88f..b50e21d15 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/GpodnetSetHostnameDialog.java
@@ -1,7 +1,6 @@
package de.danoeh.antennapod.dialog;
import android.content.Context;
-import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.text.Editable;
import android.text.InputType;
diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java
new file mode 100644
index 000000000..98a4b5356
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java
@@ -0,0 +1,320 @@
+package de.danoeh.antennapod.dialog;
+
+import android.app.Dialog;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.support.v4.content.ContextCompat;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.Patterns;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.EditText;
+import android.widget.Spinner;
+import android.widget.TextView;
+
+import com.afollestad.materialdialogs.DialogAction;
+import com.afollestad.materialdialogs.MaterialDialog;
+import com.afollestad.materialdialogs.internal.MDButton;
+import com.squareup.okhttp.Credentials;
+import com.squareup.okhttp.OkHttpClient;
+import com.squareup.okhttp.Request;
+import com.squareup.okhttp.Response;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.SocketAddress;
+import java.util.concurrent.TimeUnit;
+
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
+import de.danoeh.antennapod.core.service.download.ProxyConfig;
+import rx.Observable;
+import rx.Subscriber;
+import rx.Subscription;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.schedulers.Schedulers;
+
+public class ProxyDialog {
+
+ private static final String TAG = "ProxyDialog";
+
+ private Context context;
+
+ private MaterialDialog dialog;
+
+ private Spinner spType;
+ private EditText etHost;
+ private EditText etPort;
+ private EditText etUsername;
+ private EditText etPassword;
+
+ private boolean testSuccessful = false;
+ private TextView txtvMessage;
+ private Subscription subscription;
+
+ public ProxyDialog(Context context) {
+ this.context = context;
+ }
+
+ public Dialog createDialog() {
+ dialog = new MaterialDialog.Builder(context)
+ .title(R.string.pref_proxy_title)
+ .customView(R.layout.proxy_settings, true)
+ .positiveText(R.string.proxy_test_label)
+ .negativeText(R.string.cancel_label)
+ .onPositive((dialog1, which) -> {
+ if(!testSuccessful) {
+ dialog.getActionButton(DialogAction.POSITIVE).setEnabled(false);
+ test();
+ return;
+ }
+ String type = (String) ((Spinner) dialog1.findViewById(R.id.spType)).getSelectedItem();
+ ProxyConfig proxy;
+ if(Proxy.Type.valueOf(type) == Proxy.Type.DIRECT) {
+ proxy = ProxyConfig.direct();
+ } else {
+ String host = etHost.getText().toString();
+ String port = etPort.getText().toString();
+ String username = etUsername.getText().toString();
+ if(TextUtils.isEmpty(username)) {
+ username = null;
+ }
+ String password = etPassword.getText().toString();
+ if(TextUtils.isEmpty(password)) {
+ password = null;
+ }
+ int portValue = 0;
+ if(!TextUtils.isEmpty(port)) {
+ portValue = Integer.valueOf(port);
+ }
+ proxy = ProxyConfig.http(host, portValue, username, password);
+ }
+ UserPreferences.setProxyConfig(proxy);
+ AntennapodHttpClient.reinit();
+ dialog.dismiss();
+ })
+ .onNegative((dialog1, which) -> dialog1.dismiss())
+ .autoDismiss(false)
+ .build();
+ View view = dialog.getCustomView();
+ spType = (Spinner) view.findViewById(R.id.spType);
+ String[] types = { Proxy.Type.DIRECT.name(), Proxy.Type.HTTP.name() };
+ ArrayAdapter<String> adapter = new ArrayAdapter<>(context,
+ android.R.layout.simple_spinner_item, types);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spType.setAdapter(adapter);
+ ProxyConfig proxyConfig = UserPreferences.getProxyConfig();
+ spType.setSelection(adapter.getPosition(proxyConfig.type.name()));
+ etHost = (EditText) view.findViewById(R.id.etHost);
+ if(!TextUtils.isEmpty(proxyConfig.host)) {
+ etHost.setText(proxyConfig.host);
+ }
+ etHost.addTextChangedListener(requireTestOnChange);
+ etPort = (EditText) view.findViewById(R.id.etPort);
+ if(proxyConfig.port > 0) {
+ etPort.setText(String.valueOf(proxyConfig.port));
+ }
+ etPort.addTextChangedListener(requireTestOnChange);
+ etUsername = (EditText) view.findViewById(R.id.etUsername);
+ if(!TextUtils.isEmpty(proxyConfig.username)) {
+ etUsername.setText(proxyConfig.username);
+ }
+ etUsername.addTextChangedListener(requireTestOnChange);
+ etPassword = (EditText) view.findViewById(R.id.etPassword);
+ if(!TextUtils.isEmpty(proxyConfig.password)) {
+ etPassword.setText(proxyConfig.username);
+ }
+ etPassword.addTextChangedListener(requireTestOnChange);
+ if(proxyConfig.type == Proxy.Type.DIRECT) {
+ enableSettings(false);
+ setTestRequired(false);
+ }
+ spType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ enableSettings(position > 0);
+ setTestRequired(position > 0);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ enableSettings(false);
+ }
+ });
+ txtvMessage = (TextView) view.findViewById(R.id.txtvMessage);
+ checkValidity();
+ return dialog;
+ }
+
+ private final TextWatcher requireTestOnChange = 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) {
+ setTestRequired(true);
+ }
+ };
+
+ private void enableSettings(boolean enable) {
+ etHost.setEnabled(enable);
+ etPort.setEnabled(enable);
+ etUsername.setEnabled(enable);
+ etPassword.setEnabled(enable);
+ }
+
+ private boolean checkValidity() {
+ boolean valid = true;
+ if(spType.getSelectedItemPosition() > 0) {
+ valid &= checkHost();
+ }
+ valid &= checkPort();
+ return valid;
+ }
+
+ private boolean checkHost() {
+ String host = etHost.getText().toString();
+ if(host.length() == 0) {
+ etHost.setError(context.getString(R.string.proxy_host_empty_error));
+ return false;
+ }
+ if(!"localhost".equals(host) && !Patterns.DOMAIN_NAME.matcher(host).matches()) {
+ etHost.setError(context.getString(R.string.proxy_host_invalid_error));
+ return false;
+ }
+ return true;
+ }
+
+ private boolean checkPort() {
+ int port = getPort();
+ if(port < 0 && port > 65535) {
+ etPort.setError(context.getString(R.string.proxy_port_invalid_error));
+ return false;
+ }
+ return true;
+ }
+
+ private int getPort() {
+ String port = etPort.getText().toString();
+ if(port.length() > 0) {
+ try {
+ return Integer.parseInt(port);
+ } catch(NumberFormatException e) {
+ // ignore
+ }
+ }
+ return 0;
+ }
+
+ private void setTestRequired(boolean required) {
+ if(required) {
+ testSuccessful = false;
+ MDButton button = dialog.getActionButton(DialogAction.POSITIVE);
+ button.setText(context.getText(R.string.proxy_test_label));
+ button.setEnabled(true);
+ } else {
+ testSuccessful = true;
+ MDButton button = dialog.getActionButton(DialogAction.POSITIVE);
+ button.setText(context.getText(android.R.string.ok));
+ button.setEnabled(true);
+ }
+ }
+
+ private void test() {
+ if(subscription != null) {
+ subscription.unsubscribe();
+ }
+ if(!checkValidity()) {
+ setTestRequired(true);
+ return;
+ }
+ TypedArray res = context.getTheme().obtainStyledAttributes(new int[] { android.R.attr.textColorPrimary });
+ int textColorPrimary = res.getColor(0, 0);
+ res.recycle();
+ String checking = context.getString(R.string.proxy_checking);
+ 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 client = AntennapodHttpClient.newHttpClient();
+ client.setConnectTimeout(10, TimeUnit.SECONDS);
+ client.setProxy(proxy);
+ client.interceptors().clear();
+ 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(
+ response -> {
+ int colorId;
+ String icon;
+ String result;
+ if(response.isSuccessful()) {
+ colorId = R.color.download_success_green;
+ icon = "{fa-check}";
+ result = context.getString(R.string.proxy_test_successful);
+ } else {
+ colorId = R.color.download_failed_red;
+ icon = "{fa-close}";
+ result = context.getString(R.string.proxy_test_failed);
+ }
+ int color = ContextCompat.getColor(context, colorId);
+ txtvMessage.setTextColor(color);
+ String message = String.format("%s %s: %s", icon, result, response.message());
+ txtvMessage.setText(message);
+ setTestRequired(!response.isSuccessful());
+ },
+ error -> {
+ String icon = "{fa-close}";
+ String result = context.getString(R.string.proxy_test_failed);
+ int color = ContextCompat.getColor(context, R.color.download_failed_red);
+ txtvMessage.setTextColor(color);
+ String message = String.format("%s %s: %s", icon, result, error.getMessage());
+ txtvMessage.setText(message);
+ setTestRequired(true);
+ }
+ );
+ }
+
+}
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 ed0db92a4..64fc1fda4 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/RatingDialog.java
@@ -94,11 +94,7 @@ public class RatingDialog {
long firstDate = mPreferences.getLong(KEY_FIRST_START_DATE, now);
long diff = now - firstDate;
long diffDays = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
- if (diffDays >= AFTER_DAYS) {
- return true;
- } else {
- return false;
- }
+ return diffDays >= AFTER_DAYS;
}
@Nullable
@@ -107,30 +103,16 @@ public class RatingDialog {
if(context == null) {
return null;
}
- MaterialDialog dialog = new MaterialDialog.Builder(context)
+ return new MaterialDialog.Builder(context)
.title(R.string.rating_title)
.content(R.string.rating_message)
.positiveText(R.string.rating_now_label)
.negativeText(R.string.rating_never_label)
.neutralText(R.string.rating_later_label)
- .callback(new MaterialDialog.ButtonCallback() {
- @Override
- public void onPositive(MaterialDialog dialog) {
- rateNow();
- }
-
- @Override
- public void onNegative(MaterialDialog dialog) {
- saveRated();
- }
-
- @Override
- public void onNeutral(MaterialDialog dialog) {
- resetStartDate();
- }
- })
+ .onPositive((dialog, which) -> rateNow())
+ .onNegative((dialog, which) -> saveRated())
+ .onNeutral((dialog, which) -> resetStartDate())
.cancelListener(dialog1 -> resetStartDate())
.build();
- return dialog;
}
}
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 930079e40..8a13a75d9 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java
@@ -1,17 +1,13 @@
package de.danoeh.antennapod.dialog;
-import android.app.Dialog;
import android.content.Context;
import android.content.SharedPreferences;
-import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
-import android.view.Window;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
-import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Spinner;
@@ -58,14 +54,8 @@ public abstract class SleepTimerDialog {
builder.customView(R.layout.time_dialog, false);
builder.positiveText(R.string.set_sleeptimer_label);
builder.negativeText(R.string.cancel_label);
- builder.callback(new MaterialDialog.ButtonCallback() {
- @Override
- public void onNegative(MaterialDialog dialog) {
- dialog.dismiss();
- }
-
- @Override
- public void onPositive(MaterialDialog dialog) {
+ builder.onNegative((dialog, which) -> dialog.dismiss());
+ builder.onPositive((dialog, which) -> {
try {
savePreferences();
long input = readTimeMillis();
@@ -77,8 +67,7 @@ public abstract class SleepTimerDialog {
Toast.LENGTH_LONG);
toast.show();
}
- }
- });
+ });
dialog = builder.build();
View view = dialog.getView();
@@ -138,7 +127,7 @@ public abstract class SleepTimerDialog {
private long readTimeMillis() {
TimeUnit selectedUnit = units[spTimeUnit.getSelectedItemPosition()];
- long value = Long.valueOf(etxtTime.getText().toString());
+ long value = Long.parseLong(etxtTime.getText().toString());
return selectedUnit.toMillis(value);
}
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 3ed82b9bd..2bf9c4e7a 100644
--- a/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
+++ b/app/src/main/java/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
@@ -102,8 +102,8 @@ public class VariableSpeedDialog {
builder.setPositiveButton(android.R.string.ok,
(dialog, which) -> {
int choiceCount = 0;
- for (int i = 0; i < speedChecked.length; i++) {
- if (speedChecked[i]) {
+ for (boolean checked : speedChecked) {
+ if (checked) {
choiceCount++;
}
}
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 d979dc382..45364ca07 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java
@@ -47,36 +47,18 @@ public class AddFeedFragment extends Fragment {
final MainActivity activity = (MainActivity) getActivity();
activity.getSupportActionBar().setTitle(R.string.add_feed_label);
- butSearchITunes.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- activity.loadChildFragment(new ItunesSearchFragment());
- }
- });
+ butSearchITunes.setOnClickListener(v -> activity.loadChildFragment(new ItunesSearchFragment()));
- butBrowserGpoddernet.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- activity.loadChildFragment(new GpodnetMainFragment());
- }
- });
+ butBrowserGpoddernet.setOnClickListener(v -> activity.loadChildFragment(new GpodnetMainFragment()));
- butOpmlImport.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- startActivity(new Intent(getActivity(),
- OpmlImportFromPathActivity.class));
- }
- });
+ butOpmlImport.setOnClickListener(v -> startActivity(new Intent(getActivity(),
+ OpmlImportFromPathActivity.class)));
- butConfirm.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent intent = new Intent(getActivity(), OnlineFeedViewActivity.class);
- intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, etxtFeedurl.getText().toString());
- intent.putExtra(OnlineFeedViewActivity.ARG_TITLE, getString(R.string.add_feed_label));
- startActivity(intent);
- }
+ butConfirm.setOnClickListener(v -> {
+ Intent intent = new Intent(getActivity(), OnlineFeedViewActivity.class);
+ intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, etxtFeedurl.getText().toString());
+ intent.putExtra(OnlineFeedViewActivity.ARG_TITLE, getString(R.string.add_feed_label));
+ startActivity(intent);
});
return root;
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 aa2879330..8ae7f1cf9 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java
@@ -1,6 +1,5 @@
package de.danoeh.antennapod.fragment;
-import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
@@ -24,7 +23,6 @@ import android.widget.Toast;
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;
import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.MainActivity;
@@ -72,17 +70,15 @@ public class AllEpisodesFragment extends Fragment {
private static final String PREF_SCROLL_OFFSET = "scroll_offset";
protected RecyclerView recyclerView;
- private AllEpisodesRecycleAdapter listAdapter;
+ protected AllEpisodesRecycleAdapter listAdapter;
private ProgressBar progLoading;
- private List<FeedItem> episodes;
+ protected List<FeedItem> episodes;
private List<Downloader> downloaderList;
private boolean itemsLoaded = false;
private boolean viewsCreated = false;
- private AtomicReference<MainActivity> activity = new AtomicReference<MainActivity>();
-
private boolean isUpdatingFeeds;
protected Subscription subscription;
@@ -101,7 +97,6 @@ public class AllEpisodesFragment extends Fragment {
public void onStart() {
super.onStart();
EventDistributor.getInstance().register(contentUpdate);
- this.activity.set((MainActivity) getActivity());
if (viewsCreated && itemsLoaded) {
onFragmentLoaded();
}
@@ -133,12 +128,6 @@ public class AllEpisodesFragment extends Fragment {
}
@Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- this.activity.set((MainActivity) getActivity());
- }
-
- @Override
public void onDestroyView() {
super.onDestroyView();
resetViewState();
@@ -176,18 +165,13 @@ public class AllEpisodesFragment extends Fragment {
}
protected void resetViewState() {
- listAdapter = null;
- activity.set(null);
viewsCreated = false;
+ listAdapter = null;
}
- private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker = new MenuItemUtils.UpdateRefreshMenuItemChecker() {
- @Override
- public boolean isRefreshing() {
- return DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
- }
- };
+ private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker =
+ () -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
@@ -325,7 +309,7 @@ public class AllEpisodesFragment extends Fragment {
viewsCreated = true;
- if (itemsLoaded && activity.get() != null) {
+ if (itemsLoaded) {
onFragmentLoaded();
}
@@ -334,7 +318,7 @@ public class AllEpisodesFragment extends Fragment {
private void onFragmentLoaded() {
if (listAdapter == null) {
- MainActivity mainActivity = activity.get();
+ MainActivity mainActivity = (MainActivity) getActivity();
listAdapter = new AllEpisodesRecycleAdapter(mainActivity, itemAccess,
new DefaultActionButtonCallback(mainActivity), showOnlyNewEpisodes());
listAdapter.setHasStableIds(true);
@@ -365,6 +349,18 @@ public class AllEpisodesFragment extends Fragment {
}
@Override
+ public LongList getItemsIds() {
+ if(episodes == null) {
+ return new LongList(0);
+ }
+ LongList ids = new LongList(episodes.size());
+ for(FeedItem episode : episodes) {
+ ids.add(episode.getId());
+ }
+ return ids;
+ }
+
+ @Override
public int getItemDownloadProgressPercent(FeedItem item) {
if (downloaderList != null) {
for (Downloader downloader : downloaderList) {
@@ -379,39 +375,9 @@ public class AllEpisodesFragment extends Fragment {
@Override
public boolean isInQueue(FeedItem item) {
- if (item != null) {
- return item.isTagged(FeedItem.TAG_QUEUE);
- }
- return false;
+ return item != null && item.isTagged(FeedItem.TAG_QUEUE);
}
- @Override
- public LongList getQueueIds() {
- LongList queueIds = new LongList();
- if(episodes == null) {
- return queueIds;
- }
- for(FeedItem item : episodes) {
- if(item.isTagged(FeedItem.TAG_QUEUE)) {
- queueIds.add(item.getId());
- }
- }
- return queueIds;
- }
-
- @Override
- public LongList getFavoritesIds() {
- LongList favoritesIds = new LongList();
- if(episodes == null) {
- return favoritesIds;
- }
- for(FeedItem item : episodes) {
- if(item.isTagged(FeedItem.TAG_FAVORITE)) {
- favoritesIds.add(item.getId());
- }
- }
- return favoritesIds;
- }
};
public void onEventMainThread(FeedItemEvent event) {
@@ -471,7 +437,7 @@ public class AllEpisodesFragment extends Fragment {
recyclerView.setVisibility(View.GONE);
progLoading.setVisibility(View.VISIBLE);
}
- subscription = Observable.fromCallable(() -> loadData())
+ subscription = Observable.fromCallable(this::loadData)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(data -> {
@@ -480,7 +446,7 @@ public class AllEpisodesFragment extends Fragment {
if (data != null) {
episodes = data;
itemsLoaded = true;
- if (viewsCreated && activity.get() != null) {
+ if (viewsCreated) {
onFragmentLoaded();
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java
index 96abdd835..77e66f3b0 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java
@@ -2,28 +2,30 @@ package de.danoeh.antennapod.fragment;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
+import android.util.Log;
import android.view.View;
import android.widget.ListView;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.AudioplayerActivity.AudioplayerContentFragment;
+import de.danoeh.antennapod.activity.MediaplayerInfoActivity.MediaplayerInfoContentFragment;
import de.danoeh.antennapod.adapter.ChaptersListAdapter;
import de.danoeh.antennapod.core.feed.Chapter;
import de.danoeh.antennapod.core.util.playback.Playable;
import de.danoeh.antennapod.core.util.playback.PlaybackController;
-public class ChaptersFragment extends ListFragment implements AudioplayerContentFragment {
+public class ChaptersFragment extends ListFragment implements MediaplayerInfoContentFragment {
+
+ private static final String TAG = "ChaptersFragment";
private Playable media;
private PlaybackController controller;
private ChaptersListAdapter adapter;
- public static ChaptersFragment newInstance(Playable media, PlaybackController controller) {
+ public static ChaptersFragment newInstance(Playable media) {
ChaptersFragment f = new ChaptersFragment();
f.media = media;
- f.controller = controller;
return f;
}
@@ -37,6 +39,10 @@ public class ChaptersFragment extends ListFragment implements AudioplayerContent
lv.setPadding(0, vertPadding, 0, vertPadding);
adapter = new ChaptersListAdapter(getActivity(), 0, pos -> {
+ if(controller == null) {
+ Log.d(TAG, "controller is null");
+ return;
+ }
Chapter chapter = (Chapter) getListAdapter().getItem(pos);
controller.seekToChapter(chapter);
});
@@ -58,6 +64,7 @@ public class ChaptersFragment extends ListFragment implements AudioplayerContent
public void onDestroy() {
super.onDestroy();
adapter = null;
+ controller = null;
}
@Override
@@ -74,4 +81,9 @@ public class ChaptersFragment extends ListFragment implements AudioplayerContent
setEmptyText(null);
}
}
+
+ public void setController(PlaybackController controller) {
+ this.controller = controller;
+ }
+
}
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 a53c85f1c..d14265f70 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java
@@ -25,6 +25,7 @@ import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
+import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment;
import rx.Observable;
import rx.Subscription;
@@ -116,10 +117,9 @@ public class CompletedDownloadsFragment extends ListFragment {
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
- FeedItem item = listAdapter.getItem(position - l.getHeaderViewsCount());
- if (item != null) {
- ((MainActivity) getActivity()).loadChildFragment(ItemFragment.newInstance(item.getId()));
- }
+ position -= l.getHeaderViewsCount();
+ long[] ids = FeedItemUtil.getIds(items);
+ ((MainActivity) getActivity()).loadChildFragment(ItemFragment.newInstance(ids, position));
}
private void onFragmentLoaded() {
@@ -205,7 +205,7 @@ public class CompletedDownloadsFragment extends ListFragment {
if (items == null && viewCreated) {
setListShown(false);
}
- subscription = Observable.fromCallable(() -> DBReader.getDownloadedItems())
+ subscription = Observable.fromCallable(DBReader::getDownloadedItems)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java
index d3b97f9df..943ddeec7 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java
@@ -12,14 +12,14 @@ import android.widget.TextView;
import com.bumptech.glide.Glide;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.AudioplayerActivity.AudioplayerContentFragment;
+import de.danoeh.antennapod.activity.MediaplayerInfoActivity.MediaplayerInfoContentFragment;
import de.danoeh.antennapod.core.glide.ApGlideSettings;
import de.danoeh.antennapod.core.util.playback.Playable;
/**
* Displays the cover and the title of a FeedItem.
*/
-public class CoverFragment extends Fragment implements AudioplayerContentFragment {
+public class CoverFragment extends Fragment implements MediaplayerInfoContentFragment {
private static final String TAG = "CoverFragment";
private static final String ARG_PLAYABLE = "arg.playable";
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 b470d379a..93527b149 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java
@@ -154,7 +154,7 @@ public class DownloadLogFragment extends ListFragment {
if(subscription != null) {
subscription.unsubscribe();
}
- subscription = Observable.fromCallable(() -> DBReader.getDownloadLog())
+ subscription = Observable.fromCallable(DBReader::getDownloadLog)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
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 80a9bf0b3..758f8095d 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java
@@ -5,7 +5,6 @@ import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
@@ -53,16 +52,12 @@ public class ExternalPlayerFragment extends Fragment {
mFeedName = (TextView) root.findViewById(R.id.txtvAuthor);
mProgressBar = (ProgressBar) root.findViewById(R.id.episodeProgress);
- fragmentLayout.setOnClickListener(new OnClickListener() {
+ fragmentLayout.setOnClickListener(v -> {
+ Log.d(TAG, "layoutInfo was clicked");
- @Override
- public void onClick(View v) {
- Log.d(TAG, "layoutInfo was clicked");
-
- if (controller != null && controller.getMedia() != null) {
- startActivity(PlaybackService.getPlayerActivityIntent(
- getActivity(), controller.getMedia()));
- }
+ if (controller != null && controller.getMedia() != null) {
+ startActivity(PlaybackService.getPlayerActivityIntent(
+ getActivity(), controller.getMedia()));
}
});
return root;
@@ -72,7 +67,11 @@ public class ExternalPlayerFragment extends Fragment {
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
controller = setupPlaybackController();
- butPlay.setOnClickListener(controller.newOnPlayButtonClickListener());
+ butPlay.setOnClickListener(v -> {
+ if(controller != null) {
+ controller.playPause();
+ }
+ });
}
private PlaybackController setupPlaybackController() {
@@ -88,7 +87,6 @@ public class ExternalPlayerFragment extends Fragment {
return butPlay;
}
-
@Override
public boolean loadMediaInfo() {
ExternalPlayerFragment fragment = ExternalPlayerFragment.this;
@@ -145,8 +143,11 @@ public class ExternalPlayerFragment extends Fragment {
}
controller = setupPlaybackController();
if (butPlay != null) {
- butPlay.setOnClickListener(controller
- .newOnPlayButtonClickListener());
+ butPlay.setOnClickListener(v -> {
+ if(controller != null) {
+ controller.playPause();
+ }
+ });
}
controller.init();
}
@@ -171,7 +172,7 @@ public class ExternalPlayerFragment extends Fragment {
.into(imgvCover);
fragmentLayout.setVisibility(View.VISIBLE);
- if (controller.isPlayingVideo()) {
+ if (controller.isPlayingVideoLocally()) {
butPlay.setVisibility(View.GONE);
} else {
butPlay.setVisibility(View.VISIBLE);
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 c1c1aab6c..55d28cadb 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java
@@ -27,8 +27,8 @@ import android.webkit.WebViewClient;
import android.widget.Toast;
import de.danoeh.antennapod.R;
-import de.danoeh.antennapod.activity.AudioplayerActivity;
-import de.danoeh.antennapod.activity.AudioplayerActivity.AudioplayerContentFragment;
+import de.danoeh.antennapod.activity.MediaplayerInfoActivity;
+import de.danoeh.antennapod.activity.MediaplayerInfoActivity.MediaplayerInfoContentFragment;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBReader;
@@ -47,7 +47,7 @@ import rx.schedulers.Schedulers;
/**
* Displays the description of a Playable object in a Webview.
*/
-public class ItemDescriptionFragment extends Fragment implements AudioplayerContentFragment {
+public class ItemDescriptionFragment extends Fragment implements MediaplayerInfoContentFragment {
private static final String TAG = "ItemDescriptionFragment";
@@ -111,7 +111,7 @@ public class ItemDescriptionFragment extends Fragment implements AudioplayerCont
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Log.d(TAG, "Creating view");
- webvDescription = new WebView(getActivity());
+ webvDescription = new WebView(getActivity().getApplicationContext());
if (Build.VERSION.SDK_INT >= 11) {
webvDescription.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
@@ -148,7 +148,7 @@ public class ItemDescriptionFragment extends Fragment implements AudioplayerCont
super.onPageFinished(view, url);
Log.d(TAG, "Page finished");
// Restoring the scroll position might not always work
- view.postDelayed(() -> restoreFromPreference(), 50);
+ view.postDelayed(ItemDescriptionFragment.this::restoreFromPreference, 50);
}
});
@@ -318,8 +318,7 @@ public class ItemDescriptionFragment extends Fragment implements AudioplayerCont
private String loadData() {
Timeline timeline = new Timeline(getActivity(), shownotesProvider);
- String data = timeline.processShownotes(highlightTimecodes);
- return data;
+ return timeline.processShownotes(highlightTimecodes);
}
@Override
@@ -372,8 +371,8 @@ public class ItemDescriptionFragment extends Fragment implements AudioplayerCont
private void onTimecodeLinkSelected(String link) {
int time = Timeline.getTimecodeLinkTime(link);
- if (getActivity() != null && getActivity() instanceof AudioplayerActivity) {
- PlaybackController pc = ((AudioplayerActivity) getActivity()).getPlaybackController();
+ if (getActivity() != null && getActivity() instanceof MediaplayerInfoActivity) {
+ PlaybackController pc = ((MediaplayerInfoActivity) getActivity()).getPlaybackController();
if (pc != null) {
pc.seekTo(time);
}
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 1382929af..e721af47d 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemFragment.java
@@ -1,6 +1,5 @@
package de.danoeh.antennapod.fragment;
-import android.annotation.TargetApi;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
@@ -10,6 +9,8 @@ import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
+import android.support.v4.view.GestureDetectorCompat;
+import android.text.Layout;
import android.text.TextUtils;
import android.util.Log;
import android.view.ContextMenu;
@@ -17,12 +18,14 @@ import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
@@ -36,6 +39,7 @@ import org.apache.commons.lang3.ArrayUtils;
import java.util.List;
import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.activity.CastEnabledActivity;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
import de.danoeh.antennapod.core.event.DownloadEvent;
@@ -57,10 +61,11 @@ 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.IntentUtils;
-import de.danoeh.antennapod.core.util.LongList;
import de.danoeh.antennapod.core.util.ShareUtils;
import de.danoeh.antennapod.core.util.playback.Timeline;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
+import de.danoeh.antennapod.view.OnSwipeGesture;
+import de.danoeh.antennapod.view.SwipeGestureDetector;
import de.greenrobot.event.EventBus;
import rx.Observable;
import rx.Subscription;
@@ -70,13 +75,17 @@ import rx.schedulers.Schedulers;
/**
* Displays information about a FeedItem and actions.
*/
-public class ItemFragment extends Fragment {
+public class ItemFragment extends Fragment implements OnSwipeGesture {
private static final String TAG = "ItemFragment";
private static final int EVENTS = EventDistributor.UNREAD_ITEMS_UPDATE;
- private static final String ARG_FEEDITEM = "feeditem";
+ private static final String ARG_FEEDITEMS = "feeditems";
+ private static final String ARG_FEEDITEM_POS = "feeditem_pos";
+
+ private GestureDetectorCompat headerGestureDetector;
+ private GestureDetectorCompat webviewGestureDetector;
/**
* Creates a new instance of an ItemFragment
@@ -85,23 +94,35 @@ public class ItemFragment extends Fragment {
* @return The ItemFragment instance
*/
public static ItemFragment newInstance(long feeditem) {
+ return newInstance(new long[] { feeditem }, 0);
+ }
+
+ /**
+ * Creates a new instance of an ItemFragment
+ *
+ * @param feeditems The IDs of the FeedItems that belong to the same list
+ * @param feedItemPos The position of the FeedItem that is currently shown
+ * @return The ItemFragment instance
+ */
+ public static ItemFragment newInstance(long[] feeditems, int feedItemPos) {
ItemFragment fragment = new ItemFragment();
Bundle args = new Bundle();
- args.putLong(ARG_FEEDITEM, feeditem);
+ args.putLongArray(ARG_FEEDITEMS, feeditems);
+ args.putInt(ARG_FEEDITEM_POS, feedItemPos);
fragment.setArguments(args);
return fragment;
}
private boolean itemsLoaded = false;
- private long itemID;
+ private long[] feedItems;
+ private int feedItemPos;
private FeedItem item;
- private LongList queue;
- private LongList favorites;
private String webviewData;
private List<Downloader> downloaderList;
private ViewGroup root;
private WebView webvDescription;
+ private TextView txtvPodcast;
private TextView txtvTitle;
private TextView txtvDuration;
private TextView txtvPublished;
@@ -125,17 +146,37 @@ public class ItemFragment extends Fragment {
setRetainInstance(true);
setHasOptionsMenu(true);
- itemID = getArguments().getLong(ARG_FEEDITEM, -1);
+ feedItems = getArguments().getLongArray(ARG_FEEDITEMS);
+ feedItemPos = getArguments().getInt(ARG_FEEDITEM_POS);
+
+ headerGestureDetector = new GestureDetectorCompat(getActivity(), new SwipeGestureDetector(this));
+ webviewGestureDetector = new GestureDetectorCompat(getActivity(), new SwipeGestureDetector(this) {
+ // necessary for the longclick context menu to work properly
+ @Override
+ public boolean onDown(MotionEvent e) {
+ return false;
+ }
+ });
}
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View layout = inflater.inflate(R.layout.feeditem_fragment, container, false);
root = (ViewGroup) layout.findViewById(R.id.content_root);
+
+ LinearLayout header = (LinearLayout) root.findViewById(R.id.header);
+ if(feedItems.length > 0) {
+ header.setOnTouchListener((v, event) -> headerGestureDetector.onTouchEvent(event));
+ }
+
+ txtvPodcast = (TextView) layout.findViewById(R.id.txtvPodcast);
+ txtvPodcast.setOnClickListener(v -> openPodcast());
txtvTitle = (TextView) layout.findViewById(R.id.txtvTitle);
+ if(Build.VERSION.SDK_INT >= 23) {
+ txtvTitle.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_FULL);
+ }
txtvDuration = (TextView) layout.findViewById(R.id.txtvDuration);
txtvPublished = (TextView) layout.findViewById(R.id.txtvPublished);
if (Build.VERSION.SDK_INT >= 14) { // ellipsize is causing problems on old versions, see #448
@@ -153,7 +194,10 @@ public class ItemFragment extends Fragment {
webvDescription.getSettings().setLayoutAlgorithm(
WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
webvDescription.getSettings().setLoadWithOverviewMode(true);
- webvDescription.setOnLongClickListener(webViewLongClickListener);
+ if(feedItems.length > 0) {
+ webvDescription.setOnLongClickListener(webViewLongClickListener);
+ }
+ webvDescription.setOnTouchListener((v, event) -> webviewGestureDetector.onTouchEvent(event));
webvDescription.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
@@ -167,6 +211,7 @@ public class ItemFragment extends Fragment {
registerForContextMenu(webvDescription);
imgvCover = (ImageView) layout.findViewById(R.id.imgvCover);
+ imgvCover.setOnClickListener(v -> openPodcast());
progbarDownload = (ProgressBar) layout.findViewById(R.id.progbarDownload);
progbarLoading = (ProgressBar) layout.findViewById(R.id.progbarLoading);
butAction1 = (IconButton) layout.findViewById(R.id.butAction1);
@@ -219,6 +264,7 @@ public class ItemFragment extends Fragment {
EventDistributor.getInstance().register(contentUpdate);
EventBus.getDefault().registerSticky(this);
if(itemsLoaded) {
+ progbarLoading.setVisibility(View.GONE);
updateAppearance();
}
}
@@ -243,29 +289,55 @@ public class ItemFragment extends Fragment {
}
@Override
+ public boolean onSwipeLeftToRight() {
+ Log.d(TAG, "onSwipeLeftToRight()");
+ feedItemPos = feedItemPos - 1;
+ if(feedItemPos < 0) {
+ feedItemPos = feedItems.length - 1;
+ }
+ load();
+ return true;
+ }
+
+ @Override
+ public boolean onSwipeRightToLeft() {
+ Log.d(TAG, "onSwipeRightToLeft()");
+ feedItemPos = (feedItemPos + 1) % feedItems.length;
+ load();
+ return true;
+ }
+
+ @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if(!isAdded() || item == null) {
return;
}
+ ((CastEnabledActivity) getActivity()).requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS);
inflater.inflate(R.menu.feeditem_options, menu);
popupMenu = menu;
if (item.hasMedia()) {
- FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item, true, queue, favorites);
+ FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item, true, null);
} else {
// these are already available via button1 and button2
- FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item, true, queue, favorites,
+ FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item, true, null,
R.id.mark_read_item, R.id.visit_website_item);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
- try {
- return FeedItemMenuHandler.onMenuItemClicked(getActivity(), menuItem.getItemId(), item);
- } catch (DownloadRequestException e) {
- e.printStackTrace();
- Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
- return true;
+ switch(menuItem.getItemId()) {
+ case R.id.open_podcast:
+ 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;
+ }
}
}
@@ -281,10 +353,8 @@ public class ItemFragment extends Fragment {
private void onFragmentLoaded() {
- progbarLoading.setVisibility(View.INVISIBLE);
if (webviewData != null) {
- webvDescription.loadDataWithBaseURL(null, webviewData, "text/html",
- "utf-8", "about:blank");
+ webvDescription.loadDataWithBaseURL(null, webviewData, "text/html", "utf-8", "about:blank");
}
updateAppearance();
}
@@ -295,6 +365,7 @@ public class ItemFragment extends Fragment {
return;
}
getActivity().supportInvalidateOptionsMenu();
+ txtvPodcast.setText(item.getFeed().getTitle());
txtvTitle.setText(item.getTitle());
if (item.getPubDate() != null) {
@@ -452,22 +523,15 @@ public class ItemFragment extends Fragment {
}
}
- public void onEventMainThread(QueueEvent event) {
- if(event.contains(itemID)) {
- load();
- }
- }
-
- public void onEventMainThread(FavoritesEvent event) {
- if(event.item.getId() == itemID) {
- load();
- }
+ private void openPodcast() {
+ Fragment fragment = ItemlistFragment.newInstance(item.getFeedId());
+ ((MainActivity)getActivity()).loadChildFragment(fragment);
}
public void onEventMainThread(FeedItemEvent event) {
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
for(FeedItem item : event.items) {
- if(itemID == item.getId()) {
+ if(feedItems[feedItemPos] == item.getId()) {
load();
return;
}
@@ -503,43 +567,27 @@ public class ItemFragment extends Fragment {
if(subscription != null) {
subscription.unsubscribe();
}
- subscription = Observable.fromCallable(() -> loadInBackground())
+ progbarLoading.setVisibility(View.VISIBLE);
+ subscription = Observable.fromCallable(this::loadInBackground)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
- item = (FeedItem) result[0];
- queue = (LongList) result[1];
- favorites = (LongList) result[2];
- if (!itemsLoaded) {
- itemsLoaded = true;
- onFragmentLoaded();
- } else {
- updateAppearance();
- }
+ progbarLoading.setVisibility(View.GONE);
+ item = result;
+ itemsLoaded = true;
+ onFragmentLoaded();
}, error -> {
Log.e(TAG, Log.getStackTraceString(error));
});
}
- private Object[] loadInBackground() {
- FeedItem feedItem = DBReader.getFeedItem(itemID);
+ private FeedItem loadInBackground() {
+ FeedItem feedItem = DBReader.getFeedItem(feedItems[feedItemPos]);
if (feedItem != null) {
Timeline t = new Timeline(getActivity(), feedItem);
webviewData = t.processShownotes(false);
}
- LongList queue;
- if(feedItem.isTagged(FeedItem.TAG_QUEUE)) {
- queue = LongList.of(feedItem.getId());
- } else {
- queue = new LongList(0);
- }
- LongList favorites;
- if(feedItem.isTagged(FeedItem.TAG_FAVORITE)) {
- favorites = LongList.of(feedItem.getId());
- } else {
- favorites = new LongList(0);
- }
- return new Object[] { feedItem, queue, favorites };
+ return feedItem;
}
}
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 303d273bc..3194d7cab 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java
@@ -47,9 +47,7 @@ import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloaderUpdate;
-import de.danoeh.antennapod.core.event.FavoritesEvent;
import de.danoeh.antennapod.core.event.FeedItemEvent;
-import de.danoeh.antennapod.core.event.QueueEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.feed.FeedEvent;
@@ -66,7 +64,6 @@ import de.danoeh.antennapod.core.storage.DBTasks;
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;
import de.danoeh.antennapod.core.util.gui.MoreContentListFooterUtil;
import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment;
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
@@ -98,8 +95,6 @@ public class ItemlistFragment extends ListFragment {
private long feedID;
private Feed feed;
- private LongList queuedItemsIds;
- private LongList favoritedItemsId;
private boolean itemsLoaded = false;
private boolean viewsCreated = false;
@@ -185,11 +180,7 @@ public class ItemlistFragment extends ListFragment {
private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker = new MenuItemUtils.UpdateRefreshMenuItemChecker() {
@Override
public boolean isRefreshing() {
- if (feed != null && DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFile(feed)) {
- return true;
- } else {
- return false;
- }
+ return feed != null && DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFile(feed);
}
};
@@ -325,8 +316,7 @@ public class ItemlistFragment extends ListFragment {
contextMenu = menu;
lastMenuInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
- FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, true, queuedItemsIds,
- favoritedItemsId);
+ FeedItemMenuHandler.onPrepareMenu(contextMenuInterface, item, true, null);
}
@Override
@@ -378,22 +368,11 @@ public class ItemlistFragment extends ListFragment {
if(adapter == null) {
return;
}
- FeedItem selection = adapter.getItem(position - l.getHeaderViewsCount());
- if (selection != null) {
- MainActivity activity = (MainActivity) getActivity();
- activity.loadChildFragment(ItemFragment.newInstance(selection.getId()));
- activity.getSupportActionBar().setTitle(feed.getTitle());
- }
- }
-
- public void onEvent(QueueEvent event) {
- Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
- loadItems();
- }
-
- public void onEvent(FavoritesEvent event) {
- Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
- loadItems();
+ position -= l.getHeaderViewsCount();
+ MainActivity activity = (MainActivity) getActivity();
+ long[] ids = FeedItemUtil.getIds(feed.getItems());
+ activity.loadChildFragment(ItemFragment.newInstance(ids, position));
+ activity.getSupportActionBar().setTitle(feed.getTitle());
}
public void onEvent(FeedEvent event) {
@@ -405,7 +384,6 @@ public class ItemlistFragment extends ListFragment {
public void onEventMainThread(FeedItemEvent event) {
Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
- boolean queueChanged = false;
if(feed == null || feed.getItems() == null || adapter == null) {
return;
}
@@ -605,11 +583,6 @@ public class ItemlistFragment extends ListFragment {
}
@Override
- public boolean isInQueue(FeedItem item) {
- return (queuedItemsIds != null) && queuedItemsIds.contains(item.getId());
- }
-
- @Override
public int getItemDownloadProgressPercent(FeedItem item) {
if (downloaderList != null) {
for (Downloader downloader : downloaderList) {
@@ -628,14 +601,12 @@ public class ItemlistFragment extends ListFragment {
if(subscription != null) {
subscription.unsubscribe();
}
- subscription = Observable.fromCallable(() -> loadData())
+ subscription = Observable.fromCallable(this::loadData)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
if (result != null) {
- feed = (Feed) result[0];
- queuedItemsIds = (LongList) result[1];
- favoritedItemsId = (LongList) result[2];
+ feed = result;
itemsLoaded = true;
if (viewsCreated) {
onFragmentLoaded();
@@ -646,15 +617,14 @@ public class ItemlistFragment extends ListFragment {
});
}
- private Object[] loadData() {
+ private Feed loadData() {
Feed feed = DBReader.getFeed(feedID);
+ DBReader.loadAdditionalFeedItemListData(feed.getItems());
if(feed != null && feed.getItemFilter() != null) {
FeedItemFilter filter = feed.getItemFilter();
feed.setItems(filter.filter(feed.getItems()));
}
- LongList queuedItemsIds = DBReader.getQueueIDList();
- LongList favoritedItemsId = DBReader.getFavoriteIDList();
- return new Object[] { feed, queuedItemsIds, favoritedItemsId };
+ return feed;
}
}
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 b996e1cb3..7ef070f21 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/NewEpisodesFragment.java
@@ -14,12 +14,13 @@ import java.util.List;
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.adapter.AllEpisodesRecycleAdapter;
-import de.danoeh.antennapod.core.event.QueueEvent;
+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;
/**
@@ -39,17 +40,27 @@ public class NewEpisodesFragment extends AllEpisodesFragment {
@Override
protected String getPrefName() { return PREF_NAME; }
- public void onEvent(QueueEvent event) {
- Log.d(TAG, "onEvent() called with: " + "event = [" + event + "]");
- loadItems();
- }
-
@Override
protected void resetViewState() {
super.resetViewState();
}
@Override
+ public void onEventMainThread(FeedItemEvent event) {
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ if(episodes == null) {
+ return;
+ }
+ for(FeedItem item : event.items) {
+ int pos = FeedItemUtil.indexOfItemWithId(episodes, item.getId());
+ if(pos >= 0 && item.isTagged(FeedItem.TAG_QUEUE)) {
+ episodes.remove(pos);
+ listAdapter.notifyItemRemoved(pos);
+ }
+ }
+ }
+
+ @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = super.onCreateViewHelper(inflater, container, savedInstanceState,
R.layout.all_episodes_fragment);
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 c5b77fae2..49c68c732 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/PlaybackHistoryFragment.java
@@ -4,7 +4,6 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
-import android.support.v4.util.Pair;
import android.support.v4.view.MenuItemCompat;
import android.util.Log;
import android.view.Menu;
@@ -21,14 +20,14 @@ import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
import de.danoeh.antennapod.adapter.FeedItemlistAdapter;
import de.danoeh.antennapod.core.event.DownloadEvent;
import de.danoeh.antennapod.core.event.DownloaderUpdate;
-import de.danoeh.antennapod.core.event.QueueEvent;
+import de.danoeh.antennapod.core.event.FeedItemEvent;
import de.danoeh.antennapod.core.feed.EventDistributor;
import de.danoeh.antennapod.core.feed.FeedItem;
import de.danoeh.antennapod.core.feed.FeedMedia;
import de.danoeh.antennapod.core.service.download.Downloader;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBWriter;
-import de.danoeh.antennapod.core.util.LongList;
+import de.danoeh.antennapod.core.util.FeedItemUtil;
import de.greenrobot.event.EventBus;
import rx.Observable;
import rx.Subscription;
@@ -43,7 +42,6 @@ public class PlaybackHistoryFragment extends ListFragment {
EventDistributor.PLAYER_STATUS_UPDATE;
private List<FeedItem> playbackHistory;
- private LongList queue;
private FeedItemlistAdapter adapter;
private boolean itemsLoaded = false;
@@ -140,10 +138,9 @@ public class PlaybackHistoryFragment extends ListFragment {
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
- FeedItem item = adapter.getItem(position - l.getHeaderViewsCount());
- if (item != null) {
- ((MainActivity) getActivity()).loadChildFragment(ItemFragment.newInstance(item.getId()));
- }
+ position -= l.getHeaderViewsCount();
+ long[] ids = FeedItemUtil.getIds(playbackHistory);
+ ((MainActivity) getActivity()).loadChildFragment(ItemFragment.newInstance(ids, position));
}
@Override
@@ -187,9 +184,18 @@ public class PlaybackHistoryFragment extends ListFragment {
}
}
- public void onEvent(QueueEvent event) {
- Log.d(TAG, "onEvent(" + event + ")");
- loadItems();
+ public void onEventMainThread(FeedItemEvent event) {
+ Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]");
+ if(playbackHistory == null) {
+ return;
+ }
+ for(FeedItem item : event.items) {
+ int pos = FeedItemUtil.indexOfItemWithId(playbackHistory, item.getId());
+ if(pos >= 0) {
+ loadItems();
+ return;
+ }
+ }
}
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@@ -218,10 +224,6 @@ public class PlaybackHistoryFragment extends ListFragment {
}
private FeedItemlistAdapter.ItemAccess itemAccess = new FeedItemlistAdapter.ItemAccess() {
- @Override
- public boolean isInQueue(FeedItem item) {
- return (queue != null) ? queue.contains(item.getId()) : false;
- }
@Override
public int getItemDownloadProgressPercent(FeedItem item) {
@@ -255,13 +257,12 @@ public class PlaybackHistoryFragment extends ListFragment {
if(subscription != null) {
subscription.unsubscribe();
}
- subscription = Observable.fromCallable(() -> loadData())
+ subscription = Observable.fromCallable(this::loadData)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
if (result != null) {
- playbackHistory = result.first;
- queue = result.second;
+ playbackHistory = result;
itemsLoaded = true;
if (viewsCreated) {
onFragmentLoaded();
@@ -272,11 +273,10 @@ public class PlaybackHistoryFragment extends ListFragment {
});
}
- private Pair<List<FeedItem>, LongList> loadData() {
+ private List<FeedItem> loadData() {
List<FeedItem> history = DBReader.getPlaybackHistory();
- LongList queue = DBReader.getQueueIDList();
DBReader.loadAdditionalFeedItemListData(history);
- return Pair.create(history, queue);
+ return history;
}
}
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 e5bb1d895..08e681c99 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/QueueFragment.java
@@ -230,9 +230,8 @@ public class QueueFragment extends Fragment {
resetViewState();
}
- private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker = () -> {
- return DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
- };
+ private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker =
+ () -> DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
@@ -410,12 +409,12 @@ public class QueueFragment extends Fragment {
Log.d(TAG, "remove(" + position + ")");
final FeedItem item = queue.get(position);
final boolean isRead = item.isPlayed();
- DBWriter.markItemPlayed(FeedItem.PLAYED, item.getId());
+ DBWriter.markItemPlayed(FeedItem.PLAYED, false, item.getId());
DBWriter.removeQueueItem(getActivity(), item, true);
Snackbar snackbar = Snackbar.make(root, getString(R.string.marked_as_read_label), Snackbar.LENGTH_LONG);
snackbar.setAction(getString(R.string.undo), v -> {
DBWriter.addQueueItemAt(getActivity(), item.getId(), position, false);
- if(false == isRead) {
+ if(!isRead) {
DBWriter.markItemPlayed(FeedItem.UNPLAYED, item.getId());
}
});
@@ -424,12 +423,12 @@ public class QueueFragment extends Fragment {
@Override
public boolean isLongPressDragEnabled() {
- return false == UserPreferences.isQueueLocked();
+ return !UserPreferences.isQueueLocked();
}
@Override
public boolean isItemViewSwipeEnabled() {
- return false == UserPreferences.isQueueLocked();
+ return !UserPreferences.isQueueLocked();
}
@Override
@@ -569,20 +568,6 @@ public class QueueFragment extends Fragment {
public LongList getQueueIds() {
return queue != null ? LongList.of(FeedItemUtil.getIds(queue)) : new LongList(0);
}
-
- @Override
- public LongList getFavoritesIds() {
- LongList favoritesIds = new LongList();
- if(queue == null) {
- return favoritesIds;
- }
- for(FeedItem item : queue) {
- if(item.isTagged(FeedItem.TAG_FAVORITE)) {
- favoritesIds.add(item.getId());
- }
- }
- return favoritesIds;
- }
};
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@@ -608,7 +593,7 @@ public class QueueFragment extends Fragment {
txtvEmpty.setVisibility(View.GONE);
progLoading.setVisibility(View.VISIBLE);
}
- subscription = Observable.fromCallable(() -> DBReader.getQueue())
+ subscription = Observable.fromCallable(DBReader::getQueue)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(items -> {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
index dbd18163c..510909379 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/SearchFragment.java
@@ -208,7 +208,7 @@ public class SearchFragment extends ListFragment {
if (viewCreated && !itemsLoaded) {
setListShown(false);
}
- subscription = Observable.fromCallable(() -> performSearch())
+ subscription = Observable.fromCallable(this::performSearch)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
new file mode 100644
index 000000000..a314419ac
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java
@@ -0,0 +1,238 @@
+package de.danoeh.antennapod.fragment;
+
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.util.Log;
+import android.view.ContextMenu;
+import android.view.LayoutInflater;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.GridView;
+
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.activity.MainActivity;
+import de.danoeh.antennapod.adapter.SubscriptionsAdapter;
+import de.danoeh.antennapod.core.asynctask.FeedRemover;
+import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
+import de.danoeh.antennapod.core.feed.EventDistributor;
+import de.danoeh.antennapod.core.feed.Feed;
+import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
+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 rx.Observable;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.schedulers.Schedulers;
+
+/**
+ * Fragment for displaying feed subscriptions
+ */
+public class SubscriptionFragment extends Fragment {
+
+ public static final String TAG = "SubscriptionFragment";
+
+ private static final int EVENTS = EventDistributor.FEED_LIST_UPDATE
+ | EventDistributor.UNREAD_ITEMS_UPDATE;
+
+ private GridView subscriptionGridLayout;
+ private DBReader.NavDrawerData navDrawerData;
+ private SubscriptionsAdapter subscriptionAdapter;
+
+ private int mPosition = -1;
+
+
+ public SubscriptionFragment() {
+ }
+
+ @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);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View root = inflater.inflate(R.layout.fragment_subscriptions, container, false);
+ subscriptionGridLayout = (GridView) root.findViewById(R.id.subscriptions_grid);
+ registerForContextMenu(subscriptionGridLayout);
+ return root;
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ subscriptionAdapter = new SubscriptionsAdapter((MainActivity)getActivity(), itemAccess);
+
+ subscriptionGridLayout.setAdapter(subscriptionAdapter);
+
+ loadSubscriptions();
+
+ subscriptionGridLayout.setOnItemClickListener(subscriptionAdapter);
+
+ if (getActivity() instanceof MainActivity) {
+ ((MainActivity) getActivity()).getSupportActionBar().setTitle(R.string.subscriptions_label);
+ }
+
+ EventDistributor.getInstance().register(contentUpdate);
+ }
+
+ private void loadSubscriptions() {
+ Observable.fromCallable(() -> DBReader.getNavDrawerData())
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(result -> {
+ navDrawerData = result;
+ subscriptionAdapter.notifyDataSetChanged();
+ }, error -> {
+ Log.e(TAG, Log.getStackTraceString(error));
+ });
+ }
+
+ @Override
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, v, menuInfo);
+ AdapterView.AdapterContextMenuInfo adapterInfo = (AdapterView.AdapterContextMenuInfo) menuInfo;
+ int position = adapterInfo.position;
+
+ Object selectedObject = subscriptionAdapter.getItem(position);
+ if (selectedObject.equals(SubscriptionsAdapter.ADD_ITEM_OBJ)) {
+ mPosition = position;
+ return;
+ }
+
+ Feed feed = (Feed)selectedObject;
+
+ MenuInflater inflater = getActivity().getMenuInflater();
+ inflater.inflate(R.menu.nav_feed_context, menu);
+
+ menu.setHeaderTitle(feed.getTitle());
+
+ mPosition = position;
+ }
+
+ @Override
+ public boolean onContextItemSelected(MenuItem item) {
+
+ final int position = mPosition;
+ mPosition = -1; // reset
+ if(position < 0) {
+ return false;
+ }
+
+ Object selectedObject = subscriptionAdapter.getItem(position);
+ if (selectedObject.equals(SubscriptionsAdapter.ADD_ITEM_OBJ)) {
+ // this is the add object, do nothing
+ return false;
+ }
+
+ 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));
+ });
+ 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));
+ });
+ return true;
+ case R.id.remove_item:
+ final FeedRemover remover = new FeedRemover(getContext(), feed) {
+ @Override
+ protected void onPostExecute(Void result) {
+ super.onPostExecute(result);
+ loadSubscriptions();
+ }
+ };
+ ConfirmationDialog conDialog = new ConfirmationDialog(getContext(),
+ R.string.remove_feed_label,
+ R.string.feed_delete_confirmation_msg) {
+ @Override
+ public void onConfirmButtonPressed(
+ DialogInterface dialog) {
+ dialog.dismiss();
+ long mediaId = PlaybackPreferences.getCurrentlyPlayingFeedMediaId();
+ if (mediaId > 0 &&
+ FeedItemUtil.indexOfItemWithMediaId(feed.getItems(), mediaId) >= 0) {
+ Log.d(TAG, "Currently playing episode is about to be deleted, skipping");
+ remover.skipOnCompletion = true;
+ int playerStatus = PlaybackPreferences.getCurrentPlayerStatus();
+ if(playerStatus == PlaybackPreferences.PLAYER_STATUS_PLAYING) {
+ getActivity().sendBroadcast(new Intent(
+ PlaybackService.ACTION_PAUSE_PLAY_CURRENT_EPISODE));
+ }
+ }
+ remover.executeAsync();
+ }
+ };
+ conDialog.createNewDialog().show();
+ return true;
+ default:
+ return super.onContextItemSelected(item);
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ loadSubscriptions();
+ }
+
+ private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
+ @Override
+ public void update(EventDistributor eventDistributor, Integer arg) {
+ if ((EVENTS & arg) != 0) {
+ Log.d(TAG, "Received contentUpdate Intent.");
+ loadSubscriptions();
+ }
+ }
+ };
+
+ private SubscriptionsAdapter.ItemAccess itemAccess = new SubscriptionsAdapter.ItemAccess() {
+ @Override
+ public int getCount() {
+ if (navDrawerData != null) {
+ return navDrawerData.feeds.size();
+ } else {
+ return 0;
+ }
+ }
+
+ @Override
+ public Feed getItem(int position) {
+ if (navDrawerData != null && 0 <= position && position < navDrawerData.feeds.size()) {
+ return navDrawerData.feeds.get(position);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public int getFeedCounter(long feedId) {
+ return navDrawerData != null ? navDrawerData.feedCounters.get(feedId) : 0;
+ }
+ };
+}
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 204f36956..15e9c9943 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
@@ -14,7 +14,6 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.AdapterView;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ProgressBar;
@@ -84,18 +83,9 @@ public abstract class PodcastListFragment extends Fragment {
txtvError = (TextView) root.findViewById(R.id.txtvError);
butRetry = (Button) root.findViewById(R.id.butRetry);
- gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- onPodcastSelected((GpodnetPodcast) gridView.getAdapter().getItem(position));
- }
- });
- butRetry.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- loadData();
- }
- });
+ gridView.setOnItemClickListener((parent, view, position, id) ->
+ onPodcastSelected((GpodnetPodcast) gridView.getAdapter().getItem(position)));
+ butRetry.setOnClickListener(v -> loadData());
loadData();
return root;
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SuggestionListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SuggestionListFragment.java
index 133bb0281..1b1b61efb 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SuggestionListFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/SuggestionListFragment.java
@@ -1,13 +1,13 @@
package de.danoeh.antennapod.fragment.gpodnet;
+import java.util.Collections;
+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 de.danoeh.antennapod.core.preferences.GpodnetPreferences;
-import java.util.ArrayList;
-import java.util.List;
-
/**
* Displays suggestions from gpodder.net
*/
@@ -20,7 +20,7 @@ public class SuggestionListFragment extends PodcastListFragment {
service.authenticate(GpodnetPreferences.getUsername(), GpodnetPreferences.getPassword());
return service.getSuggestions(SUGGESTIONS_COUNT);
} else {
- return new ArrayList<GpodnetPodcast>();
+ return Collections.emptyList();
}
}
}
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 338f02e61..d2c7f32dd 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
@@ -11,7 +11,6 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
-import android.widget.AdapterView;
import android.widget.TextView;
import java.util.List;
@@ -65,13 +64,10 @@ public class TagListFragment extends ListFragment {
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
- getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- GpodnetTag tag = (GpodnetTag) getListAdapter().getItem(position);
- MainActivity activity = (MainActivity) getActivity();
- activity.loadChildFragment(TagFragment.newInstance(tag));
- }
+ getListView().setOnItemClickListener((parent, view1, position, id) -> {
+ GpodnetTag tag = (GpodnetTag) getListAdapter().getItem(position);
+ MainActivity activity = (MainActivity) getActivity();
+ activity.loadChildFragment(TagFragment.newInstance(tag));
});
startLoadTask();
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 58fe8afbf..b80213459 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedItemMenuHandler.java
@@ -3,6 +3,7 @@ package de.danoeh.antennapod.menuhandler;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.Toast;
@@ -41,7 +42,7 @@ public class FeedItemMenuHandler {
* menu-object and call setVisibility(visibility) on the returned
* MenuItem object.
*/
- abstract void setItemVisibility(int id, boolean visible);
+ void setItemVisibility(int id, boolean visible);
}
/**
@@ -54,14 +55,14 @@ public class FeedItemMenuHandler {
* @param showExtendedMenu True if MenuItems that let the user share information about
* the FeedItem and visit its website should be set visible. This
* parameter should be set to false if the menu space is limited.
- * @param queueAccess Used for testing if the queue contains the selected item
+ * @param queueAccess Used for testing if the queue contains the selected item; only used for
+ * move to top/bottom in the queue
* @return Returns true if selectedItem is not null.
*/
public static boolean onPrepareMenu(MenuInterface mi,
FeedItem selectedItem,
boolean showExtendedMenu,
- LongList queueAccess,
- LongList favorites) {
+ @Nullable LongList queueAccess) {
if (selectedItem == null) {
return false;
}
@@ -72,10 +73,7 @@ public class FeedItemMenuHandler {
mi.setItemVisibility(R.id.skip_episode_item, false);
}
- boolean isInQueue = false;
- if(queueAccess != null) {
- isInQueue = queueAccess.contains(selectedItem.getId());
- }
+ boolean isInQueue = selectedItem.isTagged(FeedItem.TAG_QUEUE);
if(queueAccess == null || queueAccess.size() == 0 || queueAccess.get(0) == selectedItem.getId()) {
mi.setItemVisibility(R.id.move_to_top_item, false);
}
@@ -98,7 +96,7 @@ public class FeedItemMenuHandler {
mi.setItemVisibility(R.id.share_download_url_item, false);
mi.setItemVisibility(R.id.share_download_url_with_position_item, false);
}
- if(false == hasMedia || selectedItem.getMedia().getPosition() <= 0) {
+ if(!hasMedia || selectedItem.getMedia().getPosition() <= 0) {
mi.setItemVisibility(R.id.share_link_with_position_item, false);
mi.setItemVisibility(R.id.share_download_url_with_position_item, false);
}
@@ -113,7 +111,7 @@ public class FeedItemMenuHandler {
mi.setItemVisibility(R.id.reset_position, false);
}
- if(false == UserPreferences.isEnableAutodownload()) {
+ if(!UserPreferences.isEnableAutodownload()) {
mi.setItemVisibility(R.id.activate_auto_download, false);
mi.setItemVisibility(R.id.deactivate_auto_download, false);
} else if(selectedItem.getAutoDownload()) {
@@ -126,7 +124,7 @@ public class FeedItemMenuHandler {
mi.setItemVisibility(R.id.support_item, false);
}
- boolean isFavorite = favorites != null && favorites.contains(selectedItem.getId());
+ boolean isFavorite = selectedItem.isTagged(FeedItem.TAG_FAVORITE);
mi.setItemVisibility(R.id.add_to_favorites_item, !isFavorite);
mi.setItemVisibility(R.id.remove_from_favorites_item, isFavorite);
@@ -144,9 +142,8 @@ public class FeedItemMenuHandler {
FeedItem selectedItem,
boolean showExtendedMenu,
LongList queueAccess,
- LongList favorites,
int... excludeIds) {
- boolean rc = onPrepareMenu(mi, selectedItem, showExtendedMenu, queueAccess, favorites);
+ boolean rc = onPrepareMenu(mi, selectedItem, showExtendedMenu, queueAccess);
if (rc && excludeIds != null) {
for (int id : excludeIds) {
mi.setItemVisibility(id, false);
@@ -224,7 +221,7 @@ public class FeedItemMenuHandler {
context.startActivity(intent);
} else {
Toast.makeText(context, context.getString(R.string.download_error_malformed_url),
- Toast.LENGTH_SHORT);
+ Toast.LENGTH_SHORT).show();
}
break;
case R.id.support_item:
diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java
index 38030f4ea..ab7d0e7c6 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/FeedMenuHandler.java
@@ -92,7 +92,7 @@ public class FeedMenuHandler {
context.startActivity(intent);
} else {
Toast.makeText(context, context.getString(R.string.download_error_malformed_url),
- Toast.LENGTH_SHORT);
+ Toast.LENGTH_SHORT).show();
}
break;
case R.id.support_item:
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 0d2ff8a75..4c28b197d 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java
@@ -39,6 +39,7 @@ public class MenuItemUtils extends de.danoeh.antennapod.core.menuhandler.MenuIte
queueLock.setTitle(de.danoeh.antennapod.R.string.lock_queue);
queueLock.setIcon(ta.getDrawable(1));
}
+ ta.recycle();
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/NavDrawerActivity.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/NavDrawerActivity.java
index 6ceaaada4..c973990c9 100644
--- a/app/src/main/java/de/danoeh/antennapod/menuhandler/NavDrawerActivity.java
+++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/NavDrawerActivity.java
@@ -5,5 +5,5 @@ package de.danoeh.antennapod.menuhandler;
*/
public interface NavDrawerActivity {
- public boolean isDrawerOpen();
+ boolean isDrawerOpen();
}
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 c563d278f..6c03dc7ae 100644
--- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
+++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java
@@ -4,6 +4,7 @@ import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.TimePickerDialog;
+import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@@ -19,6 +20,7 @@ import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
+import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
@@ -29,8 +31,11 @@ import android.text.format.DateFormat;
import android.util.Log;
import android.widget.EditText;
import android.widget.Toast;
+import android.widget.ListView;
import com.afollestad.materialdialogs.MaterialDialog;
+import com.google.android.gms.common.ConnectionResult;
+import com.google.android.gms.common.GoogleApiAvailability;
import org.apache.commons.lang3.ArrayUtils;
@@ -49,15 +54,18 @@ import de.danoeh.antennapod.activity.DirectoryChooserActivity;
import de.danoeh.antennapod.activity.MainActivity;
import de.danoeh.antennapod.activity.PreferenceActivity;
import de.danoeh.antennapod.activity.PreferenceActivityGingerbread;
+import de.danoeh.antennapod.activity.StatisticsActivity;
import de.danoeh.antennapod.asynctask.OpmlExportWorker;
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.Converter;
import de.danoeh.antennapod.core.util.StorageUtils;
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.GpodnetSetHostnameDialog;
+import de.danoeh.antennapod.dialog.ProxyDialog;
import de.danoeh.antennapod.dialog.VariableSpeedDialog;
/**
@@ -73,15 +81,21 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
public static final String PREF_FLATTR_REVOKE = "prefRevokeAccess";
public static final String PREF_AUTO_FLATTR_PREFS = "prefAutoFlattrPrefs";
public static final String PREF_OPML_EXPORT = "prefOpmlExport";
+ public static final String STATISTICS = "statistics";
public static final String PREF_ABOUT = "prefAbout";
public static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir";
public static final String AUTO_DL_PREF_SCREEN = "prefAutoDownloadSettings";
public static final String PREF_PLAYBACK_SPEED_LAUNCHER = "prefPlaybackSpeedLauncher";
public static final String PREF_GPODNET_LOGIN = "pref_gpodnet_authenticate";
public static final String PREF_GPODNET_SETLOGIN_INFORMATION = "pref_gpodnet_setlogin_information";
+ public static final String PREF_GPODNET_SYNC = "pref_gpodnet_sync";
public static final String PREF_GPODNET_LOGOUT = "pref_gpodnet_logout";
public static final String PREF_GPODNET_HOSTNAME = "pref_gpodnet_hostname";
public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify";
+ public static final String PREF_PROXY = "prefProxy";
+ public static final String PREF_KNOWN_ISSUES = "prefKnownIssues";
+ public static final String PREF_FAQ = "prefFaq";
+ public static final String PREF_SEND_CRASH_REPORT = "prefSendCrashReport";
private final PreferenceUI ui;
@@ -149,6 +163,12 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
return true;
}
);
+ ui.findPreference(PreferenceController.STATISTICS).setOnPreferenceClickListener(
+ preference -> {
+ activity.startActivity(new Intent(activity, StatisticsActivity.class));
+ return true;
+ }
+ );
ui.findPreference(PreferenceController.PREF_OPML_EXPORT).setOnPreferenceClickListener(
preference -> {
new OpmlExportWorker(activity).executeAsync();
@@ -177,20 +197,17 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
);
ui.findPreference(PreferenceController.PREF_CHOOSE_DATA_DIR)
.setOnPreferenceClickListener(
- new Preference.OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- if (Build.VERSION.SDK_INT >= 19) {
- showChooseDataFolderDialog();
- } else {
- Intent intent = new Intent(activity, DirectoryChooserActivity.class);
- activity.startActivityForResult(intent,
- DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED);
- }
- return true;
+ preference -> {
+ if (Build.VERSION.SDK_INT >= 19) {
+ showChooseDataFolderDialog();
+ } else {
+ Intent intent = new Intent(activity, DirectoryChooserActivity.class);
+ activity.startActivityForResult(intent,
+ DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED);
}
- }
- );
+ return true;
+ }
+ );
ui.findPreference(UserPreferences.PREF_THEME)
.setOnPreferenceChangeListener(
(preference, newValue) -> {
@@ -208,6 +225,12 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
return true;
});
+ ui.findPreference(UserPreferences.PREF_COMPACT_NOTIFICATION_BUTTONS)
+ .setOnPreferenceClickListener(preference -> {
+ showNotificationButtonsDialog();
+ return true;
+ });
+
ui.findPreference(UserPreferences.PREF_UPDATE_INTERVAL)
.setOnPreferenceClickListener(preference -> {
showUpdateIntervalTimePreferencesDialog();
@@ -241,7 +264,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
(preference, o) -> {
if (o instanceof String) {
try {
- int value = Integer.valueOf((String) o);
+ int value = Integer.parseInt((String) o);
if (1 <= value && value <= 50) {
setParallelDownloadsText(value);
return true;
@@ -268,7 +291,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
public void afterTextChanged(Editable s) {
if (s.length() > 0) {
try {
- int value = Integer.valueOf(s.toString());
+ int value = Integer.parseInt(s.toString());
if (value <= 0) {
ev.setText("1");
} else if (value > 50) {
@@ -309,6 +332,14 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
dialog.show();
return true;
});
+ ui.findPreference(PreferenceController.PREF_GPODNET_SYNC).
+ setOnPreferenceClickListener(preference -> {
+ GpodnetSyncService.sendSyncIntent(ui.getActivity().getApplicationContext());
+ Toast toast = Toast.makeText(ui.getActivity(), R.string.pref_gpodnet_sync_started,
+ Toast.LENGTH_SHORT);
+ toast.show();
+ return true;
+ });
ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setOnPreferenceClickListener(
preference -> {
GpodnetPreferences.logout();
@@ -343,7 +374,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
ui.findPreference(UserPreferences.PREF_IMAGE_CACHE_SIZE).setOnPreferenceChangeListener(
(preference, o) -> {
if (o instanceof String) {
- int newValue = Integer.valueOf((String) o) * 1024 * 1024;
+ 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);
@@ -356,7 +387,20 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
return false;
}
);
- ui.findPreference("prefSendCrashReport").setOnPreferenceClickListener(preference -> {
+ ui.findPreference(PREF_PROXY).setOnPreferenceClickListener(preference -> {
+ ProxyDialog dialog = new ProxyDialog(ui.getActivity());
+ dialog.createDialog().show();
+ return true;
+ });
+ ui.findPreference(PREF_KNOWN_ISSUES).setOnPreferenceClickListener(preference -> {
+ openInBrowser("https://github.com/AntennaPod/AntennaPod/labels/bug");
+ return true;
+ });
+ ui.findPreference(PREF_FAQ).setOnPreferenceClickListener(preference -> {
+ openInBrowser("http://antennapod.org/faq.html");
+ return true;
+ });
+ ui.findPreference(PREF_SEND_CRASH_REPORT).setOnPreferenceClickListener(preference -> {
Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.setType("text/plain");
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"Martin.Fietz@gmail.com"});
@@ -368,12 +412,38 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
ui.getActivity().startActivity(Intent.createChooser(emailIntent, intentTitle));
return true;
});
+ //checks whether Google Play Services is installed on the device (condition necessary for Cast support)
+ ui.findPreference(UserPreferences.PREF_CAST_ENABLED).setOnPreferenceChangeListener((preference, o) -> {
+ if (o instanceof Boolean && ((Boolean) o)) {
+ final int googlePlayServicesCheck = GoogleApiAvailability.getInstance()
+ .isGooglePlayServicesAvailable(ui.getActivity());
+ if (googlePlayServicesCheck == ConnectionResult.SUCCESS) {
+ return true;
+ } else {
+ GoogleApiAvailability.getInstance()
+ .getErrorDialog(ui.getActivity(), googlePlayServicesCheck, 0)
+ .show();
+ return false;
+ }
+ }
+ return true;
+ });
buildEpisodeCleanupPreference();
buildSmartMarkAsPlayedPreference();
buildAutodownloadSelectedNetworsPreference();
setSelectedNetworksEnabled(UserPreferences.isEnableAutodownloadWifiFilter());
}
+ private void openInBrowser(String url) {
+ try {
+ Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ ui.getActivity().startActivity(myIntent);
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(ui.getActivity(), R.string.pref_no_browser_found, Toast.LENGTH_LONG).show();
+ Log.e(TAG, Log.getStackTraceString(e));
+ }
+ }
+
public void onResume() {
checkItemVisibility();
setUpdateIntervalText();
@@ -423,7 +493,16 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
final boolean loggedIn = GpodnetPreferences.loggedIn();
ui.findPreference(PreferenceController.PREF_GPODNET_LOGIN).setEnabled(!loggedIn);
ui.findPreference(PreferenceController.PREF_GPODNET_SETLOGIN_INFORMATION).setEnabled(loggedIn);
+ ui.findPreference(PreferenceController.PREF_GPODNET_SYNC).setEnabled(loggedIn);
ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setEnabled(loggedIn);
+ if(loggedIn) {
+ String format = ui.getActivity().getString(R.string.pref_gpodnet_login_status);
+ String summary = String.format(format, GpodnetPreferences.getUsername(),
+ GpodnetPreferences.getDeviceID());
+ ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setSummary(Html.fromHtml(summary));
+ } else {
+ ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setSummary(null);
+ }
ui.findPreference(PreferenceController.PREF_GPODNET_HOSTNAME).setSummary(GpodnetPreferences.getHostname());
}
@@ -514,7 +593,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER).setEnabled(autoDownload);
setSelectedNetworksEnabled(autoDownload && UserPreferences.isEnableAutodownloadWifiFilter());
- ui.findPreference("prefSendCrashReport").setEnabled(CrashReportWriter.getFile().exists());
+ ui.findPreference(PREF_SEND_CRASH_REPORT).setEnabled(CrashReportWriter.getFile().exists());
if (Build.VERSION.SDK_INT >= 16) {
ui.findPreference(UserPreferences.PREF_SONIC).setEnabled(true);
@@ -598,7 +677,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
Preference.OnPreferenceClickListener clickListener = preference -> {
if (preference instanceof CheckBoxPreference) {
String key = preference.getKey();
- ArrayList<String> prefValuesList = new ArrayList<String>(
+ List<String> prefValuesList = new ArrayList<>(
Arrays.asList(UserPreferences
.getAutodownloadSelectedNetworks())
);
@@ -607,10 +686,10 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
Log.d(TAG, "Selected network " + key + ". New state: " + newValue);
int index = prefValuesList.indexOf(key);
- if (index >= 0 && newValue == false) {
+ if (index >= 0 && !newValue) {
// remove network
prefValuesList.remove(index);
- } else if (index < 0 && newValue == true) {
+ } else if (index < 0 && newValue) {
prefValuesList.add(key);
}
@@ -646,9 +725,9 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
if (selectedNetworks != null) {
PreferenceScreen prefScreen = (PreferenceScreen) ui.findPreference(PreferenceController.AUTO_DL_PREF_SCREEN);
- for (int i = 0; i < selectedNetworks.length; i++) {
- if (selectedNetworks[i] != null) {
- prefScreen.removePreference(selectedNetworks[i]);
+ for (CheckBoxPreference network : selectedNetworks) {
+ if (network != null) {
+ prefScreen.removePreference(network);
}
}
}
@@ -682,6 +761,52 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
builder.create().show();
}
+ private void showNotificationButtonsDialog() {
+ final Context context = ui.getActivity();
+ final List<Integer> preferredButtons = UserPreferences.getCompactNotificationButtons();
+ final String[] allButtonNames = context.getResources().getStringArray(
+ R.array.compact_notification_buttons_options);
+ boolean[] checked = new boolean[allButtonNames.length]; // booleans default to false in java
+
+ for(int i=0; i < checked.length; i++) {
+ if(preferredButtons.contains(i)) {
+ checked[i] = true;
+ }
+ }
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setTitle(String.format(context.getResources().getString(
+ R.string.pref_compact_notification_buttons_dialog_title), 2));
+ builder.setMultiChoiceItems(allButtonNames, checked, (dialog, which, isChecked) -> {
+ checked[which] = isChecked;
+
+ if (isChecked) {
+ if (preferredButtons.size() < 2) {
+ preferredButtons.add(which);
+ } else {
+ // Only allow a maximum of two selections. This is because the notification
+ // on the lock screen can only display 3 buttons, and the play/pause button
+ // is always included.
+ checked[which] = false;
+ ListView selectionView = ((AlertDialog) dialog).getListView();
+ selectionView.setItemChecked(which, false);
+ Snackbar.make(
+ selectionView,
+ String.format(context.getResources().getString(
+ R.string.pref_compact_notification_buttons_dialog_error), 2),
+ Snackbar.LENGTH_SHORT).show();
+ }
+ } else {
+ preferredButtons.remove((Integer) which);
+ }
+ });
+ builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
+ UserPreferences.setCompactNotificationButtons(preferredButtons);
+ });
+ builder.setNegativeButton(R.string.cancel_label, null);
+ builder.create().show();
+ }
+
// CHOOSE DATA FOLDER
private void requestPermission() {
@@ -712,7 +837,8 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
List<String> folders = new ArrayList<>(mediaDirs.length);
List<CharSequence> choices = new ArrayList<>(mediaDirs.length);
for(int i=0; i < mediaDirs.length; i++) {
- if(mediaDirs[i] == null) {
+ File dir = mediaDirs[i];
+ if(dir == null || !dir.exists() || !dir.canRead() || !dir.canWrite()) {
continue;
}
String path = mediaDirs[i].getAbsolutePath();
@@ -781,7 +907,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc
checkedItem = ArrayUtils.indexOf(values, currIntervalStr);
}
builder1.setSingleChoiceItems(entries, checkedItem, (dialog1, which1) -> {
- int hours = Integer.valueOf(values[which1]);
+ int hours = Integer.parseInt(values[which1]);
UserPreferences.setUpdateInterval(hours);
dialog1.dismiss();
setUpdateIntervalText();
diff --git a/app/src/main/java/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java b/app/src/main/java/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java
index 665ddc3b5..1075117dd 100644
--- a/app/src/main/java/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java
+++ b/app/src/main/java/de/danoeh/antennapod/receiver/ConnectivityActionReceiver.java
@@ -8,6 +8,7 @@ import android.net.NetworkInfo;
import android.text.TextUtils;
import android.util.Log;
+import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DownloadRequester;
import de.danoeh.antennapod.core.util.NetworkUtils;
@@ -20,7 +21,8 @@ public class ConnectivityActionReceiver extends BroadcastReceiver {
if (TextUtils.equals(intent.getAction(), ConnectivityManager.CONNECTIVITY_ACTION)) {
Log.d(TAG, "Received intent");
- if (NetworkUtils.autodownloadNetworkAvailable()) {
+ ClientConfig.initialize(context);
+ if (NetworkUtils.autodownloadNetworkAvailable()) {
Log.d(TAG, "auto-dl network available, starting auto-download");
DBTasks.autodownloadUndownloadedItems(context);
} else { // if new network is Wi-Fi, finish ongoing downloads,
diff --git a/app/src/main/java/de/danoeh/antennapod/receiver/PlayerWidget.java b/app/src/main/java/de/danoeh/antennapod/receiver/PlayerWidget.java
index 7000827c6..f0d4014ed 100644
--- a/app/src/main/java/de/danoeh/antennapod/receiver/PlayerWidget.java
+++ b/app/src/main/java/de/danoeh/antennapod/receiver/PlayerWidget.java
@@ -1,5 +1,7 @@
package de.danoeh.antennapod.receiver;
+import java.util.Arrays;
+
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
@@ -44,14 +46,14 @@ public class PlayerWidget extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
- Log.d(TAG, "onUpdate() called with: " + "context = [" + context + "], appWidgetManager = [" + appWidgetManager + "], appWidgetIds = [" + 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, "Widet disabled");
+ Log.d(TAG, "Widget disabled");
setEnabled(context, false);
stopUpdate(context);
}
diff --git a/app/src/main/java/de/danoeh/antennapod/receiver/PowerConnectionReceiver.java b/app/src/main/java/de/danoeh/antennapod/receiver/PowerConnectionReceiver.java
index f050e031d..339a4f0f7 100644
--- a/app/src/main/java/de/danoeh/antennapod/receiver/PowerConnectionReceiver.java
+++ b/app/src/main/java/de/danoeh/antennapod/receiver/PowerConnectionReceiver.java
@@ -3,10 +3,9 @@ package de.danoeh.antennapod.receiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.os.BatteryManager;
import android.util.Log;
-import de.danoeh.antennapod.core.BuildConfig;
+import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.storage.DownloadRequester;
@@ -25,6 +24,7 @@ public class PowerConnectionReceiver extends BroadcastReceiver {
Log.d(TAG, "charging intent: " + action);
+ ClientConfig.initialize(context);
if (Intent.ACTION_POWER_CONNECTED.equals(action)) {
Log.d(TAG, "charging, starting auto-download");
// we're plugged in, this is a great time to auto-download if everything else is
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 8201fe3e2..a373c5353 100644
--- a/app/src/main/java/de/danoeh/antennapod/receiver/SPAReceiver.java
+++ b/app/src/main/java/de/danoeh/antennapod/receiver/SPAReceiver.java
@@ -9,8 +9,8 @@ import android.widget.Toast;
import java.util.Arrays;
-import de.danoeh.antennapod.BuildConfig;
import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.ClientConfig;
import de.danoeh.antennapod.core.feed.Feed;
import de.danoeh.antennapod.core.storage.DownloadRequestException;
import de.danoeh.antennapod.core.storage.DownloadRequester;
@@ -27,29 +27,30 @@ public class SPAReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
- if (TextUtils.equals(intent.getAction(), ACTION_SP_APPS_QUERY_FEEDS_REPSONSE)) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Received SP_APPS_QUERY_RESPONSE");
- if (intent.hasExtra(ACTION_SP_APPS_QUERY_FEEDS_REPSONSE_FEEDS_EXTRA)) {
- String[] feedUrls = intent.getStringArrayExtra(ACTION_SP_APPS_QUERY_FEEDS_REPSONSE_FEEDS_EXTRA);
- if (feedUrls != null) {
- if (BuildConfig.DEBUG) Log.d(TAG, "Received feeds list: " + Arrays.toString(feedUrls));
- for (String url : feedUrls) {
- Feed f = new Feed(url, null);
- try {
- DownloadRequester.getInstance().downloadFeed(context, f);
- } catch (DownloadRequestException e) {
- Log.e(TAG, "Error while trying to add feed " + url);
- e.printStackTrace();
- }
- }
- Toast.makeText(context, R.string.sp_apps_importing_feeds_msg, Toast.LENGTH_LONG).show();
-
- } else {
- Log.e(TAG, "Received invalid SP_APPS_QUERY_REPSONSE: extra was null");
- }
- } else {
- Log.e(TAG, "Received invalid SP_APPS_QUERY_RESPONSE: Contains no extra");
+ if (!TextUtils.equals(intent.getAction(), ACTION_SP_APPS_QUERY_FEEDS_REPSONSE)) {
+ return;
+ }
+ Log.d(TAG, "Received SP_APPS_QUERY_RESPONSE");
+ if (!intent.hasExtra(ACTION_SP_APPS_QUERY_FEEDS_REPSONSE_FEEDS_EXTRA)) {
+ Log.e(TAG, "Received invalid SP_APPS_QUERY_RESPONSE: Contains no extra");
+ return;
+ }
+ String[] feedUrls = intent.getStringArrayExtra(ACTION_SP_APPS_QUERY_FEEDS_REPSONSE_FEEDS_EXTRA);
+ if (feedUrls == null) {
+ Log.e(TAG, "Received invalid SP_APPS_QUERY_REPSONSE: extra was null");
+ return;
+ }
+ Log.d(TAG, "Received feeds list: " + Arrays.toString(feedUrls));
+ ClientConfig.initialize(context);
+ for (String url : feedUrls) {
+ Feed f = new Feed(url, null);
+ try {
+ DownloadRequester.getInstance().downloadFeed(context, f);
+ } catch (DownloadRequestException e) {
+ Log.e(TAG, "Error while trying to add feed " + url);
+ e.printStackTrace();
}
}
+ Toast.makeText(context, R.string.sp_apps_importing_feeds_msg, Toast.LENGTH_LONG).show();
}
}
diff --git a/app/src/main/java/de/danoeh/antennapod/view/OnSwipeGesture.java b/app/src/main/java/de/danoeh/antennapod/view/OnSwipeGesture.java
new file mode 100644
index 000000000..eb72a7135
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/view/OnSwipeGesture.java
@@ -0,0 +1,9 @@
+package de.danoeh.antennapod.view;
+
+public interface OnSwipeGesture {
+
+ boolean onSwipeLeftToRight();
+
+ boolean onSwipeRightToLeft();
+
+}
diff --git a/app/src/main/java/de/danoeh/antennapod/view/SquareImageView.java b/app/src/main/java/de/danoeh/antennapod/view/SquareImageView.java
new file mode 100644
index 000000000..27b6ee2bc
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/view/SquareImageView.java
@@ -0,0 +1,32 @@
+package de.danoeh.antennapod.view;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+/**
+ * From http://stackoverflow.com/a/19449488/6839
+ */
+public class SquareImageView extends ImageView {
+
+ public SquareImageView(Context context) {
+ super(context);
+ }
+
+ public SquareImageView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public SquareImageView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ int width = getMeasuredWidth();
+ setMeasuredDimension(width, width);
+ }
+
+} \ No newline at end of file
diff --git a/app/src/main/java/de/danoeh/antennapod/view/SwipeGestureDetector.java b/app/src/main/java/de/danoeh/antennapod/view/SwipeGestureDetector.java
new file mode 100644
index 000000000..f4ee092df
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/view/SwipeGestureDetector.java
@@ -0,0 +1,44 @@
+package de.danoeh.antennapod.view;
+
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+
+public class SwipeGestureDetector extends GestureDetector.SimpleOnGestureListener {
+
+ private static final String TAG = "SwipeGestureDetector";
+
+ private static final int SWIPE_MIN_DISTANCE = 120;
+ private static final int SWIPE_MAX_OFF_PATH = 250;
+ private static final int SWIPE_THRESHOLD_VELOCITY = 200;
+
+ private final OnSwipeGesture callback;
+
+ public SwipeGestureDetector(OnSwipeGesture callback) {
+ this.callback = callback;
+ }
+
+ @Override
+ public boolean onDown(MotionEvent e) {
+ return true;
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ try {
+ if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
+ return false;
+ if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
+ && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
+ return callback.onSwipeRightToLeft();
+ } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
+ && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
+ return callback.onSwipeLeftToRight();
+ }
+ } catch (Exception e) {
+ Log.d(TAG, Log.getStackTraceString(e));
+ }
+ return false;
+ }
+
+}
diff --git a/app/src/main/res/layout/downloadlog_item.xml b/app/src/main/res/layout/downloadlog_item.xml
index 20d879933..7b4773bca 100644
--- a/app/src/main/res/layout/downloadlog_item.xml
+++ b/app/src/main/res/layout/downloadlog_item.xml
@@ -10,14 +10,13 @@
android:paddingBottom="8dp"
tools:background="@android:color/darker_gray">
- <TextView
+ <com.joanzapata.iconify.widget.IconTextView
android:id="@+id/txtvIcon"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:textSize="48sp"
- tools:text="[Icon]"
android:gravity="center" />
<com.joanzapata.iconify.widget.IconButton
diff --git a/app/src/main/res/layout/external_player_fragment.xml b/app/src/main/res/layout/external_player_fragment.xml
index ac55b4c40..fb7abde55 100644
--- a/app/src/main/res/layout/external_player_fragment.xml
+++ b/app/src/main/res/layout/external_player_fragment.xml
@@ -37,6 +37,18 @@
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"/>
+
<TextView
android:id="@+id/txtvTitle"
android:layout_width="wrap_content"
@@ -72,18 +84,6 @@
android:maxLines="1"
tools:text="Episode author 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"
- tools:src="@drawable/ic_play_arrow_white_36dp"/>
-
</RelativeLayout>
</LinearLayout>
diff --git a/app/src/main/res/layout/feeditem_fragment.xml b/app/src/main/res/layout/feeditem_fragment.xml
index c18e5fd6c..a6ce221db 100644
--- a/app/src/main/res/layout/feeditem_fragment.xml
+++ b/app/src/main/res/layout/feeditem_fragment.xml
@@ -31,24 +31,34 @@
android:layout_alignParentStart="true"
android:layout_width="50dp"
android:layout_height="50dp"
+ android:layout_marginRight="16dp"
+ android:layout_marginBottom="16dp"
android:contentDescription="@string/cover_label"
android:gravity="center_vertical"
tools:src="@drawable/ic_stat_antenna_default"
tools:background="@android:color/holo_green_dark" />
<TextView
- android:id="@+id/txtvTitle"
+ android:id="@+id/txtvPodcast"
+ style="@style/AntennaPod.TextView.ListItemSecondaryTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginLeft="16dp"
android:layout_alignTop="@id/imgvCover"
android:layout_toRightOf="@id/imgvCover"
- android:includeFontPadding="false"
+ tools:text="Podcast title"
+ tools:background="@android:color/holo_green_dark" />
+
+ <TextView
+ android:id="@+id/txtvTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/txtvPodcast"
+ android:layout_toRightOf="@id/imgvCover"
android:textSize="16sp"
android:textColor="?android:attr/textColorPrimary"
android:ellipsize="end"
android:maxLines="5"
- tools:text="Podcast title"
+ tools:text="Episode title"
tools:background="@android:color/holo_green_dark" />
<TextView
@@ -58,7 +68,6 @@
android:layout_height="wrap_content"
android:layout_toRightOf="@id/imgvCover"
android:layout_below="@id/txtvTitle"
- android:layout_marginLeft="16dp"
tools:text="00:42:23"
tools:background="@android:color/holo_green_dark"/>
@@ -70,7 +79,7 @@
android:layout_alignParentRight="true"
android:layout_below="@id/txtvTitle"
android:layout_marginLeft="8dp"
- tools:text="Jan\n23"
+ tools:text="Jan 23"
tools:background="@android:color/holo_green_dark" />
</RelativeLayout>
diff --git a/app/src/main/res/layout/fragment_subscriptions.xml b/app/src/main/res/layout/fragment_subscriptions.xml
new file mode 100644
index 000000000..a716cecb6
--- /dev/null
+++ b/app/src/main/res/layout/fragment_subscriptions.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <GridView
+ android:id="@+id/subscriptions_grid"
+ android:layout_width="match_parent"
+ android:numColumns="3"
+ android:horizontalSpacing="2dp"
+ android:verticalSpacing="2dp"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal">
+ </GridView>
+</LinearLayout>
diff --git a/app/src/main/res/layout/audioplayer_activity.xml b/app/src/main/res/layout/mediaplayerinfo_activity.xml
index fb4f995a2..0f68b503e 100644
--- a/app/src/main/res/layout/audioplayer_activity.xml
+++ b/app/src/main/res/layout/mediaplayerinfo_activity.xml
@@ -152,6 +152,21 @@
android:src="?attr/av_fast_forward"
android:textSize="@dimen/text_size_medium"
android:textAllCaps="false"
+ tools:visibility="gone"
+ tools:background="@android:color/holo_green_dark" />
+
+ <ImageButton
+ android:id="@+id/butCastDisconnect"
+ android:layout_width="@dimen/audioplayer_playercontrols_length"
+ android:layout_height="@dimen/audioplayer_playercontrols_length"
+ android:layout_toLeftOf="@id/butRev"
+ android:background="?attr/selectableItemBackground"
+ android:contentDescription="@string/cast_disconnect_label"
+ android:src="?attr/ic_cast_disconnect"
+ android:scaleType="fitCenter"
+ android:visibility="gone"
+ tools:visibility="visible"
+ tools:src="@drawable/ic_cast_disconnect_white_36dp"
tools:background="@android:color/holo_green_dark" />
<ImageButton
diff --git a/app/src/main/res/layout/new_episodes_listitem.xml b/app/src/main/res/layout/new_episodes_listitem.xml
index 0f1e873f3..944711aec 100644
--- a/app/src/main/res/layout/new_episodes_listitem.xml
+++ b/app/src/main/res/layout/new_episodes_listitem.xml
@@ -8,6 +8,7 @@
android:layout_height="wrap_content">
<LinearLayout
+ android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="@dimen/listitem_threeline_height"
android:background="?attr/selectableItemBackground"
diff --git a/app/src/main/res/layout/proxy_settings.xml b/app/src/main/res/layout/proxy_settings.xml
new file mode 100644
index 000000000..983325030
--- /dev/null
+++ b/app/src/main/res/layout/proxy_settings.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:orientation="vertical">
+
+ <TextView
+ android:id="@+id/txtvType"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/proxy_type_label"
+ android:textColor="?android:attr/textColorSecondary" />
+
+ <Spinner
+ android:id="@+id/spType"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:id="@+id/txtvHost"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="@string/host_label"
+ android:textColor="?android:attr/textColorSecondary" />
+
+ <EditText
+ android:id="@+id/etHost"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:inputType="textUri"
+ android:hint="www.example.com" />
+
+ <TextView
+ android:id="@+id/txtvPort"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="@string/port_label"
+ android:textColor="?android:attr/textColorSecondary" />
+
+ <EditText
+ android:id="@+id/etPort"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:hint="8080"
+ android:inputType="number" />
+
+ <TextView
+ android:id="@+id/txtvUsername"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:singleLine="true"
+ android:text="@string/username_label"
+ android:textColor="?android:attr/textColorSecondary" />
+
+ <EditText
+ android:id="@+id/etUsername"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:hint="@string/optional_hint" />
+
+ <TextView
+ android:id="@+id/txtvPassword"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:text="@string/password_label"
+ android:textColor="?android:attr/textColorSecondary" />
+
+ <EditText
+ android:id="@+id/etPassword"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:hint="@string/optional_hint"
+ android:inputType="textPassword" />
+
+ <com.joanzapata.iconify.widget.IconTextView
+ android:id="@+id/txtvMessage"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:visibility="invisible"
+ android:gravity="center"/>
+
+</LinearLayout>
diff --git a/app/src/main/res/layout/statistics_activity.xml b/app/src/main/res/layout/statistics_activity.xml
new file mode 100644
index 000000000..4a72dc7de
--- /dev/null
+++ b/app/src/main/res/layout/statistics_activity.xml
@@ -0,0 +1,41 @@
+<?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:paddingTop="8dp"
+ android:paddingBottom="8dp">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/total_time_listened_to_podcasts"
+ android:gravity="center_horizontal"/>
+
+ <ProgressBar
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/progressBar"
+ android:layout_gravity="center_horizontal"
+ style="?android:attr/progressBarStyleLarge"/>
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/total_time"
+ android:gravity="center_horizontal"
+ android:textSize="45sp"/>
+
+ <ListView
+ android:id="@+id/statistics_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:choiceMode="singleChoice"
+ android:clipToPadding="false"
+ android:divider="@android:color/transparent"
+ android:dividerHeight="0dp"
+ android:paddingBottom="@dimen/list_vertical_padding"
+ android:paddingTop="@dimen/list_vertical_padding"
+ android:scrollbarStyle="outsideOverlay" />
+
+</LinearLayout>
diff --git a/app/src/main/res/layout/statistics_listitem.xml b/app/src/main/res/layout/statistics_listitem.xml
new file mode 100644
index 000000000..20e01bf32
--- /dev/null
+++ b/app/src/main/res/layout/statistics_listitem.xml
@@ -0,0 +1,57 @@
+<?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:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/listitem_iconwithtext_height"
+ android:paddingRight="@dimen/listitem_threeline_verticalpadding"
+ tools:background="@android:color/darker_gray">
+
+ <ImageView
+ android:id="@+id/imgvCover"
+ android:contentDescription="@string/cover_label"
+ android:layout_width="@dimen/thumbnail_length_navlist"
+ android:layout_height="@dimen/thumbnail_length_navlist"
+ android:layout_alignParentLeft="true"
+ android:layout_centerVertical="true"
+ android:adjustViewBounds="true"
+ android:cropToPadding="true"
+ android:scaleType="centerCrop"
+ android:layout_marginTop="4dp"
+ android:layout_marginBottom="4dp"
+ android:layout_marginLeft="@dimen/listitem_icon_leftpadding"
+ tools:src="@drawable/ic_stat_antenna_default"
+ tools:background="@android:color/holo_green_dark"/>
+
+ <TextView
+ android:id="@+id/txtvTime"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/list_vertical_padding"
+ android:lines="1"
+ android:textColor="?android:attr/textColorTertiary"
+ android:textSize="@dimen/text_size_navdrawer"
+ android:layout_alignParentRight="true"
+ android:layout_centerVertical="true"
+ tools:text="23"
+ tools:background="@android:color/holo_green_dark"/>
+
+ <TextView
+ android:id="@+id/txtvTitle"
+ android:lines="1"
+ android:ellipsize="end"
+ android:singleLine="true"
+ android:layout_centerVertical="true"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="@dimen/text_size_navdrawer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/listitem_iconwithtext_textleftpadding"
+ android:layout_toRightOf="@id/imgvCover"
+ android:layout_toLeftOf="@id/txtvTime"
+ android:layout_alignWithParentIfMissing="true"
+ tools:text="Navigation feed item title"
+ tools:background="@android:color/holo_green_dark"/>
+
+
+</RelativeLayout>
diff --git a/app/src/main/res/layout/subscription_item.xml b/app/src/main/res/layout/subscription_item.xml
new file mode 100644
index 000000000..19b9943e4
--- /dev/null
+++ b/app/src/main/res/layout/subscription_item.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
+
+ <de.danoeh.antennapod.view.SquareImageView
+ android:id="@+id/imgvCover"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:scaleType="centerCrop"
+ tools:src="@drawable/ic_launcher" />
+
+ <com.joanzapata.iconify.widget.IconTextView
+ android:id="@+id/txtvTitle"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:ellipsize="end"
+ android:gravity="center"
+ android:background="@color/light_gray"
+ tools:text="@string/app_name" />
+
+ <jp.shts.android.library.TriangleLabelView
+ android:id="@+id/triangleCountView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ app:backgroundColor="@color/antennapod_blue"
+ app:corner="rightTop"
+ app:primaryText="Test"
+ app:primaryTextColor="@color/white"
+ app:primaryTextSize="12sp"
+ android:layout_gravity="right|top"/>
+
+</FrameLayout>
diff --git a/app/src/main/res/layout/videoplayer_activity.xml b/app/src/main/res/layout/videoplayer_activity.xml
index 2e1097fb8..4db663e19 100644
--- a/app/src/main/res/layout/videoplayer_activity.xml
+++ b/app/src/main/res/layout/videoplayer_activity.xml
@@ -32,7 +32,7 @@
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:background="@drawable/overlay_button_circle_background"
- android:contentDescription="@string/pause_label"
+ android:contentDescription="@string/rewind_label"
android:src="@drawable/ic_av_rewind_80dp" />
<ImageButton
@@ -50,7 +50,7 @@
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:background="@drawable/overlay_button_circle_background"
- android:contentDescription="@string/pause_label"
+ android:contentDescription="@string/fast_forward_label"
android:src="@drawable/ic_av_fast_forward_80dp" />
</LinearLayout>
diff --git a/app/src/main/res/menu/cast_enabled.xml b/app/src/main/res/menu/cast_enabled.xml
new file mode 100644
index 000000000..d6e85c311
--- /dev/null
+++ b/app/src/main/res/menu/cast_enabled.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:custom="http://schemas.android.com/apk/res-auto">
+
+ <item
+ android:id="@+id/media_route_menu_item"
+ android:title="@string/cast_media_route_menu_title"
+ custom:actionProviderClass="de.danoeh.antennapod.core.cast.SwitchableMediaRouteActionProvider"
+ custom:showAsAction="ifRoom"/>
+</menu> \ No newline at end of file
diff --git a/app/src/main/res/menu/feeditem_options.xml b/app/src/main/res/menu/feeditem_options.xml
index 898081486..511758c2e 100644
--- a/app/src/main/res/menu/feeditem_options.xml
+++ b/app/src/main/res/menu/feeditem_options.xml
@@ -93,4 +93,10 @@
android:title="@string/support_label">
</item>
-</menu> \ No newline at end of file
+ <item
+ android:id="@+id/open_podcast"
+ custom:showAsAction="collapseActionView"
+ android:title="@string/open_podcast">
+ </item>
+
+</menu>
diff --git a/app/src/main/res/menu/opml_selection_options.xml b/app/src/main/res/menu/opml_selection_options.xml
new file mode 100644
index 000000000..26d2a0519
--- /dev/null
+++ b/app/src/main/res/menu/opml_selection_options.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:custom="http://schemas.android.com/apk/res-auto">
+
+ <item
+ android:id="@id/select_all_item"
+ android:icon="?attr/ic_check_box_outline"
+ android:title="@string/select_all_label"
+ custom:showAsAction="ifRoom">
+ </item>
+
+ <item
+ android:id="@id/deselect_all_item"
+ android:icon="?attr/ic_check_box"
+ android:title="@string/deselect_all_label"
+ custom:showAsAction="ifRoom">
+ </item>
+
+</menu>
diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml
index 3ecd79b1e..57829e3e1 100644
--- a/app/src/main/res/xml/preferences.xml
+++ b/app/src/main/res/xml/preferences.xml
@@ -49,6 +49,10 @@
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"
@@ -185,7 +189,7 @@
android:title="@string/pref_automatic_download_title"
android:defaultValue="false"/>
<com.afollestad.materialdialogs.prefs.MaterialListPreference
- android:defaultValue="20"
+ android:defaultValue="25"
android:entries="@array/episode_cache_size_entries"
android:key="prefEpisodeCacheSize"
android:title="@string/pref_episode_cache_title"
@@ -200,8 +204,11 @@
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>
@@ -240,6 +247,10 @@
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_title"
+ android:summary="@string/pref_gpodnet_sync_sum"/>
+ <Preference
android:key="pref_gpodnet_logout"
android:title="@string/pref_gpodnet_logout_title"/>
<Preference
@@ -247,7 +258,7 @@
android:title="@string/pref_gpodnet_sethostname_title"/>
</PreferenceScreen>
</PreferenceCategory>
- <PreferenceCategory android:title="@string/other_pref">
+ <PreferenceCategory android:title="@string/storage_pref">
<Preference
android:title="@string/choose_data_directory"
android:key="prefChooseDataDir"/>
@@ -258,16 +269,38 @@
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="prefAbout"
- android:title="@string/about_pref"/>
+ android:key="statistics"
+ android:title="@string/statistics_label"/>
+ </PreferenceCategory>
+ <PreferenceCategory android:title="@string/project_pref">
+ <Preference
+ android:key="prefFaq"
+ android:title="@string/pref_faq"/>
+ <Preference
+ android:key="prefKnownIssues"
+ android:title="@string/pref_known_issues"/>
<Preference
android:key="prefSendCrashReport"
android:title="@string/crash_report_title"
android:summary="@string/crash_report_sum"/>
+ <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"/>
</PreferenceCategory>
</PreferenceScreen>
diff --git a/app/src/main/templates/about.html b/app/src/main/templates/about.html
index 222429b17..5c7a3cbd0 100644
--- a/app/src/main/templates/about.html
+++ b/app/src/main/templates/about.html
@@ -100,6 +100,9 @@ licensed under the Apache 2.0 license <a href="LICENSE_APACHE-2.0.txt">(View)</a
<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>
+<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>
+
<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>